SkCanvas.cpp revision 713b8ef3748609ee20f6005a66d6aafd02aab4b6
18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2008 The Android Open Source Project
38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
873fe7b07e6391da81dfc48d600d7b3141be1f471Herb Derby#include "SkArenaAlloc.h"
9986480a71f4e860663ced7ad90a1fe346a164afbMike Reed#include "SkBitmapDevice.h"
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
11d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed#include "SkCanvasPriv.h"
12d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkClipStack.h"
13dbc3cefb0b624808ddb86d444e6103f216e12fa5reed#include "SkColorFilter.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h"
153cb3840c9af6f70896cf5565a38d4ee03c02d767reed#include "SkDrawable.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawFilter.h"
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawLooper.h"
18b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr#include "SkImage.h"
19262a71b7f95ce98ff3dd8dba845afbd724470903reed#include "SkImage_Base.h"
20900c36779610dc65c42a5004ee3693fd70961ba4senorblanco#include "SkImageFilter.h"
21900c36779610dc65c42a5004ee3693fd70961ba4senorblanco#include "SkImageFilterCache.h"
22c573a40ed5024b463e47088d307e3164a486dba5msarett#include "SkLatticeIter.h"
235df4934b3e40cdc378e225d1dda39f015cae9baeMike Reed#include "SkMakeUnique.h"
24262a71b7f95ce98ff3dd8dba845afbd724470903reed#include "SkMatrixUtils.h"
2574bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org#include "SkMetaData.h"
26ee424acbb87bf999be132a437527e656e37541d7Florin Malita#include "SkNoDrawCanvas.h"
27fbfa25802709139c2f14e304319c9541da65ca27msarett#include "SkNx.h"
28c83a29759a5c2966da5ab973e4fd90763e4c962breed#include "SkPaintPriv.h"
29b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkPatchUtils.h"
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPicture.h"
31b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack#include "SkRadialShadowMapShader.h"
320017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com#include "SkRasterClip.h"
33356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed#include "SkRasterHandleAllocator.h"
344ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com#include "SkRRect.h"
35904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack#include "SkShadowPaintFilterCanvas.h"
36904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack#include "SkShadowShader.h"
374418dbac3386f26c8da62ab242be9c178961eb18robertphillips#include "SkSpecialImage.h"
3897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com#include "SkSurface_Base.h"
397ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita#include "SkTextBlob.h"
4052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com#include "SkTextFormatParams.h"
41a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com#include "SkTLazy.h"
428f757f540a8378c7b1354aab3d4650eaa920b17adanakj#include "SkTraceEvent.h"
43d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include <new>
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
45644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
467354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips#include "GrContext.h"
47644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#include "GrRenderTarget.h"
483b65598bceb65736486db27ed49a56d787032747Brian Osman#include "SkGr.h"
49e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack
50644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
51ebfce6d9b42198e04288a15953f40c395a7b6139Mike Reed#include "SkClipOpPriv.h"
52199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon#include "SkVertices.h"
53644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
54e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed#define RETURN_ON_NULL(ptr)     do { if (nullptr == (ptr)) return; } while (0)
55e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed
56139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reedclass SkNoPixelsDevice : public SkBaseDevice {
57139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reedpublic:
58139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    SkNoPixelsDevice(const SkIRect& bounds, const SkSurfaceProps& props)
59139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed        : SkBaseDevice(SkImageInfo::MakeUnknown(bounds.width(), bounds.height()), props)
60566e53c7003920ff45c72498754060804b657c68Mike Reed    {
61e393a629491e9a52dd6662983d2bfd424541957eMike Reed        // this fails if we enable this assert: DiscardableImageMapTest.GetDiscardableImagesInRectMaxImage
62e393a629491e9a52dd6662983d2bfd424541957eMike Reed        //SkASSERT(bounds.width() >= 0 && bounds.height() >= 0);
63566e53c7003920ff45c72498754060804b657c68Mike Reed    }
64139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed
65139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void resetForNextPicture(const SkIRect& bounds) {
66e393a629491e9a52dd6662983d2bfd424541957eMike Reed        //SkASSERT(bounds.width() >= 0 && bounds.height() >= 0);
67139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed        this->privateResize(bounds.width(), bounds.height());
68139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    }
69139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed
70139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reedprotected:
71139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    // We don't track the clip at all (for performance), but we have to respond to some queries.
72139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    // We pretend to be wide-open. We could pretend to always be empty, but that *seems* worse.
73139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void onSave() override {}
74139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void onRestore() override {}
75139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void onClipRect(const SkRect& rect, SkClipOp, bool aa) override {}
76139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) override {}
77139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void onClipPath(const SkPath& path, SkClipOp, bool aa) override {}
78139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void onClipRegion(const SkRegion& deviceRgn, SkClipOp) override {}
79139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void onSetDeviceClipRestriction(SkIRect* mutableClipRestriction) override {}
80139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    bool onClipIsAA() const override { return false; }
81139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void onAsRgnClip(SkRegion* rgn) const override {
82139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed        rgn->setRect(SkIRect::MakeWH(this->width(), this->height()));
83139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    }
84139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    ClipType onGetClipType() const override {
85139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed        return kRect_ClipType;
86139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    }
87139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed
88139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawPaint(const SkPaint& paint) override {}
89139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawPoints(SkCanvas::PointMode, size_t, const SkPoint[], const SkPaint&) override {}
90139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawRect(const SkRect&, const SkPaint&) override {}
91139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawOval(const SkRect&, const SkPaint&) override {}
92139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawRRect(const SkRRect&, const SkPaint&) override {}
93139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawPath(const SkPath&, const SkPaint&, const SkMatrix*, bool) override {}
94139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawBitmap(const SkBitmap&, const SkMatrix&, const SkPaint&) override {}
95139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawSprite(const SkBitmap&, int, int, const SkPaint&) override {}
96139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint&,
97139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed                        SkCanvas::SrcRectConstraint) override {}
98139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawText(const void*, size_t, SkScalar, SkScalar, const SkPaint&) override {}
99139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawPosText(const void*, size_t, const SkScalar[], int, const SkPoint&,
100139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed                     const SkPaint&) override {}
101139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawDevice(SkBaseDevice*, int, int, const SkPaint&) override {}
1022f6b5a47a50cdd218bc3302273be3a4a71add8fbMike Reed    void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) override {}
103139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed
104139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reedprivate:
105139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    typedef SkBaseDevice INHERITED;
106139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed};
107139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed
108139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed///////////////////////////////////////////////////////////////////////////////////////////////////
109139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed
110c83a29759a5c2966da5ab973e4fd90763e4c962breed/*
111c83a29759a5c2966da5ab973e4fd90763e4c962breed *  Return true if the drawing this rect would hit every pixels in the canvas.
112c83a29759a5c2966da5ab973e4fd90763e4c962breed *
113c83a29759a5c2966da5ab973e4fd90763e4c962breed *  Returns false if
114c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - rect does not contain the canvas' bounds
115c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - paint is not fill
116c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - paint would blur or otherwise change the coverage of the rect
117c83a29759a5c2966da5ab973e4fd90763e4c962breed */
118c83a29759a5c2966da5ab973e4fd90763e4c962breedbool SkCanvas::wouldOverwriteEntireSurface(const SkRect* rect, const SkPaint* paint,
119c83a29759a5c2966da5ab973e4fd90763e4c962breed                                           ShaderOverrideOpacity overrideOpacity) const {
12099fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert((int)SkPaintPriv::kNone_ShaderOverrideOpacity ==
12199fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  (int)kNone_ShaderOverrideOpacity,
12299fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  "need_matching_enums0");
12399fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert((int)SkPaintPriv::kOpaque_ShaderOverrideOpacity ==
12499fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  (int)kOpaque_ShaderOverrideOpacity,
12599fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  "need_matching_enums1");
12699fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert((int)SkPaintPriv::kNotOpaque_ShaderOverrideOpacity ==
12799fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  (int)kNotOpaque_ShaderOverrideOpacity,
12899fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  "need_matching_enums2");
129c83a29759a5c2966da5ab973e4fd90763e4c962breed
130c83a29759a5c2966da5ab973e4fd90763e4c962breed    const SkISize size = this->getBaseLayerSize();
131c83a29759a5c2966da5ab973e4fd90763e4c962breed    const SkRect bounds = SkRect::MakeIWH(size.width(), size.height());
132a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
133a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    // if we're clipped at all, we can't overwrite the entire surface
134a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    {
135a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        SkBaseDevice* base = this->getDevice();
136a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        SkBaseDevice* top = this->getTopDevice();
137a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        if (base != top) {
138a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            return false;   // we're in a saveLayer, so conservatively don't assume we'll overwrite
139a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        }
140a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        if (!base->clipIsWideOpen()) {
141a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            return false;
142a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        }
143c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
144c83a29759a5c2966da5ab973e4fd90763e4c962breed
145c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (rect) {
146c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary        if (!this->getTotalMatrix().isScaleTranslate()) {
147c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false; // conservative
148c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
149c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary
150c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary        SkRect devRect;
151c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary        this->getTotalMatrix().mapRectScaleTranslate(&devRect, *rect);
152c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary        if (!devRect.contains(bounds)) {
153c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false;
154c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
155c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
156c83a29759a5c2966da5ab973e4fd90763e4c962breed
157c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (paint) {
158c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkPaint::Style paintStyle = paint->getStyle();
159c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (!(paintStyle == SkPaint::kFill_Style ||
160c83a29759a5c2966da5ab973e4fd90763e4c962breed              paintStyle == SkPaint::kStrokeAndFill_Style)) {
161c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false;
162c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
163c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (paint->getMaskFilter() || paint->getLooper()
164c83a29759a5c2966da5ab973e4fd90763e4c962breed            || paint->getPathEffect() || paint->getImageFilter()) {
165c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false; // conservative
166c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
167c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
168c83a29759a5c2966da5ab973e4fd90763e4c962breed    return SkPaintPriv::Overwrites(paint, (SkPaintPriv::ShaderOverrideOpacity)overrideOpacity);
169c83a29759a5c2966da5ab973e4fd90763e4c962breed}
170c83a29759a5c2966da5ab973e4fd90763e4c962breed
171c83a29759a5c2966da5ab973e4fd90763e4c962breed///////////////////////////////////////////////////////////////////////////////////////////////////
172c83a29759a5c2966da5ab973e4fd90763e4c962breed
173d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedstatic bool gIgnoreSaveLayerBounds;
174d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedvoid SkCanvas::Internal_Private_SetIgnoreSaveLayerBounds(bool ignore) {
175d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    gIgnoreSaveLayerBounds = ignore;
176d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed}
177d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedbool SkCanvas::Internal_Private_GetIgnoreSaveLayerBounds() {
178d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    return gIgnoreSaveLayerBounds;
179d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed}
180d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed
1810acf1b4b3645772d220c720313821bac389751b5reedstatic bool gTreatSpriteAsBitmap;
1820acf1b4b3645772d220c720313821bac389751b5reedvoid SkCanvas::Internal_Private_SetTreatSpriteAsBitmap(bool spriteAsBitmap) {
1830acf1b4b3645772d220c720313821bac389751b5reed    gTreatSpriteAsBitmap = spriteAsBitmap;
1840acf1b4b3645772d220c720313821bac389751b5reed}
1850acf1b4b3645772d220c720313821bac389751b5reedbool SkCanvas::Internal_Private_GetTreatSpriteAsBitmap() {
1860acf1b4b3645772d220c720313821bac389751b5reed    return gTreatSpriteAsBitmap;
1870acf1b4b3645772d220c720313821bac389751b5reed}
1880acf1b4b3645772d220c720313821bac389751b5reed
189da17f758442f16747af39f8fbaed9c097048519creed@google.com// experimental for faster tiled drawing...
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define SK_TRACE_SAVERESTORE
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_TRACE_SAVERESTORE
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gLayerCounter;
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gRecCounter;
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gCanvasCounter;
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_layer()
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_layer()
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_rec()
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_rec()
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_canvas()
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_canvas()
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2132c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.orgtypedef SkTLazy<SkPaint> SkLazyPaint;
2142c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org
215c83a29759a5c2966da5ab973e4fd90763e4c962breedvoid SkCanvas::predrawNotify(bool willOverwritesEntireSurface) {
21697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    if (fSurfaceBase) {
217c83a29759a5c2966da5ab973e4fd90763e4c962breed        fSurfaceBase->aboutToDraw(willOverwritesEntireSurface
218c83a29759a5c2966da5ab973e4fd90763e4c962breed                                  ? SkSurface::kDiscard_ContentChangeMode
219c83a29759a5c2966da5ab973e4fd90763e4c962breed                                  : SkSurface::kRetain_ContentChangeMode);
220c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
221c83a29759a5c2966da5ab973e4fd90763e4c962breed}
222c83a29759a5c2966da5ab973e4fd90763e4c962breed
223c83a29759a5c2966da5ab973e4fd90763e4c962breedvoid SkCanvas::predrawNotify(const SkRect* rect, const SkPaint* paint,
224c83a29759a5c2966da5ab973e4fd90763e4c962breed                             ShaderOverrideOpacity overrideOpacity) {
225c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (fSurfaceBase) {
226c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkSurface::ContentChangeMode mode = SkSurface::kRetain_ContentChangeMode;
227c83a29759a5c2966da5ab973e4fd90763e4c962breed        // Since willOverwriteAllPixels() may not be complete free to call, we only do so if
228c83a29759a5c2966da5ab973e4fd90763e4c962breed        // there is an outstanding snapshot, since w/o that, there will be no copy-on-write
229c83a29759a5c2966da5ab973e4fd90763e4c962breed        // and therefore we don't care which mode we're in.
230c83a29759a5c2966da5ab973e4fd90763e4c962breed        //
231c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (fSurfaceBase->outstandingImageSnapshot()) {
232c83a29759a5c2966da5ab973e4fd90763e4c962breed            if (this->wouldOverwriteEntireSurface(rect, paint, overrideOpacity)) {
233c83a29759a5c2966da5ab973e4fd90763e4c962breed                mode = SkSurface::kDiscard_ContentChangeMode;
234c83a29759a5c2966da5ab973e4fd90763e4c962breed            }
235c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
236c83a29759a5c2966da5ab973e4fd90763e4c962breed        fSurfaceBase->aboutToDraw(mode);
23797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    }
23897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com}
23997af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2421f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com/*  This is the record we keep for each SkBaseDevice that the user installs.
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The clip/matrix/proc are fields that reflect the top of the save/restore
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stack. Whenever the canvas changes, it marks a dirty flag, and then before
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    these are used (assuming we're not on a layer) we rebuild these cache
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    values: they reflect the top of the save stack, but translated and clipped
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    by the device's XY offset and bitmap-bounds.
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct DeviceCM {
250713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    DeviceCM*                      fNext;
251713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    sk_sp<SkBaseDevice>            fDevice;
252713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    SkRasterClip                   fClip;
253713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    std::unique_ptr<const SkPaint> fPaint; // may be null (in the future)
254713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    SkMatrix                       fStashedMatrix; // original CTM; used by imagefilter in saveLayer
255713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita
256713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    DeviceCM(sk_sp<SkBaseDevice> device, const SkPaint* paint, const SkMatrix& stashed)
25796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        : fNext(nullptr)
258713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita        , fDevice(std::move(device))
259713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita        , fPaint(paint ? skstd::make_unique<SkPaint>(*paint) : nullptr)
2608c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        , fStashedMatrix(stashed)
261713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    {}
2624b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
263feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    void reset(const SkIRect& bounds) {
264feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(!fPaint);
265feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(!fNext);
266feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fDevice);
267feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fClip.setRect(bounds);
268feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    }
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  This is the record we keep for each save/restore level in the stack.
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Since a level optionally copies the matrix and/or stack, we have pointers
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for these fields. If the value is copied for this level, the copy is
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stored in the ...Storage field, and the pointer points to that. If the
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    value is not copied for this level, we ignore ...Storage, and just point
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    at the corresponding value in the previous level in the stack.
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkCanvas::MCRec {
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2801f836ee096bb988adef4b9757b2629c7afeda36dreed    SkDrawFilter*   fFilter;    // the current filter (or null)
281d954498c01ccf0417feacf89e45d0c62a06a813breed    DeviceCM*       fLayer;
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  If there are any layers in the stack, this points to the top-most
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        one that is at or below this level in the stack (so we know what
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bitmap/device to draw into from this level. This value is NOT
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reference counted, since the real owner is either our fLayer field,
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        or a previous one in a lower level.)
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
288a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    DeviceCM*           fTopLayer;
289a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    SkConservativeClip  fRasterClip;
290a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    SkMatrix            fMatrix;
291a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    int                 fDeferredSaveCount;
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
293e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    // This is the current cumulative depth (aggregate of all done translateZ calls)
294e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    SkScalar        fCurDrawDepth;
295e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack
296a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    MCRec() {
29796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fFilter     = nullptr;
29896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fLayer      = nullptr;
29996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fTopLayer   = nullptr;
3002ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fMatrix.reset();
3012ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fDeferredSaveCount = 0;
302e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack        fCurDrawDepth      = 0;
303b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
304d954498c01ccf0417feacf89e45d0c62a06a813breed        // don't bother initializing fNext
305d954498c01ccf0417feacf89e45d0c62a06a813breed        inc_rec();
306d954498c01ccf0417feacf89e45d0c62a06a813breed    }
307e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix),
308e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack                               fCurDrawDepth(prev.fCurDrawDepth) {
309d954498c01ccf0417feacf89e45d0c62a06a813breed        fFilter = SkSafeRef(prev.fFilter);
31096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fLayer = nullptr;
311d954498c01ccf0417feacf89e45d0c62a06a813breed        fTopLayer = prev.fTopLayer;
3122ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fDeferredSaveCount = 0;
313b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // don't bother initializing fNext
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inc_rec();
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~MCRec() {
31882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        SkSafeUnref(fFilter);
319385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        delete fLayer;
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dec_rec();
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
322feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
323feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    void reset(const SkIRect& bounds) {
324feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fLayer);
325feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fDeferredSaveCount == 0);
326feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
327feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fMatrix.reset();
328feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fRasterClip.setRect(bounds);
329feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fLayer->reset(bounds);
330feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    }
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
333a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedclass SkDrawIter {
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
335a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    SkDrawIter(SkCanvas* canvas)
336a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        : fDevice(nullptr), fCurrLayer(canvas->fMCRec->fTopLayer), fPaint(nullptr)
337a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    {}
3384b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool next() {
340f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        const DeviceCM* rec = fCurrLayer;
341f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        if (rec && rec->fDevice) {
342713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita            fDevice = rec->fDevice.get();
343713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita            fPaint  = rec->fPaint.get();
3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fCurrLayer = rec->fNext;
34596fcdcc219d2a0d3579719b84b28bede76efba64halcanary            // fCurrLayer may be nullptr now
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3504b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3516f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getX() const { return fDevice->getOrigin().x(); }
3526f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getY() const { return fDevice->getOrigin().y(); }
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* getPaint() const { return fPaint; }
3546f8f292aa768869a9e85c314b124875f57504f2creed@google.com
35599330ba6227137866a0dbd63478d36f335203ebdMike Reed    SkBaseDevice*   fDevice;
35699330ba6227137866a0dbd63478d36f335203ebdMike Reed
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const DeviceCM* fCurrLayer;
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint*  fPaint;     // May be null.
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
362713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita#define FOR_EACH_TOP_DEVICE( code )                       \
363713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    do {                                                  \
364713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita        DeviceCM* layer = fMCRec->fTopLayer;              \
365713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita        while (layer) {                                   \
366713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita            SkBaseDevice* device = layer->fDevice.get();  \
367713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita            if (device) {                                 \
368713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita                code;                                     \
369713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita            }                                             \
370713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita            layer = layer->fNext;                         \
371713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita        }                                                 \
3727627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    } while (0)
3737627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
376dbc3cefb0b624808ddb86d444e6103f216e12fa5reedstatic SkPaint* set_if_needed(SkLazyPaint* lazy, const SkPaint& orig) {
377dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    return lazy->isValid() ? lazy->get() : lazy->set(orig);
378dbc3cefb0b624808ddb86d444e6103f216e12fa5reed}
379dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
380dbc3cefb0b624808ddb86d444e6103f216e12fa5reed/**
381dbc3cefb0b624808ddb86d444e6103f216e12fa5reed *  If the paint has an imagefilter, but it can be simplified to just a colorfilter, return that
38296fcdcc219d2a0d3579719b84b28bede76efba64halcanary *  colorfilter, else return nullptr.
383dbc3cefb0b624808ddb86d444e6103f216e12fa5reed */
384d053ce9c54d4e5937a142278359e5a4cde18095ereedstatic sk_sp<SkColorFilter> image_to_color_filter(const SkPaint& paint) {
385dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkImageFilter* imgf = paint.getImageFilter();
386dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    if (!imgf) {
38796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
388dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
389dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
390d053ce9c54d4e5937a142278359e5a4cde18095ereed    SkColorFilter* imgCFPtr;
391d053ce9c54d4e5937a142278359e5a4cde18095ereed    if (!imgf->asAColorFilter(&imgCFPtr)) {
39296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
393dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
394d053ce9c54d4e5937a142278359e5a4cde18095ereed    sk_sp<SkColorFilter> imgCF(imgCFPtr);
395dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
396dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkColorFilter* paintCF = paint.getColorFilter();
39796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paintCF) {
398dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        // there is no existing paint colorfilter, so we can just return the imagefilter's
399dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        return imgCF;
400dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
401dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
402dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    // The paint has both a colorfilter(paintCF) and an imagefilter-which-is-a-colorfilter(imgCF)
403dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    // and we need to combine them into a single colorfilter.
404d053ce9c54d4e5937a142278359e5a4cde18095ereed    return SkColorFilter::MakeComposeFilter(std::move(imgCF), sk_ref_sp(paintCF));
405dbc3cefb0b624808ddb86d444e6103f216e12fa5reed}
406dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
40787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco/**
40887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * There are many bounds in skia. A circle's bounds is just its center extended by its radius.
40987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * However, if we stroke a circle, then the "bounds" of that is larger, since it will now draw
41087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * outside of its raw-bounds by 1/2 the stroke width.  SkPaint has lots of optional
41187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * effects/attributes that can modify the effective bounds of a given primitive -- maskfilters,
41287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * patheffects, stroking, etc.  This function takes a raw bounds and a paint, and returns the
41387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * conservative "effective" bounds based on the settings in the paint... with one exception. This
41487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * function does *not* look at the imagefilter, which can also modify the effective bounds. It is
41587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * deliberately ignored.
41687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco */
41787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblancostatic const SkRect& apply_paint_to_bounds_sans_imagefilter(const SkPaint& paint,
41887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                                                            const SkRect& rawBounds,
41987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                                                            SkRect* storage) {
42087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    SkPaint tmpUnfiltered(paint);
42187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    tmpUnfiltered.setImageFilter(nullptr);
42287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    if (tmpUnfiltered.canComputeFastBounds()) {
42387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        return tmpUnfiltered.computeFastBounds(rawBounds, storage);
42487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    } else {
42587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        return rawBounds;
42687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    }
42787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco}
42887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco
4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper {
4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
43187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    // "rawBounds" is the original bounds of the primitive about to be drawn, unmodified by the
43287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    // paint. It's used to determine the size of the offscreen layer for filters.
43387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    // If null, the clip will be used instead.
4343aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint, bool skipLayerForImageFilter = false,
43587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                   const SkRect* rawBounds = nullptr) : fOrigPaint(paint) {
4364e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fCanvas = canvas;
43753d9f1cfbd5ddbf57c2f22b9e613ce48e5b2896cfmalita#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFilter = canvas->getDrawFilter();
4397765000709dc64eb23be7df47d1f995d1f787115fmalita#else
4407765000709dc64eb23be7df47d1f995d1f787115fmalita        fFilter = nullptr;
4417765000709dc64eb23be7df47d1f995d1f787115fmalita#endif
4424a8126e7f81384526629b1e21bf89b632ea13cd9reed        fPaint = &fOrigPaint;
4434e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fSaveCount = canvas->getSaveCount();
4445c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        fTempLayerForImageFilter = false;
4454e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = false;
4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
447d053ce9c54d4e5937a142278359e5a4cde18095ereed        auto simplifiedCF = image_to_color_filter(fOrigPaint);
448dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        if (simplifiedCF) {
449dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
450d053ce9c54d4e5937a142278359e5a4cde18095ereed            paint->setColorFilter(std::move(simplifiedCF));
45196fcdcc219d2a0d3579719b84b28bede76efba64halcanary            paint->setImageFilter(nullptr);
452dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            fPaint = paint;
453dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        }
454dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
455dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        if (!skipLayerForImageFilter && fPaint->getImageFilter()) {
4565c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            /**
4575c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  We implement ImageFilters for a given draw by creating a layer, then applying the
4585c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  imagefilter to the pixels of that layer (its backing surface/image), and then
4595c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  we call restore() to xfer that layer to the main canvas.
4605c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *
4615c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  1. SaveLayer (with a paint containing the current imagefilter and xfermode)
4625c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  2. Generate the src pixels:
4635c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      Remove the imagefilter and the xfermode from the paint that we (AutoDrawLooper)
4645c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      return (fPaint). We then draw the primitive (using srcover) into a cleared
4655c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      buffer/surface.
4665c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  3. Restore the layer created in #1
4675c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      The imagefilter is passed the buffer/surface from the layer (now filled with the
4685c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      src pixels of the primitive). It returns a new "filtered" buffer, which we
4695c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      draw onto the previous layer using the xfermode from the original paint.
4705c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             */
4718926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkPaint tmp;
472693fdbd6b81a860657612e7604430dd55d6e721bMike Reed            tmp.setImageFilter(fPaint->refImageFilter());
473374772bd61951f01bf84fe17bf53d8867681c9aereed            tmp.setBlendMode(fPaint->getBlendMode());
47487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            SkRect storage;
47587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            if (rawBounds) {
47687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                // Make rawBounds include all paint outsets except for those due to image filters.
47787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                rawBounds = &apply_paint_to_bounds_sans_imagefilter(*fPaint, *rawBounds, &storage);
47887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            }
479bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed            (void)canvas->internalSaveLayer(SkCanvas::SaveLayerRec(rawBounds, &tmp),
48076033be81b82c44fd5d4fdf2672eb22e505da1f0reed                                            SkCanvas::kFullLayer_SaveLayerStrategy);
4815c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            fTempLayerForImageFilter = true;
4825c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            // we remove the imagefilter/xfermode inside doNext()
4838926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
4848926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
48579fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (SkDrawLooper* looper = paint.getLooper()) {
48673fe7b07e6391da81dfc48d600d7b3141be1f471Herb Derby            fLooperContext = looper->makeContext(canvas, &fAlloc);
487129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fIsSimple = false;
488129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
48996fcdcc219d2a0d3579719b84b28bede76efba64halcanary            fLooperContext = nullptr;
490129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // can we be marked as simple?
4915c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            fIsSimple = !fFilter && !fTempLayerForImageFilter;
4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
49474b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
4954e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    ~AutoDrawLooper() {
4965c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        if (fTempLayerForImageFilter) {
4978926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            fCanvas->internalRestore();
4988926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
4994e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fCanvas->getSaveCount() == fSaveCount);
5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
50174b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
5024e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    const SkPaint& paint() const {
5034e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fPaint);
5044e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return *fPaint;
5054e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
50674b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
507129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool next(SkDrawFilter::Type drawType) {
508129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        if (fDone) {
509129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return false;
510129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else if (fIsSimple) {
511129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fDone = true;
512129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return !fPaint->nothingToDraw();
513129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
514129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return this->doNext(drawType);
515129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        }
516fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
51774b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
51973fe7b07e6391da81dfc48d600d7b3141be1f471Herb Derby    SkLazyPaint     fLazyPaintInit;       // base paint storage in case we need to modify it
520dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkLazyPaint     fLazyPaintPerLooper;  // per-draw-looper storage, so the looper can modify it
5212c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkCanvas*       fCanvas;
5222c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint&  fOrigPaint;
5232c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkDrawFilter*   fFilter;
5242c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
5252c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    int             fSaveCount;
5265c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    bool            fTempLayerForImageFilter;
5272c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    bool            fDone;
528129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool            fIsSimple;
52979fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkDrawLooper::Context* fLooperContext;
53073fe7b07e6391da81dfc48d600d7b3141be1f471Herb Derby    char            fStorage[48];
53173fe7b07e6391da81dfc48d600d7b3141be1f471Herb Derby    SkArenaAlloc    fAlloc {fStorage};
532129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com
533129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool doNext(SkDrawFilter::Type drawType);
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
536129ec22cb054592261e001294c430c9dd4e90ff4reed@google.combool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
53796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fPaint = nullptr;
538129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkASSERT(!fIsSimple);
5395c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    SkASSERT(fLooperContext || fFilter || fTempLayerForImageFilter);
540632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com
541dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkPaint* paint = fLazyPaintPerLooper.set(fLazyPaintInit.isValid() ?
542dbc3cefb0b624808ddb86d444e6103f216e12fa5reed                                             *fLazyPaintInit.get() : fOrigPaint);
5438926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
5445c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    if (fTempLayerForImageFilter) {
54596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        paint->setImageFilter(nullptr);
546374772bd61951f01bf84fe17bf53d8867681c9aereed        paint->setBlendMode(SkBlendMode::kSrcOver);
547129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
5488926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
54979fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
550129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        fDone = true;
551129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        return false;
552129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
553129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fFilter) {
554971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        if (!fFilter->filter(paint, drawType)) {
555971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            fDone = true;
556971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            return false;
557971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        }
55896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == fLooperContext) {
559129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // no looper means we only draw once
560632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com            fDone = true;
561632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com        }
562129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
563129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    fPaint = paint;
5648926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
565129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    // if we only came in here for the imagefilter, mark us as done
56679fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (!fLooperContext && !fFilter) {
5674e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = true;
5684e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
5694e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
570632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    // call this after any possible paint modifiers
571632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    if (fPaint->nothingToDraw()) {
57296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fPaint = nullptr;
5734e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return false;
5744e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
5754e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    return true;
5764e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com}
5774e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls //////////////////
5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5803aafe111b6cc388400092851cc53bbbdfcb8a81creed#define LOOPER_BEGIN_DRAWBITMAP(paint, skipLayerForFilter, bounds)  \
5813aafe111b6cc388400092851cc53bbbdfcb8a81creed    this->predrawNotify();                                          \
5823aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper looper(this, paint, skipLayerForFilter, bounds); \
5833aafe111b6cc388400092851cc53bbbdfcb8a81creed    while (looper.next(SkDrawFilter::kBitmap_Type)) {               \
584262a71b7f95ce98ff3dd8dba845afbd724470903reed        SkDrawIter iter(this);
585262a71b7f95ce98ff3dd8dba845afbd724470903reed
586262a71b7f95ce98ff3dd8dba845afbd724470903reed
5878926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com#define LOOPER_BEGIN_DRAWDEVICE(paint, type)                        \
58897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
5893aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper  looper(this, paint, true);                      \
5908926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (looper.next(type)) {                                     \
5918926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkDrawIter          iter(this);
5928926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
59378cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org#define LOOPER_BEGIN(paint, type, bounds)                           \
59497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
5953aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper  looper(this, paint, false, bounds);             \
5964e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    while (looper.next(type)) {                                     \
5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawIter          iter(this);
5984b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
599c83a29759a5c2966da5ab973e4fd90763e4c962breed#define LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, type, bounds, auxOpaque)  \
600c83a29759a5c2966da5ab973e4fd90763e4c962breed    this->predrawNotify(bounds, &paint, auxOpaque);                 \
6013aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper  looper(this, paint, false, bounds);             \
602c83a29759a5c2966da5ab973e4fd90763e4c962breed    while (looper.next(type)) {                                     \
603c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkDrawIter          iter(this);
604c83a29759a5c2966da5ab973e4fd90763e4c962breed
6054e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_END    }
6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////
6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
609fbfa25802709139c2f14e304319c9541da65ca27msarettstatic inline SkRect qr_clip_bounds(const SkIRect& bounds) {
610fbfa25802709139c2f14e304319c9541da65ca27msarett    if (bounds.isEmpty()) {
611fbfa25802709139c2f14e304319c9541da65ca27msarett        return SkRect::MakeEmpty();
612fbfa25802709139c2f14e304319c9541da65ca27msarett    }
613fbfa25802709139c2f14e304319c9541da65ca27msarett
614fbfa25802709139c2f14e304319c9541da65ca27msarett    // Expand bounds out by 1 in case we are anti-aliasing.  We store the
615fbfa25802709139c2f14e304319c9541da65ca27msarett    // bounds as floats to enable a faster quick reject implementation.
616fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect dst;
617fbfa25802709139c2f14e304319c9541da65ca27msarett    SkNx_cast<float>(Sk4i::Load(&bounds.fLeft) + Sk4i(-1,-1,1,1)).store(&dst.fLeft);
618fbfa25802709139c2f14e304319c9541da65ca27msarett    return dst;
619fbfa25802709139c2f14e304319c9541da65ca27msarett}
620fbfa25802709139c2f14e304319c9541da65ca27msarett
621feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtkleinvoid SkCanvas::resetForNextPicture(const SkIRect& bounds) {
622feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    this->restoreToCount(1);
623feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fMCRec->reset(bounds);
624feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
625feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    // We're peering through a lot of structs here.  Only at this scope do we
626139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    // know that the device is a SkNoPixelsDevice.
627713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    static_cast<SkNoPixelsDevice*>(fMCRec->fLayer->fDevice.get())->resetForNextPicture(bounds);
628fbfa25802709139c2f14e304319c9541da65ca27msarett    fDeviceClipBounds = qr_clip_bounds(bounds);
6299637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    fIsScaleTranslate = true;
630feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein}
631feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
632d954498c01ccf0417feacf89e45d0c62a06a813breedSkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
63342b73eb00367c8315974b1c374308d20efa78897reed    if (device && device->forceConservativeRasterClip()) {
63442b73eb00367c8315974b1c374308d20efa78897reed        flags = InitFlags(flags | kConservativeRasterClip_InitFlag);
63542b73eb00367c8315974b1c374308d20efa78897reed    }
63642b73eb00367c8315974b1c374308d20efa78897reed
63745a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    fAllowSimplifyClip = false;
6382ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount = 1;
63996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fMetaData = nullptr;
64095302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack#ifdef SK_EXPERIMENTAL_SHADOWING
64195302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    fLights = nullptr;
64295302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack#endif
6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.push_back();
645a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    new (fMCRec) MCRec;
6465f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev    fMCRec->fRasterClip.setDeviceClipRestriction(&fClipRestrictionRect);
6479637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    fIsScaleTranslate = true;
6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
649a499f905e9340e4935447f2562fd92e8853382b1reed    SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage));
650a499f905e9340e4935447f2562fd92e8853382b1reed    fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
651713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    new (fDeviceCMStorage) DeviceCM(sk_ref_sp(device), nullptr, fMCRec->fMatrix);
652b679ca8926a832274b14fdb512f88f64b61d32eareed
6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = fMCRec->fLayer;
6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
65596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fSurfaceBase = nullptr;
656f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
657f92c86642a1875da54d54b447f006cb9dfbbb35creed    if (device) {
658efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        // The root device and the canvas should always have the same pixel geometry
659efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        SkASSERT(fProps.pixelGeometry() == device->surfaceProps().pixelGeometry());
66078e276889795454891cbba48ab11927968114953reed        fMCRec->fRasterClip.setRect(device->getGlobalBounds());
661fbfa25802709139c2f14e304319c9541da65ca27msarett        fDeviceClipBounds = qr_clip_bounds(device->getGlobalBounds());
662c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
663c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
664f92c86642a1875da54d54b447f006cb9dfbbb35creed    }
665fbfa25802709139c2f14e304319c9541da65ca27msarett
666f92c86642a1875da54d54b447f006cb9dfbbb35creed    return device;
6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
669cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.comSkCanvas::SkCanvas()
670e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6714a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
672e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
6738d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    inc_canvas();
674ba124485687130183643994f1b4b68d629fbbebaskia.committer@gmail.com
67596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    this->init(nullptr, kDefault_InitFlags);
6768d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org}
6778d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org
67896a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reedSkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props)
679e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
68096a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reed    , fProps(SkSurfacePropsCopyOrDefault(props))
681e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
682e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    inc_canvas();
683b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
684566e53c7003920ff45c72498754060804b657c68Mike Reed    this->init(new SkNoPixelsDevice(SkIRect::MakeWH(SkTMax(width, 0), SkTMax(height, 0)), fProps),
685385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary               kDefault_InitFlags)->unref();
686d954498c01ccf0417feacf89e45d0c62a06a813breed}
687e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org
68878e276889795454891cbba48ab11927968114953reedSkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags)
689d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6904a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
691d954498c01ccf0417feacf89e45d0c62a06a813breed{
692d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
693b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
694566e53c7003920ff45c72498754060804b657c68Mike Reed    SkIRect r = bounds.isEmpty() ? SkIRect::MakeEmpty() : bounds;
695566e53c7003920ff45c72498754060804b657c68Mike Reed    this->init(new SkNoPixelsDevice(r, fProps), flags)->unref();
69627a5e656c3d6ef22f9cb34de18e1b960da3aa241reed}
6978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
698d954498c01ccf0417feacf89e45d0c62a06a813breedSkCanvas::SkCanvas(SkBaseDevice* device)
699d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7007b05ff11ebc51f3f3abd1c1756337a04f563537erobertphillips    , fProps(device->surfaceProps())
701d954498c01ccf0417feacf89e45d0c62a06a813breed{
702d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
703b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
704d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(device, kDefault_InitFlags);
7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
707fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillipsSkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags)
708fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7097b05ff11ebc51f3f3abd1c1756337a04f563537erobertphillips    , fProps(device->surfaceProps())
710fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips{
711fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    inc_canvas();
712fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips
713fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    this->init(device, flags);
714fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips}
715fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips
7164a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
7173716fd067a5621bb94a6cb08d72afec8bf3acedareed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7184a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(props)
7193716fd067a5621bb94a6cb08d72afec8bf3acedareed{
7203716fd067a5621bb94a6cb08d72afec8bf3acedareed    inc_canvas();
721b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
722704cd32e4a92d6c3eae6bfae4adcc20126bf4437Hal Canary    sk_sp<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps));
723704cd32e4a92d6c3eae6bfae4adcc20126bf4437Hal Canary    this->init(device.get(), kDefault_InitFlags);
7244a8126e7f81384526629b1e21bf89b632ea13cd9reed}
72529c857d0f3a1cb837f73406eeb6ba9771879b5e7reed
726356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedSkCanvas::SkCanvas(const SkBitmap& bitmap, std::unique_ptr<SkRasterHandleAllocator> alloc,
727356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                   SkRasterHandleAllocator::Handle hndl)
7284a8126e7f81384526629b1e21bf89b632ea13cd9reed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7294a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
730356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    , fAllocator(std::move(alloc))
7314a8126e7f81384526629b1e21bf89b632ea13cd9reed{
7324a8126e7f81384526629b1e21bf89b632ea13cd9reed    inc_canvas();
733b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
734356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    sk_sp<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps, hndl));
735704cd32e4a92d6c3eae6bfae4adcc20126bf4437Hal Canary    this->init(device.get(), kDefault_InitFlags);
7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
738356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedSkCanvas::SkCanvas(const SkBitmap& bitmap) : SkCanvas(bitmap, nullptr, nullptr) {}
739356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
74031f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
74131f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt SarettSkCanvas::SkCanvas(const SkBitmap& bitmap, ColorBehavior)
74231f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
74331f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
74431f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    , fAllocator(nullptr)
74531f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett{
74631f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    inc_canvas();
74731f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett
74831f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    SkBitmap tmp(bitmap);
74931f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    *const_cast<SkImageInfo*>(&tmp.info()) = tmp.info().makeColorSpace(nullptr);
75031f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    sk_sp<SkBaseDevice> device(new SkBitmapDevice(tmp, fProps, nullptr));
75131f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    this->init(device.get(), kDefault_InitFlags);
75231f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett}
75331f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett#endif
75431f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett
7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() {
7568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // free up the contents of our deque
7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->restoreToCount(1);    // restore everything but the last
7587c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->internalRestore();    // restore the last, since we're going away
7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
761385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    delete fMetaData;
762b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org
7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dec_canvas();
7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
76653d9f1cfbd5ddbf57c2f22b9e613ce48e5b2896cfmalita#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const {
7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fFilter;
7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
77251985e3f5e608d369e52832b7ce489d85d402422reed    this->checkForDeferredSave();
7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7767765000709dc64eb23be7df47d1f995d1f787115fmalita#endif
7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
77874bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.orgSkMetaData& SkCanvas::getMetaData() {
77974bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // metadata users are rare, so we lazily allocate it. If that changes we
78074bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // can decide to just make it a field in the device (rather than a ptr)
78196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == fMetaData) {
78274bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org        fMetaData = new SkMetaData;
78374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    }
78474bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    return *fMetaData;
78574bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org}
78674bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org
7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
7888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
789bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.orgvoid SkCanvas::flush() {
790ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed    this->onFlush();
791ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed}
792ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed
793ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reedvoid SkCanvas::onFlush() {
7941f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getDevice();
795bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    if (device) {
796bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org        device->flush();
797bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    }
798bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org}
799bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org
800afc7cce5d68663934128d76963cd501f771d71desenorblancoSkISize SkCanvas::getBaseLayerSize() const {
801afc7cce5d68663934128d76963cd501f771d71desenorblanco    SkBaseDevice* d = this->getDevice();
8024ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
8034ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
8044ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
805afc7cce5d68663934128d76963cd501f771d71desenorblancoSkIRect SkCanvas::getTopLayerBounds() const {
8064ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
807afc7cce5d68663934128d76963cd501f771d71desenorblanco    if (!d) {
808afc7cce5d68663934128d76963cd501f771d71desenorblanco        return SkIRect::MakeEmpty();
809afc7cce5d68663934128d76963cd501f771d71desenorblanco    }
810afc7cce5d68663934128d76963cd501f771d71desenorblanco    return SkIRect::MakeXYWH(d->getOrigin().x(), d->getOrigin().y(), d->width(), d->height());
811210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com}
812210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com
8131f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getDevice() const {
8148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
815c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com    MCRec* rec = (MCRec*) fMCStack.front();
8168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
817713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    return rec->fLayer->fDevice.get();
8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8200ed3b640c9da71fbbd73c65a4ec1992f85596271Florin MalitaSkBaseDevice* SkCanvas::getTopDevice() const {
821713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    return fMCRec->fTopLayer->fDevice.get();
8229266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com}
8239266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com
82496472deea70169396b8e1f576e470138f55fdb1freedbool SkCanvas::readPixels(const SkImageInfo& dstInfo, void* dstP, size_t rowBytes, int x, int y) {
825a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
826a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!device) {
827a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
828a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
829db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
83003dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    return device->readPixels(dstInfo, dstP, rowBytes, x, y);
83151df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com}
83251df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
83312e946b4bfdf598bffb276776ea6e25439e25265Mike Reedbool SkCanvas::readPixels(const SkPixmap& pm, int x, int y) {
83412e946b4bfdf598bffb276776ea6e25439e25265Mike Reed    return pm.addr() && this->readPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), x, y);
83512e946b4bfdf598bffb276776ea6e25439e25265Mike Reed}
83612e946b4bfdf598bffb276776ea6e25439e25265Mike Reed
83712e946b4bfdf598bffb276776ea6e25439e25265Mike Reedbool SkCanvas::readPixels(const SkBitmap& bm, int x, int y) {
83812e946b4bfdf598bffb276776ea6e25439e25265Mike Reed    SkPixmap pm;
83912e946b4bfdf598bffb276776ea6e25439e25265Mike Reed    return bm.peekPixels(&pm) && this->readPixels(pm, x, y);
84012e946b4bfdf598bffb276776ea6e25439e25265Mike Reed}
84112e946b4bfdf598bffb276776ea6e25439e25265Mike Reed
8424cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
8434edb5d219eb99aa1e8fbe5e37260d3b34314e54bMike Reed    SkPixmap pm;
8444edb5d219eb99aa1e8fbe5e37260d3b34314e54bMike Reed    if (bitmap.peekPixels(&pm)) {
845cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        return this->writePixels(pm.info(), pm.addr(), pm.rowBytes(), x, y);
8464cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8474cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    return false;
8484cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
8494cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
85003dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarettbool SkCanvas::writePixels(const SkImageInfo& srcInfo, const void* pixels, size_t rowBytes,
8514cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                           int x, int y) {
8524cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
8534cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!device) {
8544cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
8554cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8564cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
85703dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // This check gives us an early out and prevents generation ID churn on the surface.
85803dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // This is purely optional: it is a subset of the checks performed by SkWritePixelsRec.
85903dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    SkIRect srcRect = SkIRect::MakeXYWH(x, y, srcInfo.width(), srcInfo.height());
86003dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    if (!srcRect.intersect(0, 0, device->width(), device->height())) {
86103dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett        return false;
8624cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8634cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
86403dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // Tell our owning surface to bump its generation ID.
86503dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    const bool completeOverwrite =
86603dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett            srcRect.size() == SkISize::Make(device->width(), device->height());
867c83a29759a5c2966da5ab973e4fd90763e4c962breed    this->predrawNotify(completeOverwrite);
8684af35f348b2e2f6c428819118eb7a2f2fff53a74reed
86903dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // This can still fail, most notably in the case of a invalid color type or alpha type
87003dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // conversion.  We could pull those checks into this function and avoid the unnecessary
87103dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // generation ID bump.  But then we would be performing those checks twice, since they
87203dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // are also necessary at the bitmap/pixmap entry points.
87303dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    return device->writePixels(srcInfo, pixels, rowBytes, x, y);
8744cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
87551df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8782ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::checkForDeferredSave() {
8792ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
8802ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        this->doSave();
8812ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
8822ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
8832ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
884f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::getSaveCount() const {
8852ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#ifdef SK_DEBUG
8862ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int count = 0;
8872ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkDeque::Iter iter(fMCStack, SkDeque::Iter::kFront_IterStart);
8882ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    for (;;) {
8892ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        const MCRec* rec = (const MCRec*)iter.next();
8902ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (!rec) {
8912ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            break;
8922ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
8932ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        count += 1 + rec->fDeferredSaveCount;
8942ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
8952ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkASSERT(count == fSaveCount);
8962ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#endif
8972ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return fSaveCount;
898f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
899f0090cb80ab10a49e511aa5450ae38917fa058d9reed
900f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::save() {
9012ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount += 1;
9022ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fMCRec->fDeferredSaveCount += 1;
9032ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;  // return our prev value
9042ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
9052ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
9062ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::doSave() {
907f0090cb80ab10a49e511aa5450ae38917fa058d9reed    this->willSave();
908a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita
909a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    SkASSERT(fMCRec->fDeferredSaveCount > 0);
910a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    fMCRec->fDeferredSaveCount -= 1;
9112ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
912f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
913f0090cb80ab10a49e511aa5450ae38917fa058d9reed
914f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restore() {
9152ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
9162ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        SkASSERT(fSaveCount > 1);
9172ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fSaveCount -= 1;
9182ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fMCRec->fDeferredSaveCount -= 1;
9192ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    } else {
9202ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        // check for underflow
9212ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (fMCStack.count() > 1) {
9222ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->willRestore();
9232ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            SkASSERT(fSaveCount > 1);
924a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed            fSaveCount -= 1;
9252ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->internalRestore();
9262ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->didRestore();
9272ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
928f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
929f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
930f0090cb80ab10a49e511aa5450ae38917fa058d9reed
931f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restoreToCount(int count) {
932f0090cb80ab10a49e511aa5450ae38917fa058d9reed    // sanity check
933f0090cb80ab10a49e511aa5450ae38917fa058d9reed    if (count < 1) {
934f0090cb80ab10a49e511aa5450ae38917fa058d9reed        count = 1;
935f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
936f0f14113431ace669f278fdd97b50950f2cf4c80mtklein
937f0090cb80ab10a49e511aa5450ae38917fa058d9reed    int n = this->getSaveCount() - count;
938f0090cb80ab10a49e511aa5450ae38917fa058d9reed    for (int i = 0; i < n; ++i) {
939f0090cb80ab10a49e511aa5450ae38917fa058d9reed        this->restore();
940f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
941f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
942f0090cb80ab10a49e511aa5450ae38917fa058d9reed
9432ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::internalSave() {
9448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    MCRec* newTop = (MCRec*)fMCStack.push_back();
945d954498c01ccf0417feacf89e45d0c62a06a813breed    new (newTop) MCRec(*fMCRec);    // balanced in restore()
9468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = newTop;
9474b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
948c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    FOR_EACH_TOP_DEVICE(device->save());
9498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9514960eeec4a1f2a772654883d7f3615d47bcd5dc3reedbool SkCanvas::BoundsAffectsClip(SaveLayerFlags saveLayerFlags) {
9524960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    return !(saveLayerFlags & SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag);
9538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9554960eeec4a1f2a772654883d7f3615d47bcd5dc3reedbool SkCanvas::clipRectBounds(const SkRect* bounds, SaveLayerFlags saveLayerFlags,
9569b3aa54bc9605257c701cf465813f5fb1d7ba39ereed                              SkIRect* intersection, const SkImageFilter* imageFilter) {
957918e144408ba218df919528f8b48c544f4767883Mike Reed    SkIRect clipBounds = this->getDeviceClipBounds();
958918e144408ba218df919528f8b48c544f4767883Mike Reed    if (clipBounds.isEmpty()) {
959a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        return false;
960f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
961c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
96296e657d0e103b8358a77ecd913f6086929f792b8reed    const SkMatrix& ctm = fMCRec->fMatrix;  // this->getTotalMatrix()
96396e657d0e103b8358a77ecd913f6086929f792b8reed
964c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (imageFilter) {
965e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco        clipBounds = imageFilter->filterBounds(clipBounds, ctm);
966db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco        if (bounds && !imageFilter->canComputeFastBounds()) {
967db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco            bounds = nullptr;
968db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco        }
969c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
970bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ir;
97149f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
9728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect r;
9734b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
97496e657d0e103b8358a77ecd913f6086929f792b8reed        ctm.mapRect(&r, *bounds);
9758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r.roundOut(&ir);
9768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // early exit if the layer's bounds are clipped out
9778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!ir.intersect(clipBounds)) {
9784960eeec4a1f2a772654883d7f3615d47bcd5dc3reed            if (BoundsAffectsClip(saveLayerFlags)) {
979a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed                fMCRec->fTopLayer->fDevice->clipRegion(SkRegion(), SkClipOp::kIntersect); // empty
9801f836ee096bb988adef4b9757b2629c7afeda36dreed                fMCRec->fRasterClip.setEmpty();
981fbfa25802709139c2f14e304319c9541da65ca27msarett                fDeviceClipBounds.setEmpty();
982bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            }
983a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org            return false;
9848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // no user bounds, so just use the clip
9868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ir = clipBounds;
9878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
988180aec43451dd951fdaae81a92efc710ba093260reed    SkASSERT(!ir.isEmpty());
9898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9904960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    if (BoundsAffectsClip(saveLayerFlags)) {
991180aec43451dd951fdaae81a92efc710ba093260reed        // Simplify the current clips since they will be applied properly during restore()
992180aec43451dd951fdaae81a92efc710ba093260reed        fMCRec->fRasterClip.setRect(ir);
993fbfa25802709139c2f14e304319c9541da65ca27msarett        fDeviceClipBounds = qr_clip_bounds(ir);
994a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
995a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
996a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    if (intersection) {
997a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        *intersection = ir;
998a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
999a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return true;
1000a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org}
1001a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
10024960eeec4a1f2a772654883d7f3615d47bcd5dc3reed
10034960eeec4a1f2a772654883d7f3615d47bcd5dc3reedint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
10044960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    return this->saveLayer(SaveLayerRec(bounds, paint, 0));
1005d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
1006d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
10074960eeec4a1f2a772654883d7f3615d47bcd5dc3reedint SkCanvas::saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint) {
10084960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    return this->saveLayer(SaveLayerRec(bounds, paint, kPreserveLCDText_SaveLayerFlag));
10094960eeec4a1f2a772654883d7f3615d47bcd5dc3reed}
10104960eeec4a1f2a772654883d7f3615d47bcd5dc3reed
10114960eeec4a1f2a772654883d7f3615d47bcd5dc3reedint SkCanvas::saveLayer(const SaveLayerRec& origRec) {
10124960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    SaveLayerRec rec(origRec);
1013d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    if (gIgnoreSaveLayerBounds) {
10144960eeec4a1f2a772654883d7f3615d47bcd5dc3reed        rec.fBounds = nullptr;
1015d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    }
10164960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    SaveLayerStrategy strategy = this->getSaveLayerStrategy(rec);
1017a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed    fSaveCount += 1;
10184960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    this->internalSaveLayer(rec, strategy);
10192ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;
10208926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
10218926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
1022a2217ef965e57fdbbf989989e7ec1f2c04f62d39reedvoid SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter,
1023c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed                                    SkBaseDevice* dst, const SkIPoint& dstOrigin,
1024a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed                                    const SkMatrix& ctm) {
1025a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    SkDraw draw;
1026a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    SkRasterClip rc;
1027a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    rc.setRect(SkIRect::MakeWH(dst->width(), dst->height()));
1028a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    if (!dst->accessPixels(&draw.fDst)) {
1029a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        draw.fDst.reset(dst->imageInfo(), nullptr, 0);
1030a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    }
1031a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    draw.fMatrix = &SkMatrix::I();
1032a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    draw.fRC = &rc;
10337354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips
10347354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips    SkPaint p;
1035c61abeed8958a757c6b49937f28b63066148dd67Mike Reed    if (filter) {
1036c61abeed8958a757c6b49937f28b63066148dd67Mike Reed        p.setImageFilter(filter->makeWithLocalMatrix(ctm));
1037c61abeed8958a757c6b49937f28b63066148dd67Mike Reed    }
1038a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed
1039c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    int x = src->getOrigin().x() - dstOrigin.x();
1040c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    int y = src->getOrigin().y() - dstOrigin.y();
1041a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    auto special = src->snapSpecial();
1042a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    if (special) {
1043a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        dst->drawSpecial(special.get(), x, y, p);
1044a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    }
10457354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips}
104670ee31b2fa127eee6c0cea61cf05508e9d3ca7b1reed
1047129ed1cd6d792f3f6cf563aefa9756fc6308289dreedstatic SkImageInfo make_layer_info(const SkImageInfo& prev, int w, int h, bool isOpaque,
1048129ed1cd6d792f3f6cf563aefa9756fc6308289dreed                                   const SkPaint* paint) {
1049129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    // need to force L32 for now if we have an image filter. Once filters support other colortypes
1050129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    // e.g. sRGB or F16, we can remove this check
105152ede1d905728cdcaa98db1e4a33724f5a85c62dbrianosman    // SRGBTODO: Can we remove this check now?
1052129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    const bool hasImageFilter = paint && paint->getImageFilter();
1053129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
1054129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    SkAlphaType alphaType = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
1055129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    if ((prev.bytesPerPixel() < 4) || hasImageFilter) {
1056129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        // force to L32
1057129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        return SkImageInfo::MakeN32(w, h, alphaType);
1058129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    } else {
1059129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        // keep the same characteristics as the prev
1060693fdbd6b81a860657612e7604430dd55d6e721bMike Reed        return SkImageInfo::Make(w, h, prev.colorType(), alphaType, prev.refColorSpace());
1061129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    }
1062129ed1cd6d792f3f6cf563aefa9756fc6308289dreed}
1063129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
10644960eeec4a1f2a772654883d7f3615d47bcd5dc3reedvoid SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy strategy) {
10654960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    const SkRect* bounds = rec.fBounds;
10664960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    const SkPaint* paint = rec.fPaint;
10674960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    SaveLayerFlags saveLayerFlags = rec.fSaveLayerFlags;
10684960eeec4a1f2a772654883d7f3615d47bcd5dc3reed
10698c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkLazyPaint lazyP;
10708c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkImageFilter* imageFilter = paint ? paint->getImageFilter() : NULL;
10718c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkMatrix stashedMatrix = fMCRec->fMatrix;
10728c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkMatrix remainder;
10738c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkSize scale;
10748c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    /*
10758c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  ImageFilters (so far) do not correctly handle matrices (CTM) that contain rotation/skew/etc.
10768c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  but they do handle scaling. To accommodate this, we do the following:
10778c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *
10788c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  1. Stash off the current CTM
10798c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  2. Decompose the CTM into SCALE and REMAINDER
10808c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  3. Wack the CTM to be just SCALE, and wrap the imagefilter with a MatrixImageFilter that
10818c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *     contains the REMAINDER
10828c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  4. Proceed as usual, allowing the client to draw into the layer (now with a scale-only CTM)
10838c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  5. During restore, we process the MatrixImageFilter, which applies REMAINDER to the output
10848c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *     of the original imagefilter, and draw that (via drawSprite)
10858c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  6. Unwack the CTM to its original state (i.e. stashedMatrix)
10868c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *
10878c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  Perhaps in the future we could augment #5 to apply REMAINDER as part of the draw (no longer
10888c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  a sprite operation) to avoid the extra buffer/overhead of MatrixImageFilter.
10898c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     */
109096a04f329926099f0002f97883242793ff04f61creed    if (imageFilter && !stashedMatrix.isScaleTranslate() && !imageFilter->canHandleComplexCTM() &&
10918c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        stashedMatrix.decomposeScale(&scale, &remainder))
10928c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    {
10938c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        // We will restore the matrix (which we are overwriting here) in restore via fStashedMatrix
10948c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        this->internalSetMatrix(SkMatrix::MakeScale(scale.width(), scale.height()));
10958c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        SkPaint* p = lazyP.set(*paint);
10968c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        p->setImageFilter(SkImageFilter::MakeMatrixFilter(remainder,
10978c30a8196dd5903d2d23b4d0a5dc888e802bf698reed                                                          SkFilterQuality::kLow_SkFilterQuality,
10988c30a8196dd5903d2d23b4d0a5dc888e802bf698reed                                                          sk_ref_sp(imageFilter)));
10998c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        imageFilter = p->getImageFilter();
11008c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        paint = p;
11018c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    }
11028c30a8196dd5903d2d23b4d0a5dc888e802bf698reed
1103a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // do this before we create the layer. We don't call the public save() since
1104a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // that would invoke a possibly overridden virtual
11052ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
1106a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1107a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    SkIRect ir;
11088c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, imageFilter)) {
11092ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
11108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1112e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
1113e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // the clipRectBounds() call above?
1114e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    if (kNoLayer_SaveLayerStrategy == strategy) {
11152ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1116e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    }
1117e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
11184960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    bool isOpaque = SkToBool(saveLayerFlags & kIsOpaque_SaveLayerFlag);
11198dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    SkPixelGeometry geo = fProps.pixelGeometry();
11208dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    if (paint) {
112176033be81b82c44fd5d4fdf2672eb22e505da1f0reed        // TODO: perhaps add a query to filters so we might preserve opaqueness...
1122daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        if (paint->getImageFilter() || paint->getColorFilter()) {
112376033be81b82c44fd5d4fdf2672eb22e505da1f0reed            isOpaque = false;
11248dc0ccb8d33d1af7dd13228509e61fe915bc7705reed            geo = kUnknown_SkPixelGeometry;
1125b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com        }
1126b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    }
11278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11285139e501c5ac3a511e35c78395c907a176113451robertphillips    SkBaseDevice* priorDevice = this->getTopDevice();
1129c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    if (nullptr == priorDevice) {   // Do we still need this check???
1130b2db898573e3cdcc8234eebf51961bfc4977ebbcreed        SkDebugf("Unable to find device for layer.");
11312ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1132b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    }
1133b2db898573e3cdcc8234eebf51961bfc4977ebbcreed
11345139e501c5ac3a511e35c78395c907a176113451robertphillips    SkImageInfo info = make_layer_info(priorDevice->imageInfo(), ir.width(), ir.height(), isOpaque,
1135129ed1cd6d792f3f6cf563aefa9756fc6308289dreed                                       paint);
1136129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
1137704cd32e4a92d6c3eae6bfae4adcc20126bf4437Hal Canary    sk_sp<SkBaseDevice> newDevice;
113861f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    {
113970ee31b2fa127eee6c0cea61cf05508e9d3ca7b1reed        const bool preserveLCDText = kOpaque_SkAlphaType == info.alphaType() ||
11404960eeec4a1f2a772654883d7f3615d47bcd5dc3reed                                     (saveLayerFlags & kPreserveLCDText_SaveLayerFlag);
1141daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
114270ee31b2fa127eee6c0cea61cf05508e9d3ca7b1reed        const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo,
1143356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                                                                             preserveLCDText,
1144356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                                                                             fAllocator.get());
11455139e501c5ac3a511e35c78395c907a176113451robertphillips        newDevice.reset(priorDevice->onCreateDevice(createInfo, paint));
11465139e501c5ac3a511e35c78395c907a176113451robertphillips        if (!newDevice) {
11477503d60847c4ad22df87458aecd917772b23d293reed            return;
114861f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        }
1149e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com    }
1150713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    DeviceCM* layer = new DeviceCM(newDevice, paint, stashedMatrix);
11518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1152b43a3e0160b3854a04305decd1d9e766a3889b3aMike Reed    // only have a "next" if this new layer doesn't affect the clip (rare)
1153b43a3e0160b3854a04305decd1d9e766a3889b3aMike Reed    layer->fNext = BoundsAffectsClip(saveLayerFlags) ? nullptr : fMCRec->fTopLayer;
11548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = layer;
11558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
1156a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed
1157c61abeed8958a757c6b49937f28b63066148dd67Mike Reed    if ((rec.fSaveLayerFlags & kInitWithPrevious_SaveLayerFlag) || rec.fBackdrop) {
1158c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        DrawDeviceWithFilter(priorDevice, rec.fBackdrop, newDevice.get(), { ir.fLeft, ir.fTop },
1159a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed                             fMCRec->fMatrix);
1160a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    }
1161c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
1162c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    newDevice->setOrigin(fMCRec->fMatrix, ir.fLeft, ir.fTop);
1163c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
1164c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    newDevice->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
1165c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    if (layer->fNext) {
1166c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        // need to punch a hole in the previous device, so we don't draw there, given that
1167c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        // the new top-layer will allow drawing to happen "below" it.
1168c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        SkRegion hole(ir);
1169c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        do {
1170c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed            layer = layer->fNext;
1171c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed            layer->fDevice->clipRegion(hole, SkClipOp::kDifference);
1172c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        } while (layer->fNext);
1173c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    }
11748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1176d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
1177bada1885da479d948f065182d6dfa85a1140bda5reed    if (0xFF == alpha) {
1178bada1885da479d948f065182d6dfa85a1140bda5reed        return this->saveLayer(bounds, nullptr);
1179bada1885da479d948f065182d6dfa85a1140bda5reed    } else {
1180bada1885da479d948f065182d6dfa85a1140bda5reed        SkPaint tmpPaint;
1181bada1885da479d948f065182d6dfa85a1140bda5reed        tmpPaint.setAlpha(alpha);
1182bada1885da479d948f065182d6dfa85a1140bda5reed        return this->saveLayer(bounds, &tmpPaint);
1183bada1885da479d948f065182d6dfa85a1140bda5reed    }
1184d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
1185d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
11868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() {
11878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fMCStack.count() != 0);
11888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
118988edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    // reserve our layer (if any)
11908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM* layer = fMCRec->fLayer;   // may be null
11918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
119296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fMCRec->fLayer = nullptr;
11938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now do the normal restore()
11958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->~MCRec();       // balanced in save()
11968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCStack.pop_back();
11978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.back();
11988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1199c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    if (fMCRec) {
1200c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        FOR_EACH_TOP_DEVICE(device->restore(fMCRec->fMatrix));
1201c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    }
1202c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
12038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
12048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        since if we're being recorded, we don't want to record this (the
12058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        recorder will have already recorded the restore).
12068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
120749f085dddff10473b6ebf832a974288300224e60bsalomon    if (layer) {
1208b43a3e0160b3854a04305decd1d9e766a3889b3aMike Reed        if (fMCRec) {
12096f8f292aa768869a9e85c314b124875f57504f2creed@google.com            const SkIPoint& origin = layer->fDevice->getOrigin();
1210713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita            this->internalDrawDevice(layer->fDevice.get(), origin.x(), origin.y(),
1211713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita                                     layer->fPaint.get());
12128c30a8196dd5903d2d23b4d0a5dc888e802bf698reed            // restore what we smashed in internalSaveLayer
12138c30a8196dd5903d2d23b4d0a5dc888e802bf698reed            fMCRec->fMatrix = layer->fStashedMatrix;
12148926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // reset this, since internalDrawDevice will have set it to true
1215385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            delete layer;
1216b679ca8926a832274b14fdb512f88f64b61d32eareed        } else {
1217b679ca8926a832274b14fdb512f88f64b61d32eareed            // we're at the root
1218a499f905e9340e4935447f2562fd92e8853382b1reed            SkASSERT(layer == (void*)fDeviceCMStorage);
1219b679ca8926a832274b14fdb512f88f64b61d32eareed            layer->~DeviceCM();
12208c30a8196dd5903d2d23b4d0a5dc888e802bf698reed            // no need to update fMCRec, 'cause we're killing the canvas
12218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
122288edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
1223fbfa25802709139c2f14e304319c9541da65ca27msarett
1224fbfa25802709139c2f14e304319c9541da65ca27msarett    if (fMCRec) {
12259637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett        fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate();
1226fbfa25802709139c2f14e304319c9541da65ca27msarett        fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1227fbfa25802709139c2f14e304319c9541da65ca27msarett    }
12288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1230e8f3062a36d3682f4019309a32b5b84dc9eddf8creedsk_sp<SkSurface> SkCanvas::makeSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
123196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == props) {
12324a8126e7f81384526629b1e21bf89b632ea13cd9reed        props = &fProps;
12334a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
12344a8126e7f81384526629b1e21bf89b632ea13cd9reed    return this->onNewSurface(info, *props);
123576f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
123676f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
1237e8f3062a36d3682f4019309a32b5b84dc9eddf8creedsk_sp<SkSurface> SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
123876f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    SkBaseDevice* dev = this->getDevice();
1239e8f3062a36d3682f4019309a32b5b84dc9eddf8creed    return dev ? dev->makeSurface(info, props) : nullptr;
124076f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
124176f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
1242c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkImageInfo SkCanvas::imageInfo() const {
1243ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed    return this->onImageInfo();
1244ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed}
1245ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed
1246ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reedSkImageInfo SkCanvas::onImageInfo() const {
1247c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1248c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (dev) {
1249c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return dev->imageInfo();
1250c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1251900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        return SkImageInfo::MakeUnknown(0, 0);
1252c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1253c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1254c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1255898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosmanbool SkCanvas::getProps(SkSurfaceProps* props) const {
1256ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed    return this->onGetProps(props);
1257ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed}
1258ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed
1259ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reedbool SkCanvas::onGetProps(SkSurfaceProps* props) const {
1260898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman    SkBaseDevice* dev = this->getDevice();
1261898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman    if (dev) {
1262898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman        if (props) {
1263898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman            *props = fProps;
1264898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman        }
1265898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman        return true;
1266898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman    } else {
1267898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman        return false;
1268898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman    }
1269898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman}
1270898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman
12716ceeebd37a43d879c120b6ba100ae1febdd67a18reedbool SkCanvas::peekPixels(SkPixmap* pmap) {
12726ceeebd37a43d879c120b6ba100ae1febdd67a18reed    return this->onPeekPixels(pmap);
1273c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1274c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1275884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onPeekPixels(SkPixmap* pmap) {
1276c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1277884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->peekPixels(pmap);
1278c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1279c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
12806b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.orgvoid* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
1281884e97cb04db7ed053a866567ee9c6e4c01f993areed    SkPixmap pmap;
1282884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (!this->onAccessTopLayerPixels(&pmap)) {
128396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
1284884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1285884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (info) {
1286884e97cb04db7ed053a866567ee9c6e4c01f993areed        *info = pmap.info();
1287884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1288884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (rowBytes) {
1289884e97cb04db7ed053a866567ee9c6e4c01f993areed        *rowBytes = pmap.rowBytes();
1290884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1291884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (origin) {
12920ed3b640c9da71fbbd73c65a4ec1992f85596271Florin Malita        *origin = this->getTopDevice()->getOrigin();
12936b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    }
1294884e97cb04db7ed053a866567ee9c6e4c01f993areed    return pmap.writable_addr();
12959c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
12969c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1297884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
12989c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
1299884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->accessPixels(pmap);
13009c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
13019c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1302520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////
13038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13047503d60847c4ad22df87458aecd917772b23d293reedvoid SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, const SkPaint* paint) {
13058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint tmp;
130696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
13078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &tmp;
13088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13094b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
13108926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1311a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed
13128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
13131f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        SkBaseDevice* dstDev = iter.fDevice;
131476dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        paint = &looper.paint();
131576dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkImageFilter* filter = paint->getImageFilter();
131676dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1317833dcf48844dd053ddf7ecea20e3e1c2b6b47e01Robert Phillips        if (filter) {
1318833dcf48844dd053ddf7ecea20e3e1c2b6b47e01Robert Phillips            sk_sp<SkSpecialImage> specialImage = srcDev->snapSpecial();
1319833dcf48844dd053ddf7ecea20e3e1c2b6b47e01Robert Phillips            if (specialImage) {
1320a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed                dstDev->drawSpecial(specialImage.get(), pos.x(), pos.y(), *paint);
1321833dcf48844dd053ddf7ecea20e3e1c2b6b47e01Robert Phillips            }
132276dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        } else {
1323a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            dstDev->drawDevice(srcDev, pos.x(), pos.y(), *paint);
132476dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        }
13258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1326a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed
13274e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
13288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
133032704674f64cb6a14356dfebe060cd3484c06cc7reed/////////////////////////////////////////////////////////////////////////////
1331da420b976e61071cfe5de10556b4b23e519091d6reed
133292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::translate(SkScalar dx, SkScalar dy) {
1333fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed    if (dx || dy) {
1334fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        this->checkForDeferredSave();
1335fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        fMCRec->fMatrix.preTranslate(dx,dy);
1336cbdf007bc2eb85056a1a5c75c088202becba2d16mtklein
1337fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        // Translate shouldn't affect the is-scale-translateness of the matrix.
1338fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
1339cbdf007bc2eb85056a1a5c75c088202becba2d16mtklein
1340c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
1341c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
1342fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        this->didTranslate(dx,dy);
1343fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed    }
13448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
134692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::scale(SkScalar sx, SkScalar sy) {
1347d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1348d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setScale(sx, sy);
1349d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
135292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::rotate(SkScalar degrees) {
1353d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1354d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setRotate(degrees);
1355d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
13568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13587438bfc0804d021aa92cdd5ea644994a4248f3dbbungemanvoid SkCanvas::rotate(SkScalar degrees, SkScalar px, SkScalar py) {
13597438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman    SkMatrix m;
13607438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman    m.setRotate(degrees, px, py);
13617438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman    this->concat(m);
13627438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman}
13637438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman
136492362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::skew(SkScalar sx, SkScalar sy) {
1365d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1366d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setSkew(sx, sy);
1367d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
136844c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
136944c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
137092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::concat(const SkMatrix& matrix) {
1371d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    if (matrix.isIdentity()) {
1372d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        return;
1373d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    }
1374d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org
13752ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
13761f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix.preConcat(matrix);
13779637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate();
13787627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
13797627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
13807627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
138144c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didConcat(matrix);
138244c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
138344c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
13848c30a8196dd5903d2d23b4d0a5dc888e802bf698reedvoid SkCanvas::internalSetMatrix(const SkMatrix& matrix) {
13851f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix = matrix;
13869da5a5a198e5dc9148f7f30a6089377590eee55bmsarett    fIsScaleTranslate = matrix.isScaleTranslate();
1387c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
1388c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
13898c30a8196dd5903d2d23b4d0a5dc888e802bf698reed}
13908c30a8196dd5903d2d23b4d0a5dc888e802bf698reed
13918c30a8196dd5903d2d23b4d0a5dc888e802bf698reedvoid SkCanvas::setMatrix(const SkMatrix& matrix) {
13928c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    this->checkForDeferredSave();
13938c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    this->internalSetMatrix(matrix);
139444c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didSetMatrix(matrix);
13958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() {
13988c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    this->setMatrix(SkMatrix::I());
13998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
140195302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack#ifdef SK_EXPERIMENTAL_SHADOWING
1402e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblackvoid SkCanvas::translateZ(SkScalar z) {
1403e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    this->checkForDeferredSave();
1404e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    this->fMCRec->fCurDrawDepth += z;
1405e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    this->didTranslateZ(z);
1406e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack}
1407e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack
1408e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblackSkScalar SkCanvas::getZ() const {
1409e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack    return this->fMCRec->fCurDrawDepth;
1410e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack}
1411e5de130788c8637d2f7df9ddb0241b78e04d5882vjiaoblack
141295302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblackvoid SkCanvas::setLights(sk_sp<SkLights> lights) {
141395302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    this->fLights = lights;
141495302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack}
141595302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
141695302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblacksk_sp<SkLights> SkCanvas::getLights() const {
141795302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    return this->fLights;
141895302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack}
141995302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack#endif
142095302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
14218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
14228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1423c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::clipRect(const SkRect& rect, SkClipOp op, bool doAA) {
14242ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14258f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
14268f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRect(rect, op, edgeStyle);
14278f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
14288f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
1429c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
1430a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    const bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
14317627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
14327627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    FOR_EACH_TOP_DEVICE(device->clipRect(rect, op, isAA));
14337627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
1434c64eff55049b1192052b791549a32a03be1c43e3reed    AutoValidateClip avc(this);
1435a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    fMCRec->fRasterClip.op(rect, fMCRec->fMatrix, this->getTopLayerBounds(), (SkRegion::Op)op,
1436a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon                           isAA);
1437fbfa25802709139c2f14e304319c9541da65ca27msarett    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
14388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14405f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Ilievvoid SkCanvas::androidFramework_setDeviceClipRestriction(const SkIRect& rect) {
14415f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev    fClipRestrictionRect = rect;
1442d519d484949161df6d4b2ecadc282427cab532cfMike Reed    if (fClipRestrictionRect.isEmpty()) {
1443d519d484949161df6d4b2ecadc282427cab532cfMike Reed        // we notify the device, but we *dont* resolve deferred saves (since we're just
1444d519d484949161df6d4b2ecadc282427cab532cfMike Reed        // removing the restriction if the rect is empty. how I hate this api.
1445d519d484949161df6d4b2ecadc282427cab532cfMike Reed        FOR_EACH_TOP_DEVICE(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect));
1446d519d484949161df6d4b2ecadc282427cab532cfMike Reed    } else {
14475f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev        this->checkForDeferredSave();
1448d519d484949161df6d4b2ecadc282427cab532cfMike Reed        FOR_EACH_TOP_DEVICE(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect));
14495f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev        AutoValidateClip avc(this);
14505f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev        fMCRec->fRasterClip.op(fClipRestrictionRect, SkRegion::kIntersect_Op);
14515f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev        fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
14525f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev    }
14535f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev}
14545f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev
1455c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::clipRRect(const SkRRect& rrect, SkClipOp op, bool doAA) {
14562ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14578f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
14584ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
14598f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(rrect.getBounds(), op, edgeStyle);
14608f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
14618f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRRect(rrect, op, edgeStyle);
14624ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
14638f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
146414e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
1465c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
1466a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    AutoValidateClip avc(this);
146714e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
1468a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
14697627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
14707627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    FOR_EACH_TOP_DEVICE(device->clipRRect(rrect, op, isAA));
1471a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
1472a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    fMCRec->fRasterClip.op(rrect, fMCRec->fMatrix, this->getTopLayerBounds(), (SkRegion::Op)op,
1473a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon                           isAA);
1474a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
14754ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
14764ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1477c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::clipPath(const SkPath& path, SkClipOp op, bool doAA) {
14782ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14798f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
148039f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips
148139f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips    if (!path.isInverseFillType() && fMCRec->fMatrix.rectStaysRect()) {
148239f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        SkRect r;
148339f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        if (path.isRect(&r)) {
148439f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            this->onClipRect(r, op, edgeStyle);
148539f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            return;
148639f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        }
148739f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        SkRRect rrect;
148839f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        if (path.isOval(&r)) {
148939f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            rrect.setOval(r);
149039f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            this->onClipRRect(rrect, op, edgeStyle);
149139f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            return;
149239f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        }
149339f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        if (path.isRRect(&rrect)) {
149439f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            this->onClipRRect(rrect, op, edgeStyle);
149539f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            return;
149639f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        }
14978f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
149839f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips
149939f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips    this->onClipPath(path, op, edgeStyle);
15008f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
15018f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
1502c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
15035c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
15045c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1505a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
15067627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
15077627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    FOR_EACH_TOP_DEVICE(device->clipPath(path, op, isAA));
15085c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1509a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    const SkPath* rasterClipPath = &path;
1510a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    const SkMatrix* matrix = &fMCRec->fMatrix;
1511a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    fMCRec->fRasterClip.op(*rasterClipPath, *matrix, this->getTopLayerBounds(), (SkRegion::Op)op,
1512a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon                           isAA);
1513fbfa25802709139c2f14e304319c9541da65ca27msarett    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
15148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1516c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::clipRegion(const SkRegion& rgn, SkClipOp op) {
15172ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
15188f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRegion(rgn, op);
15198f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
15208f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
1521c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::onClipRegion(const SkRegion& rgn, SkClipOp op) {
15227627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    FOR_EACH_TOP_DEVICE(device->clipRegion(rgn, op));
152327d07f0acb85eea4062075dfbe9148ce12d92c66Mike Reed
1524a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    AutoValidateClip avc(this);
152527d07f0acb85eea4062075dfbe9148ce12d92c66Mike Reed
152673603f3c52ffd89fe9d035be827b566a0e7d3b79reed    fMCRec->fRasterClip.op(rgn, (SkRegion::Op)op);
1527fbfa25802709139c2f14e304319c9541da65ca27msarett    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
15288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1530819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG
1531819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const {
1532819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    // construct clipRgn from the clipstack
15331f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    const SkBaseDevice* device = this->getDevice();
1534ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    if (!device) {
15355c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org        SkASSERT(this->isClipEmpty());
1536ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return;
1537ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
1538819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1539819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif
1540819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1541a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedbool SkCanvas::androidFramework_isClipAA() const {
1542a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    bool containsAA = false;
1543a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
1544a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    FOR_EACH_TOP_DEVICE(containsAA |= device->onClipIsAA());
1545a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
1546a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    return containsAA;
1547a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed}
1548a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
1549a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedclass RgnAccumulator {
1550a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    SkRegion* fRgn;
1551a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedpublic:
1552a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    RgnAccumulator(SkRegion* total) : fRgn(total) {}
1553a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void accumulate(SkBaseDevice* device, SkRegion* rgn) {
1554a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        SkIPoint origin = device->getOrigin();
1555a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        if (origin.x() | origin.y()) {
1556a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            rgn->translate(origin.x(), origin.y());
1557a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        }
1558a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        fRgn->op(*rgn, SkRegion::kUnion_Op);
1559a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    }
1560a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed};
1561a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
1562a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedvoid SkCanvas::temporary_internal_getRgnClip(SkRegion* rgn) {
1563a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    RgnAccumulator accum(rgn);
1564a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    SkRegion tmp;
1565a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
1566a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    rgn->setEmpty();
1567a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    FOR_EACH_TOP_DEVICE(device->onAsRgnClip(&tmp); accum.accumulate(device, &tmp));
156890c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com}
156990c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com
15705c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com///////////////////////////////////////////////////////////////////////////////
15715c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1572754de5f65b466f721d952a379194cc94de376f42reed@google.combool SkCanvas::isClipEmpty() const {
157302be3c1c3f53858263df82b1db466b5bb7059ab0Mike Reed    return fMCRec->fRasterClip.isEmpty();
157402be3c1c3f53858263df82b1db466b5bb7059ab0Mike Reed
157502be3c1c3f53858263df82b1db466b5bb7059ab0Mike Reed    // TODO: should we only use the conservative answer in a recording canvas?
157602be3c1c3f53858263df82b1db466b5bb7059ab0Mike Reed#if 0
1577a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    SkBaseDevice* dev = this->getTopDevice();
1578a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    // if no device we return true
1579a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    return !dev || dev->onGetClipType() == SkBaseDevice::kEmpty_ClipType;
158002be3c1c3f53858263df82b1db466b5bb7059ab0Mike Reed#endif
1581754de5f65b466f721d952a379194cc94de376f42reed@google.com}
1582754de5f65b466f721d952a379194cc94de376f42reed@google.com
15835c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgbool SkCanvas::isClipRect() const {
1584a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    SkBaseDevice* dev = this->getTopDevice();
1585a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    // if no device we return false
1586a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    return dev && dev->onGetClipType() == SkBaseDevice::kRect_ClipType;
15875c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
15885c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
1589fbfa25802709139c2f14e304319c9541da65ca27msarettstatic inline bool is_nan_or_clipped(const Sk4f& devRect, const Sk4f& devClip) {
1590fbfa25802709139c2f14e304319c9541da65ca27msarett#if !defined(SKNX_NO_SIMD) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
1591fbfa25802709139c2f14e304319c9541da65ca27msarett    __m128 lLtT = _mm_unpacklo_ps(devRect.fVec, devClip.fVec);
1592fbfa25802709139c2f14e304319c9541da65ca27msarett    __m128 RrBb = _mm_unpackhi_ps(devClip.fVec, devRect.fVec);
1593fbfa25802709139c2f14e304319c9541da65ca27msarett    __m128 mask = _mm_cmplt_ps(lLtT, RrBb);
1594fbfa25802709139c2f14e304319c9541da65ca27msarett    return 0xF != _mm_movemask_ps(mask);
1595fbfa25802709139c2f14e304319c9541da65ca27msarett#elif !defined(SKNX_NO_SIMD) && defined(SK_ARM_HAS_NEON)
1596fbfa25802709139c2f14e304319c9541da65ca27msarett    float32x4_t lLtT = vzipq_f32(devRect.fVec, devClip.fVec).val[0];
1597fbfa25802709139c2f14e304319c9541da65ca27msarett    float32x4_t RrBb = vzipq_f32(devClip.fVec, devRect.fVec).val[1];
1598fbfa25802709139c2f14e304319c9541da65ca27msarett    uint32x4_t mask = vcltq_f32(lLtT, RrBb);
1599fbfa25802709139c2f14e304319c9541da65ca27msarett    return 0xFFFFFFFFFFFFFFFF != (uint64_t) vmovn_u32(mask);
1600fbfa25802709139c2f14e304319c9541da65ca27msarett#else
1601fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect devRectAsRect;
1602fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect devClipAsRect;
1603fbfa25802709139c2f14e304319c9541da65ca27msarett    devRect.store(&devRectAsRect.fLeft);
1604fbfa25802709139c2f14e304319c9541da65ca27msarett    devClip.store(&devClipAsRect.fLeft);
1605fbfa25802709139c2f14e304319c9541da65ca27msarett    return !devRectAsRect.isFinite() || !devRectAsRect.intersect(devClipAsRect);
1606fbfa25802709139c2f14e304319c9541da65ca27msarett#endif
1607fbfa25802709139c2f14e304319c9541da65ca27msarett}
1608fbfa25802709139c2f14e304319c9541da65ca27msarett
1609fbfa25802709139c2f14e304319c9541da65ca27msarett// It's important for this function to not be inlined.  Otherwise the compiler will share code
1610fbfa25802709139c2f14e304319c9541da65ca27msarett// between the fast path and the slow path, resulting in two slow paths.
1611fbfa25802709139c2f14e304319c9541da65ca27msarettstatic SK_NEVER_INLINE bool quick_reject_slow_path(const SkRect& src, const SkRect& deviceClip,
1612fbfa25802709139c2f14e304319c9541da65ca27msarett                                                   const SkMatrix& matrix) {
1613fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect deviceRect;
1614fbfa25802709139c2f14e304319c9541da65ca27msarett    matrix.mapRect(&deviceRect, src);
1615fbfa25802709139c2f14e304319c9541da65ca27msarett    return !deviceRect.isFinite() || !deviceRect.intersect(deviceClip);
1616fbfa25802709139c2f14e304319c9541da65ca27msarett}
1617d22a817ff57986407facd16af36320fc86ce02damsarett
1618fbfa25802709139c2f14e304319c9541da65ca27msarettbool SkCanvas::quickReject(const SkRect& src) const {
1619fbfa25802709139c2f14e304319c9541da65ca27msarett#ifdef SK_DEBUG
1620fbfa25802709139c2f14e304319c9541da65ca27msarett    // Verify that fDeviceClipBounds are set properly.
1621fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect tmp = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
16221f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fRasterClip.isEmpty()) {
16230c685ee188a5e500df25a34fa6edfceb4cbb795cmsarett        SkASSERT(fDeviceClipBounds.isEmpty());
1624fbfa25802709139c2f14e304319c9541da65ca27msarett    } else {
1625fbfa25802709139c2f14e304319c9541da65ca27msarett        SkASSERT(tmp == fDeviceClipBounds);
16268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16289637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    // Verify that fIsScaleTranslate is set properly.
16299637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
1630fbfa25802709139c2f14e304319c9541da65ca27msarett#endif
1631d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
16329637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    if (!fIsScaleTranslate) {
1633fbfa25802709139c2f14e304319c9541da65ca27msarett        return quick_reject_slow_path(src, fDeviceClipBounds, fMCRec->fMatrix);
16348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1635fbfa25802709139c2f14e304319c9541da65ca27msarett
1636fbfa25802709139c2f14e304319c9541da65ca27msarett    // We inline the implementation of mapScaleTranslate() for the fast path.
1637fbfa25802709139c2f14e304319c9541da65ca27msarett    float sx = fMCRec->fMatrix.getScaleX();
1638fbfa25802709139c2f14e304319c9541da65ca27msarett    float sy = fMCRec->fMatrix.getScaleY();
1639fbfa25802709139c2f14e304319c9541da65ca27msarett    float tx = fMCRec->fMatrix.getTranslateX();
1640fbfa25802709139c2f14e304319c9541da65ca27msarett    float ty = fMCRec->fMatrix.getTranslateY();
1641fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f scale(sx, sy, sx, sy);
1642fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f trans(tx, ty, tx, ty);
1643fbfa25802709139c2f14e304319c9541da65ca27msarett
1644fbfa25802709139c2f14e304319c9541da65ca27msarett    // Apply matrix.
1645fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f ltrb = Sk4f::Load(&src.fLeft) * scale + trans;
1646fbfa25802709139c2f14e304319c9541da65ca27msarett
1647fbfa25802709139c2f14e304319c9541da65ca27msarett    // Make sure left < right, top < bottom.
1648fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f rblt(ltrb[2], ltrb[3], ltrb[0], ltrb[1]);
1649fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f min = Sk4f::Min(ltrb, rblt);
1650fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f max = Sk4f::Max(ltrb, rblt);
1651fbfa25802709139c2f14e304319c9541da65ca27msarett    // We can extract either pair [0,1] or [2,3] from min and max and be correct, but on
1652fbfa25802709139c2f14e304319c9541da65ca27msarett    // ARM this sequence generates the fastest (a single instruction).
1653fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f devRect = Sk4f(min[2], min[3], max[0], max[1]);
1654fbfa25802709139c2f14e304319c9541da65ca27msarett
1655fbfa25802709139c2f14e304319c9541da65ca27msarett    // Check if the device rect is NaN or outside the clip.
1656fbfa25802709139c2f14e304319c9541da65ca27msarett    return is_nan_or_clipped(devRect, Sk4f::Load(&fDeviceClipBounds.fLeft));
16578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16593b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkPath& path) const {
16603b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com    return path.isEmpty() || this->quickReject(path.getBounds());
16618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
166342e8c53b3ef58f887a623b410d9783b4d4ab4921Mike ReedSkRect SkCanvas::onGetLocalClipBounds() const {
166442e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    SkIRect ibounds = this->onGetDeviceClipBounds();
1665918e144408ba218df919528f8b48c544f4767883Mike Reed    if (ibounds.isEmpty()) {
166642e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed        return SkRect::MakeEmpty();
16678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1669d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    SkMatrix inverse;
1670d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    // if we can't invert the CTM, we can't return local clip bounds
16711f836ee096bb988adef4b9757b2629c7afeda36dreed    if (!fMCRec->fMatrix.invert(&inverse)) {
167242e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed        return SkRect::MakeEmpty();
1673d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    }
1674d9c0f0b57affec7a472879c5919acac6637d926areed@android.com
167542e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    SkRect bounds;
167642e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    SkRect r;
167742e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    // adjust it outwards in case we are antialiasing
167842e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    const int inset = 1;
1679fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com
168042e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
168142e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed           ibounds.fRight + inset, ibounds.fBottom + inset);
168242e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    inverse.mapRect(&bounds, r);
168342e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    return bounds;
16848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
168642e8c53b3ef58f887a623b410d9783b4d4ab4921Mike ReedSkIRect SkCanvas::onGetDeviceClipBounds() const {
1687a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    return fMCRec->fRasterClip.getBounds();
1688bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com}
1689bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
16908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const {
16911f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fMatrix;
16928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16941105224f9701e57ec5ce0354d6a380b664f5c638Brian OsmanGrRenderTargetContext* SkCanvas::internal_private_accessTopLayerRenderTargetContext() {
16959c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
16961105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman    return dev ? dev->accessRenderTargetContext() : nullptr;
16979c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
16989c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1699644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.orgGrContext* SkCanvas::getGrContext() {
1700644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
170186ae3d161412961c27a406465b0ec5749cc2e753reed    return device ? device->context() : nullptr;
1702644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org}
1703e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
1704ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1705ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                          const SkPaint& paint) {
17069881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()");
1707ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (outer.isEmpty()) {
1708ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1709ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1710ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (inner.isEmpty()) {
1711ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        this->drawRRect(outer, paint);
1712ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1713ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1714ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1715ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // We don't have this method (yet), but technically this is what we should
1716e0b728726d3b44bf18219b8c5bc5599332be7c34Cary Clark    // be able to return ...
1717e0b728726d3b44bf18219b8c5bc5599332be7c34Cary Clark    // if (!outer.contains(inner))) {
1718ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    //
1719ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // For now at least check for containment of bounds
1720e0b728726d3b44bf18219b8c5bc5599332be7c34Cary Clark    if (!outer.getBounds().contains(inner.getBounds())) {
1721e0b728726d3b44bf18219b8c5bc5599332be7c34Cary Clark        return;
1722e0b728726d3b44bf18219b8c5bc5599332be7c34Cary Clark    }
1723ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1724ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->onDrawDRRect(outer, inner, paint);
1725ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
1726ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
172741af966ab338e95eee81ab618ab28195075338f7reed// These need to stop being virtual -- clients need to override the onDraw... versions
172841af966ab338e95eee81ab618ab28195075338f7reed
172941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPaint(const SkPaint& paint) {
173041af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPaint(paint);
173141af966ab338e95eee81ab618ab28195075338f7reed}
173241af966ab338e95eee81ab618ab28195075338f7reed
173341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
173441af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawRect(r, paint);
173541af966ab338e95eee81ab618ab28195075338f7reed}
173641af966ab338e95eee81ab618ab28195075338f7reed
1737dca352e2d42cfe698573947b3d11abc1eaade160msarettvoid SkCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
1738dca352e2d42cfe698573947b3d11abc1eaade160msarett    if (region.isEmpty()) {
1739dca352e2d42cfe698573947b3d11abc1eaade160msarett        return;
1740dca352e2d42cfe698573947b3d11abc1eaade160msarett    }
1741dca352e2d42cfe698573947b3d11abc1eaade160msarett
1742dca352e2d42cfe698573947b3d11abc1eaade160msarett    if (region.isRect()) {
1743dca352e2d42cfe698573947b3d11abc1eaade160msarett        return this->drawIRect(region.getBounds(), paint);
1744dca352e2d42cfe698573947b3d11abc1eaade160msarett    }
1745dca352e2d42cfe698573947b3d11abc1eaade160msarett
1746dca352e2d42cfe698573947b3d11abc1eaade160msarett    this->onDrawRegion(region, paint);
1747dca352e2d42cfe698573947b3d11abc1eaade160msarett}
1748dca352e2d42cfe698573947b3d11abc1eaade160msarett
174941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) {
175041af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawOval(r, paint);
175141af966ab338e95eee81ab618ab28195075338f7reed}
175241af966ab338e95eee81ab618ab28195075338f7reed
175341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
175441af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawRRect(rrect, paint);
175541af966ab338e95eee81ab618ab28195075338f7reed}
175641af966ab338e95eee81ab618ab28195075338f7reed
175741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
175841af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPoints(mode, count, pts, paint);
175941af966ab338e95eee81ab618ab28195075338f7reed}
176041af966ab338e95eee81ab618ab28195075338f7reed
1761e88a1cb20e6b4c9f099070112225a88693a4630bMike Reedvoid SkCanvas::drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode,
1762e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed                            const SkPaint& paint) {
1763e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    RETURN_ON_NULL(vertices);
1764e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    this->onDrawVerticesObject(vertices.get(), mode, paint);
1765e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed}
1766e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed
1767e88a1cb20e6b4c9f099070112225a88693a4630bMike Reedvoid SkCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) {
1768199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    RETURN_ON_NULL(vertices);
1769e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    this->onDrawVerticesObject(vertices, mode, paint);
177041af966ab338e95eee81ab618ab28195075338f7reed}
177141af966ab338e95eee81ab618ab28195075338f7reed
177241af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
177341af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPath(path, paint);
177441af966ab338e95eee81ab618ab28195075338f7reed}
177541af966ab338e95eee81ab618ab28195075338f7reed
1776a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
1777e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
1778a85d4d0814818e4ddabb9237da209d61d6cd5854reed    this->onDrawImage(image, x, y, paint);
177941af966ab338e95eee81ab618ab28195075338f7reed}
178041af966ab338e95eee81ab618ab28195075338f7reed
1781e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
1782e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             const SkPaint* paint, SrcRectConstraint constraint) {
1783e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
1784e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (dst.isEmpty() || src.isEmpty()) {
1785e47829b6b1eeb6b0c97ccb3df3016d197046824creed        return;
1786e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
1787e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->onDrawImageRect(image, &src, dst, paint, constraint);
1788e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
178941af966ab338e95eee81ab618ab28195075338f7reed
179084984efeb64787b88c5f8bd6929cfe2d58a3ba06reedvoid SkCanvas::drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
179184984efeb64787b88c5f8bd6929cfe2d58a3ba06reed                             const SkPaint* paint, SrcRectConstraint constraint) {
1792e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
1793e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawImageRect(image, SkRect::Make(isrc), dst, paint, constraint);
179484984efeb64787b88c5f8bd6929cfe2d58a3ba06reed}
179584984efeb64787b88c5f8bd6929cfe2d58a3ba06reed
1796e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
1797e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             SrcRectConstraint constraint) {
1798e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
1799e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), dst, paint,
1800e47829b6b1eeb6b0c97ccb3df3016d197046824creed                        constraint);
1801e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1802e47829b6b1eeb6b0c97ccb3df3016d197046824creed
18034c21dc5ddf3b482293ed34eead876d8d61a662c3reedvoid SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
18044c21dc5ddf3b482293ed34eead876d8d61a662c3reed                             const SkPaint* paint) {
1805e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
18064c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (dst.isEmpty()) {
18074c21dc5ddf3b482293ed34eead876d8d61a662c3reed        return;
18084c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
1809552bca9afadd81d263041d04e2605d8d897940b6msarett    if (SkLatticeIter::Valid(image->width(), image->height(), center)) {
1810552bca9afadd81d263041d04e2605d8d897940b6msarett        this->onDrawImageNine(image, center, dst, paint);
1811552bca9afadd81d263041d04e2605d8d897940b6msarett    } else {
1812e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, dst, paint);
18134c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
18144c21dc5ddf3b482293ed34eead876d8d61a662c3reed}
18154c21dc5ddf3b482293ed34eead876d8d61a662c3reed
1816168820625c35a8c19f66c661efcbce7a5e334837msarettvoid SkCanvas::drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
1817168820625c35a8c19f66c661efcbce7a5e334837msarett                                const SkPaint* paint) {
1818168820625c35a8c19f66c661efcbce7a5e334837msarett    RETURN_ON_NULL(image);
1819168820625c35a8c19f66c661efcbce7a5e334837msarett    if (dst.isEmpty()) {
1820168820625c35a8c19f66c661efcbce7a5e334837msarett        return;
1821168820625c35a8c19f66c661efcbce7a5e334837msarett    }
182271df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett
182371df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    SkIRect bounds;
182471df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    Lattice latticePlusBounds = lattice;
182571df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    if (!latticePlusBounds.fBounds) {
182671df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        bounds = SkIRect::MakeWH(image->width(), image->height());
182771df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        latticePlusBounds.fBounds = &bounds;
182871df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    }
182971df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett
183071df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    if (SkLatticeIter::Valid(image->width(), image->height(), latticePlusBounds)) {
183171df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        this->onDrawImageLattice(image, latticePlusBounds, dst, paint);
1832168820625c35a8c19f66c661efcbce7a5e334837msarett    } else {
1833168820625c35a8c19f66c661efcbce7a5e334837msarett        this->drawImageRect(image, dst, paint);
1834168820625c35a8c19f66c661efcbce7a5e334837msarett    }
1835168820625c35a8c19f66c661efcbce7a5e334837msarett}
1836168820625c35a8c19f66c661efcbce7a5e334837msarett
183741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
18384c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing()) {
18392df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
18402df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
184141af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawBitmap(bitmap, dx, dy, paint);
184241af966ab338e95eee81ab618ab28195075338f7reed}
184341af966ab338e95eee81ab618ab28195075338f7reed
1844e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
1845a5517e2b190a8083b38964972b031c13e99f1012reed                              const SkPaint* paint, SrcRectConstraint constraint) {
1846e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (bitmap.drawsNothing() || dst.isEmpty() || src.isEmpty()) {
1847a5517e2b190a8083b38964972b031c13e99f1012reed        return;
1848a5517e2b190a8083b38964972b031c13e99f1012reed    }
1849e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->onDrawBitmapRect(bitmap, &src, dst, paint, constraint);
185041af966ab338e95eee81ab618ab28195075338f7reed}
185141af966ab338e95eee81ab618ab28195075338f7reed
185284984efeb64787b88c5f8bd6929cfe2d58a3ba06reedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
185384984efeb64787b88c5f8bd6929cfe2d58a3ba06reed                              const SkPaint* paint, SrcRectConstraint constraint) {
1854e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawBitmapRect(bitmap, SkRect::Make(isrc), dst, paint, constraint);
1855e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1856e47829b6b1eeb6b0c97ccb3df3016d197046824creed
1857e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
1858e47829b6b1eeb6b0c97ccb3df3016d197046824creed                              SrcRectConstraint constraint) {
1859e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, paint,
1860e47829b6b1eeb6b0c97ccb3df3016d197046824creed                         constraint);
186184984efeb64787b88c5f8bd6929cfe2d58a3ba06reed}
186284984efeb64787b88c5f8bd6929cfe2d58a3ba06reed
186341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
186441af966ab338e95eee81ab618ab28195075338f7reed                              const SkPaint* paint) {
18654c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing() || dst.isEmpty()) {
18662df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
18672df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
1868552bca9afadd81d263041d04e2605d8d897940b6msarett    if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), center)) {
1869552bca9afadd81d263041d04e2605d8d897940b6msarett        this->onDrawBitmapNine(bitmap, center, dst, paint);
1870552bca9afadd81d263041d04e2605d8d897940b6msarett    } else {
1871a5517e2b190a8083b38964972b031c13e99f1012reed        this->drawBitmapRect(bitmap, dst, paint);
18724c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
187341af966ab338e95eee81ab618ab28195075338f7reed}
187441af966ab338e95eee81ab618ab28195075338f7reed
1875c573a40ed5024b463e47088d307e3164a486dba5msarettvoid SkCanvas::drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
1876c573a40ed5024b463e47088d307e3164a486dba5msarett                                 const SkPaint* paint) {
1877168820625c35a8c19f66c661efcbce7a5e334837msarett    if (bitmap.drawsNothing() || dst.isEmpty()) {
1878c573a40ed5024b463e47088d307e3164a486dba5msarett        return;
1879c573a40ed5024b463e47088d307e3164a486dba5msarett    }
188071df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett
188171df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    SkIRect bounds;
188271df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    Lattice latticePlusBounds = lattice;
188371df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    if (!latticePlusBounds.fBounds) {
188471df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        bounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
188571df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        latticePlusBounds.fBounds = &bounds;
188671df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    }
188771df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett
188871df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), latticePlusBounds)) {
188971df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        this->onDrawBitmapLattice(bitmap, latticePlusBounds, dst, paint);
1890552bca9afadd81d263041d04e2605d8d897940b6msarett    } else {
1891168820625c35a8c19f66c661efcbce7a5e334837msarett        this->drawBitmapRect(bitmap, dst, paint);
1892c573a40ed5024b463e47088d307e3164a486dba5msarett    }
1893c573a40ed5024b463e47088d307e3164a486dba5msarett}
1894c573a40ed5024b463e47088d307e3164a486dba5msarett
189571c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
18967d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                         const SkColor colors[], int count, SkBlendMode mode,
189771c3c760a83123ee0b3127b8c65c6394ce541c50reed                         const SkRect* cull, const SkPaint* paint) {
1898e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(atlas);
189971c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (count <= 0) {
190071c3c760a83123ee0b3127b8c65c6394ce541c50reed        return;
190171c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
1902c485907f0420e5f9cf8223e9ba53812cd8dd5368Joe Gregorio    SkASSERT(atlas);
190371c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(tex);
1904faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed    this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
190571c3c760a83123ee0b3127b8c65c6394ce541c50reed}
190671c3c760a83123ee0b3127b8c65c6394ce541c50reed
1907f70b531daaf47db1ee95c70da9843f1dd1f418d3reedvoid SkCanvas::drawAnnotation(const SkRect& rect, const char key[], SkData* value) {
1908f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    if (key) {
1909f70b531daaf47db1ee95c70da9843f1dd1f418d3reed        this->onDrawAnnotation(rect, key, value);
1910f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    }
1911f70b531daaf47db1ee95c70da9843f1dd1f418d3reed}
1912f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
1913e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1914e47829b6b1eeb6b0c97ccb3df3016d197046824creed                                    const SkPaint* paint, SrcRectConstraint constraint) {
1915e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (src) {
1916e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, *src, dst, paint, constraint);
1917e47829b6b1eeb6b0c97ccb3df3016d197046824creed    } else {
1918e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()),
1919e47829b6b1eeb6b0c97ccb3df3016d197046824creed                            dst, paint, constraint);
1920e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
1921e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1922e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1923e47829b6b1eeb6b0c97ccb3df3016d197046824creed                                     const SkPaint* paint, SrcRectConstraint constraint) {
1924e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (src) {
1925e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawBitmapRect(bitmap, *src, dst, paint, constraint);
1926e47829b6b1eeb6b0c97ccb3df3016d197046824creed    } else {
1927e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()),
1928e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             dst, paint, constraint);
1929e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
1930e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1931e47829b6b1eeb6b0c97ccb3df3016d197046824creed
1932cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudsonvoid SkCanvas::temporary_internal_describeTopLayer(SkMatrix* matrix, SkIRect* clip_bounds) {
1933cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson    SkIRect layer_bounds = this->getTopLayerBounds();
1934cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson    if (matrix) {
1935cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson        *matrix = this->getTotalMatrix();
1936cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson        matrix->preTranslate(-layer_bounds.left(), -layer_bounds.top());
1937cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson    }
1938cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson    if (clip_bounds) {
1939918e144408ba218df919528f8b48c544f4767883Mike Reed        *clip_bounds = this->getDeviceClipBounds();
1940cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson        clip_bounds->offset(-layer_bounds.left(), -layer_bounds.top());
1941cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson    }
1942cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson}
1943cb3bd18a4b787f6281930dbe49e1c430f28a367ctomhudson
19448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
19458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  These are the virtual drawing methods
19468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
19478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
194828361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.orgvoid SkCanvas::onDiscard() {
194949f085dddff10473b6ebf832a974288300224e60bsalomon    if (fSurfaceBase) {
195028361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
195128361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    }
195228361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org}
195328361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org
195441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPaint(const SkPaint& paint) {
19559881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()");
1956fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    this->internalDrawPaint(paint);
1957fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com}
1958fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
1959fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comvoid SkCanvas::internalDrawPaint(const SkPaint& paint) {
196096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, nullptr, false)
19618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
1963a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawPaint(looper.paint());
19648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19664e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
19678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
196941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
197041af966ab338e95eee81ab618ab28195075338f7reed                            const SkPaint& paint) {
19719881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count));
19728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if ((long)count <= 0) {
19738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
19748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1976822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    SkRect r;
197796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
1978a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com    if (paint.canComputeFastBounds()) {
1979a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        // special-case 2 points (common for drawing a single line)
1980a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        if (2 == count) {
1981a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            r.set(pts[0], pts[1]);
1982a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        } else {
1983a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org            r.set(pts, SkToInt(count));
1984a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
1985822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
198687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) {
198787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
198887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
198987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &r;
1990fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
1991a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com
199296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkASSERT(pts != nullptr);
19938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
199478cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
19954b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
19968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
1997a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawPoints(mode, count, pts, looper.paint());
19988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19994b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
20004e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
20018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20034a16717bc7aa471fad10ec3157774771a76e5106reedstatic bool needs_autodrawlooper(SkCanvas* canvas, const SkPaint& paint) {
20044a16717bc7aa471fad10ec3157774771a76e5106reed    return ((intptr_t)paint.getImageFilter()    |
20054a16717bc7aa471fad10ec3157774771a76e5106reed#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
20064a16717bc7aa471fad10ec3157774771a76e5106reed            (intptr_t)canvas->getDrawFilter()   |
20074a16717bc7aa471fad10ec3157774771a76e5106reed#endif
20084a16717bc7aa471fad10ec3157774771a76e5106reed            (intptr_t)paint.getLooper()         ) != 0;
20094a16717bc7aa471fad10ec3157774771a76e5106reed}
20104a16717bc7aa471fad10ec3157774771a76e5106reed
201141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
20129881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()");
20138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.canComputeFastBounds()) {
20148432808ad8898ac7137bc7ce1d9df6005e866401reed        // Skia will draw an inverted rect, because it explicitly "sorts" it downstream.
20158432808ad8898ac7137bc7ce1d9df6005e866401reed        // To prevent accidental rejecting at this stage, we have to sort it before we check.
20168432808ad8898ac7137bc7ce1d9df6005e866401reed        SkRect tmp(r);
20178432808ad8898ac7137bc7ce1d9df6005e866401reed        tmp.sort();
20188432808ad8898ac7137bc7ce1d9df6005e866401reed
2019822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
202087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(tmp, &storage))) {
202187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
202287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
20238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20244b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
20254a16717bc7aa471fad10ec3157774771a76e5106reed    if (needs_autodrawlooper(this, paint)) {
2026822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, &r, false)
20278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20284a16717bc7aa471fad10ec3157774771a76e5106reed        while (iter.next()) {
2029a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->drawRect(r, looper.paint());
20304a16717bc7aa471fad10ec3157774771a76e5106reed        }
20318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20324a16717bc7aa471fad10ec3157774771a76e5106reed        LOOPER_END
20334a16717bc7aa471fad10ec3157774771a76e5106reed    } else {
2034822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        this->predrawNotify(&r, &paint, false);
20354a16717bc7aa471fad10ec3157774771a76e5106reed        SkDrawIter iter(this);
20364a16717bc7aa471fad10ec3157774771a76e5106reed        while (iter.next()) {
2037a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->drawRect(r, paint);
20384a16717bc7aa471fad10ec3157774771a76e5106reed        }
20394a16717bc7aa471fad10ec3157774771a76e5106reed    }
20408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
204244df651ebefc284acc2f66425dff3ea0b0e14b36msarettvoid SkCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
204344df651ebefc284acc2f66425dff3ea0b0e14b36msarett    SkRect regionRect = SkRect::Make(region.getBounds());
204444df651ebefc284acc2f66425dff3ea0b0e14b36msarett    if (paint.canComputeFastBounds()) {
2045822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
204644df651ebefc284acc2f66425dff3ea0b0e14b36msarett        if (this->quickReject(paint.computeFastBounds(regionRect, &storage))) {
204744df651ebefc284acc2f66425dff3ea0b0e14b36msarett            return;
204844df651ebefc284acc2f66425dff3ea0b0e14b36msarett        }
204944df651ebefc284acc2f66425dff3ea0b0e14b36msarett    }
205044df651ebefc284acc2f66425dff3ea0b0e14b36msarett
2051822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, &regionRect)
205244df651ebefc284acc2f66425dff3ea0b0e14b36msarett
205344df651ebefc284acc2f66425dff3ea0b0e14b36msarett    while (iter.next()) {
2054a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawRegion(region, looper.paint());
205544df651ebefc284acc2f66425dff3ea0b0e14b36msarett    }
205644df651ebefc284acc2f66425dff3ea0b0e14b36msarett
205744df651ebefc284acc2f66425dff3ea0b0e14b36msarett    LOOPER_END
205844df651ebefc284acc2f66425dff3ea0b0e14b36msarett}
205944df651ebefc284acc2f66425dff3ea0b0e14b36msarett
206041af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
20619881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()");
20624ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
2063822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
206487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
206587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
206687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
20674ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
2068306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
2069822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
207046d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
207146d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    while (iter.next()) {
2072a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawOval(oval, looper.paint());
207346d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    }
207446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
207546d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    LOOPER_END
20764ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
20774ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
2078ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomonvoid SkCanvas::onDrawArc(const SkRect& oval, SkScalar startAngle,
2079ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon                         SkScalar sweepAngle, bool useCenter,
2080ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon                         const SkPaint& paint) {
2081ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
2082ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    if (paint.canComputeFastBounds()) {
2083ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        SkRect storage;
2084ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        // Note we're using the entire oval as the bounds.
2085ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
2086ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon            return;
2087ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        }
2088ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    }
2089ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
2090822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
2091ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
2092ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    while (iter.next()) {
2093a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawArc(oval, startAngle, sweepAngle, useCenter, looper.paint());
2094ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    }
2095ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
2096ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    LOOPER_END
2097ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon}
2098ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
209941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
21009881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()");
21014ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
2102822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
210387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) {
210487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
210587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
21064ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
21074ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
21084ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
21094ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
21104ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->SkCanvas::drawRect(rrect.getBounds(), paint);
2111f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
2112f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    } else if (rrect.isOval()) {
21134ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
2114f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        this->SkCanvas::drawOval(rrect.getBounds(), paint);
2115f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
21164ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
2117f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2118822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &rrect.getBounds())
2119f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2120f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    while (iter.next()) {
2121a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawRRect(rrect, looper.paint());
2122f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    }
2123f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2124f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    LOOPER_END
21254ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
21264ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
2127822128b475c1782788f96e7a1a848d0affb878b1Mike Reedvoid SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
2128ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (paint.canComputeFastBounds()) {
2129822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
213087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(outer.getBounds(), &storage))) {
213187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
213287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
2133ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
213425c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2135822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &outer.getBounds())
213625c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2137ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    while (iter.next()) {
2138a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawDRRect(outer, inner, looper.paint());
2139ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
214025c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2141ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_END
2142ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
21434ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
214441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
21459881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()");
21469364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    if (!path.isFinite()) {
21479364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com        return;
21489364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    }
21499364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com
2150822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    const SkRect& pathBounds = path.getBounds();
2151fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
2152822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
215387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(pathBounds, &storage))) {
215487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
215587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
21568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21570b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org
2158822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    if (pathBounds.width() <= 0 && pathBounds.height() <= 0) {
21596803c219dd3be4a73e7bb5c4bb8a5b1f803624d0commit-bot@chromium.org        if (path.isInverseFillType()) {
2160fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            this->internalDrawPaint(paint);
21616651a3238dd6affa4276ada42ab613abf1d42d1dcaryclark            return;
2162fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        }
2163fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
21648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2165822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, &pathBounds)
21668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
2168a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawPath(path, looper.paint());
21698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21714e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
21728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2174262a71b7f95ce98ff3dd8dba845afbd724470903reedbool SkCanvas::canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint& paint) {
2175262a71b7f95ce98ff3dd8dba845afbd724470903reed    if (!paint.getImageFilter()) {
2176262a71b7f95ce98ff3dd8dba845afbd724470903reed        return false;
2177262a71b7f95ce98ff3dd8dba845afbd724470903reed    }
2178262a71b7f95ce98ff3dd8dba845afbd724470903reed
2179262a71b7f95ce98ff3dd8dba845afbd724470903reed    const SkMatrix& ctm = this->getTotalMatrix();
2180c7e211acd0c9201688de7ff0c9a2271c67440adffmalita    if (!SkTreatAsSprite(ctm, SkISize::Make(w, h), paint)) {
2181262a71b7f95ce98ff3dd8dba845afbd724470903reed        return false;
2182262a71b7f95ce98ff3dd8dba845afbd724470903reed    }
2183262a71b7f95ce98ff3dd8dba845afbd724470903reed
2184262a71b7f95ce98ff3dd8dba845afbd724470903reed    // Currently we can only use the filterSprite code if we are clipped to the bitmap's bounds.
2185262a71b7f95ce98ff3dd8dba845afbd724470903reed    // Once we can filter and the filter will return a result larger than itself, we should be
2186262a71b7f95ce98ff3dd8dba845afbd724470903reed    // able to remove this constraint.
2187262a71b7f95ce98ff3dd8dba845afbd724470903reed    // skbug.com/4526
2188262a71b7f95ce98ff3dd8dba845afbd724470903reed    //
2189262a71b7f95ce98ff3dd8dba845afbd724470903reed    SkPoint pt;
2190262a71b7f95ce98ff3dd8dba845afbd724470903reed    ctm.mapXY(x, y, &pt);
2191262a71b7f95ce98ff3dd8dba845afbd724470903reed    SkIRect ir = SkIRect::MakeXYWH(SkScalarRoundToInt(pt.x()), SkScalarRoundToInt(pt.y()), w, h);
2192262a71b7f95ce98ff3dd8dba845afbd724470903reed    return ir.contains(fMCRec->fRasterClip.getBounds());
2193262a71b7f95ce98ff3dd8dba845afbd724470903reed}
2194262a71b7f95ce98ff3dd8dba845afbd724470903reed
2195a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
21969881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()");
2197a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkRect bounds = SkRect::MakeXYWH(x, y,
2198a85d4d0814818e4ddabb9237da209d61d6cd5854reed                                     SkIntToScalar(image->width()), SkIntToScalar(image->height()));
219996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
220087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        SkRect tmp = bounds;
220187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (paint) {
220287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            paint->computeFastBounds(tmp, &tmp);
220387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
220487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(tmp)) {
220587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
220687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
2207a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
22089d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2209a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
221096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
2211a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2212a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2213262a71b7f95ce98ff3dd8dba845afbd724470903reed
2214a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    sk_sp<SkSpecialImage> special;
2215129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    bool drawAsSprite = this->canDrawBitmapAsSprite(x, y, image->width(), image->height(),
2216129ed1cd6d792f3f6cf563aefa9756fc6308289dreed                                                    *paint);
2217129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    if (drawAsSprite && paint->getImageFilter()) {
2218a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        special = this->getDevice()->makeSpecial(image);
2219a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        if (!special) {
2220129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            drawAsSprite = false;
2221129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        }
2222129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    }
2223129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
2224262a71b7f95ce98ff3dd8dba845afbd724470903reed    LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
2225262a71b7f95ce98ff3dd8dba845afbd724470903reed
2226a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2227262a71b7f95ce98ff3dd8dba845afbd724470903reed        const SkPaint& pnt = looper.paint();
2228a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        if (special) {
2229a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed            SkPoint pt;
2230a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->ctm().mapXY(x, y, &pt);
2231a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->drawSpecial(special.get(),
2232a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed                                      SkScalarRoundToInt(pt.fX),
2233a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed                                      SkScalarRoundToInt(pt.fY), pnt);
2234262a71b7f95ce98ff3dd8dba845afbd724470903reed        } else {
2235a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->drawImage(image, x, y, pnt);
2236262a71b7f95ce98ff3dd8dba845afbd724470903reed        }
2237a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
22389d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2239a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2240b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2241b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
224241af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
2243562fe4767cc73e08a4e039362bc0336aea66ecfbreed                               const SkPaint* paint, SrcRectConstraint constraint) {
22449881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
224596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2246c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage = dst;
224787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (paint) {
224887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            paint->computeFastBounds(dst, &storage);
224987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
225087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(storage)) {
225187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
225287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
2253a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2254a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
225596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
2256a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2257a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
22589d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2259c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2260c83a29759a5c2966da5ab973e4fd90763e4c962breed                                          image->isOpaque())
22619d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2262a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2263a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawImageRect(image, src, dst, looper.paint(), constraint);
2264a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
22659d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2266a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2267b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2268b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
226941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
22709881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()");
22718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
22728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
227333366974d43eae80e22284a2e445225c343859dareed    if (bitmap.drawsNothing()) {
227433366974d43eae80e22284a2e445225c343859dareed        return;
227533366974d43eae80e22284a2e445225c343859dareed    }
227633366974d43eae80e22284a2e445225c343859dareed
227733366974d43eae80e22284a2e445225c343859dareed    SkLazyPaint lazy;
227833366974d43eae80e22284a2e445225c343859dareed    if (nullptr == paint) {
227933366974d43eae80e22284a2e445225c343859dareed        paint = lazy.init();
228033366974d43eae80e22284a2e445225c343859dareed    }
228133366974d43eae80e22284a2e445225c343859dareed
2282822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    SkRect bounds;
2283822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    bitmap.getBounds(&bounds);
2284822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    bounds.offset(x, y);
2285822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    bool canFastBounds = paint->canComputeFastBounds();
2286822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    if (canFastBounds) {
2287822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
2288822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        if (this->quickReject(paint->computeFastBounds(bounds, &storage))) {
228987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
229087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
22918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22924b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2293a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    sk_sp<SkSpecialImage> special;
2294822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    bool drawAsSprite = canFastBounds && this->canDrawBitmapAsSprite(x, y, bitmap.width(),
2295822128b475c1782788f96e7a1a848d0affb878b1Mike Reed                                                                     bitmap.height(), *paint);
2296129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    if (drawAsSprite && paint->getImageFilter()) {
2297a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        special = this->getDevice()->makeSpecial(bitmap);
2298a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        if (!special) {
2299129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            drawAsSprite = false;
2300129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        }
2301129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    }
2302129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
2303822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    const SkMatrix matrix = SkMatrix::MakeTrans(x, y);
2304822128b475c1782788f96e7a1a848d0affb878b1Mike Reed
2305822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
230633366974d43eae80e22284a2e445225c343859dareed
230733366974d43eae80e22284a2e445225c343859dareed    while (iter.next()) {
2308262a71b7f95ce98ff3dd8dba845afbd724470903reed        const SkPaint& pnt = looper.paint();
2309a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        if (special) {
2310262a71b7f95ce98ff3dd8dba845afbd724470903reed            SkPoint pt;
2311a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->ctm().mapXY(x, y, &pt);
2312a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->drawSpecial(special.get(),
2313a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed                                      SkScalarRoundToInt(pt.fX),
2314a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed                                      SkScalarRoundToInt(pt.fY), pnt);
2315262a71b7f95ce98ff3dd8dba845afbd724470903reed        } else {
2316a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->drawBitmap(bitmap, matrix, looper.paint());
2317262a71b7f95ce98ff3dd8dba845afbd724470903reed        }
231833366974d43eae80e22284a2e445225c343859dareed    }
2319fbfa25802709139c2f14e304319c9541da65ca27msarett
232033366974d43eae80e22284a2e445225c343859dareed    LOOPER_END
23218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23239987ec3791336bad6af5cbe513564786b2df55aareed@google.com// this one is non-virtual, so it can be called safely by other canvas apis
23247112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2325eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      const SkRect& dst, const SkPaint* paint,
2326a5517e2b190a8083b38964972b031c13e99f1012reed                                      SrcRectConstraint constraint) {
232750b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing() || dst.isEmpty()) {
23288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
23298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
233074b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
233196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2332c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage;
233387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
233487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
233587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
23368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23373d60812865bb034851da777a91413ab584929887reed@google.com
233833535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    SkLazyPaint lazy;
233996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
234033535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com        paint = lazy.init();
23418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23427064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
2343c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2344c83a29759a5c2966da5ab973e4fd90763e4c962breed                                          bitmap.isOpaque())
23457064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
234633535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    while (iter.next()) {
2347a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawBitmapRect(bitmap, src, dst, looper.paint(), constraint);
2348f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
23497064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
235033535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    LOOPER_END
23518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
235341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
2354562fe4767cc73e08a4e039362bc0336aea66ecfbreed                                const SkPaint* paint, SrcRectConstraint constraint) {
23559881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()");
23569987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
2357562fe4767cc73e08a4e039362bc0336aea66ecfbreed    this->internalDrawBitmapRect(bitmap, src, dst, paint, constraint);
23589987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
23599987ec3791336bad6af5cbe513564786b2df55aareed@google.com
23604c21dc5ddf3b482293ed34eead876d8d61a662c3reedvoid SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
23614c21dc5ddf3b482293ed34eead876d8d61a662c3reed                               const SkPaint* paint) {
23624c21dc5ddf3b482293ed34eead876d8d61a662c3reed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageNine()");
23639d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
236496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2365c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage;
236687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
236787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
236887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
23693d60812865bb034851da777a91413ab584929887reed@google.com    }
23709d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
23714c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkLazyPaint lazy;
237296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
23734c21dc5ddf3b482293ed34eead876d8d61a662c3reed        paint = lazy.init();
23744c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
23759d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2376c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
23779d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
23784c21dc5ddf3b482293ed34eead876d8d61a662c3reed    while (iter.next()) {
2379a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawImageNine(image, center, dst, looper.paint());
23809987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
23819d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
23824c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_END
23839987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
23849987ec3791336bad6af5cbe513564786b2df55aareed@google.com
238541af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
238641af966ab338e95eee81ab618ab28195075338f7reed                                const SkPaint* paint) {
23879881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()");
23889987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
23899987ec3791336bad6af5cbe513564786b2df55aareed@google.com
239096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2391c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage;
239287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
239387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
239487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
23954c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
23969d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
23974c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkLazyPaint lazy;
239896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
23994c21dc5ddf3b482293ed34eead876d8d61a662c3reed        paint = lazy.init();
24004c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
24019d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2402c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
24039d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
24044c21dc5ddf3b482293ed34eead876d8d61a662c3reed    while (iter.next()) {
2405a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawBitmapNine(bitmap, center, dst, looper.paint());
24064c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
24079d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
24084c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_END
24099987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
24109987ec3791336bad6af5cbe513564786b2df55aareed@google.com
2411168820625c35a8c19f66c661efcbce7a5e334837msarettvoid SkCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
2412168820625c35a8c19f66c661efcbce7a5e334837msarett                                  const SkPaint* paint) {
2413168820625c35a8c19f66c661efcbce7a5e334837msarett    if (nullptr == paint || paint->canComputeFastBounds()) {
2414168820625c35a8c19f66c661efcbce7a5e334837msarett        SkRect storage;
2415168820625c35a8c19f66c661efcbce7a5e334837msarett        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2416168820625c35a8c19f66c661efcbce7a5e334837msarett            return;
2417168820625c35a8c19f66c661efcbce7a5e334837msarett        }
2418168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2419168820625c35a8c19f66c661efcbce7a5e334837msarett
2420168820625c35a8c19f66c661efcbce7a5e334837msarett    SkLazyPaint lazy;
2421168820625c35a8c19f66c661efcbce7a5e334837msarett    if (nullptr == paint) {
2422168820625c35a8c19f66c661efcbce7a5e334837msarett        paint = lazy.init();
2423168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2424168820625c35a8c19f66c661efcbce7a5e334837msarett
2425168820625c35a8c19f66c661efcbce7a5e334837msarett    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2426168820625c35a8c19f66c661efcbce7a5e334837msarett
2427168820625c35a8c19f66c661efcbce7a5e334837msarett    while (iter.next()) {
2428a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawImageLattice(image, lattice, dst, looper.paint());
2429168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2430168820625c35a8c19f66c661efcbce7a5e334837msarett
2431168820625c35a8c19f66c661efcbce7a5e334837msarett    LOOPER_END
2432168820625c35a8c19f66c661efcbce7a5e334837msarett}
2433168820625c35a8c19f66c661efcbce7a5e334837msarett
2434168820625c35a8c19f66c661efcbce7a5e334837msarettvoid SkCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
2435168820625c35a8c19f66c661efcbce7a5e334837msarett                                   const SkRect& dst, const SkPaint* paint) {
2436168820625c35a8c19f66c661efcbce7a5e334837msarett    if (nullptr == paint || paint->canComputeFastBounds()) {
2437168820625c35a8c19f66c661efcbce7a5e334837msarett        SkRect storage;
2438168820625c35a8c19f66c661efcbce7a5e334837msarett        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2439168820625c35a8c19f66c661efcbce7a5e334837msarett            return;
2440168820625c35a8c19f66c661efcbce7a5e334837msarett        }
2441168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2442168820625c35a8c19f66c661efcbce7a5e334837msarett
2443168820625c35a8c19f66c661efcbce7a5e334837msarett    SkLazyPaint lazy;
2444168820625c35a8c19f66c661efcbce7a5e334837msarett    if (nullptr == paint) {
2445168820625c35a8c19f66c661efcbce7a5e334837msarett        paint = lazy.init();
2446168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2447168820625c35a8c19f66c661efcbce7a5e334837msarett
2448168820625c35a8c19f66c661efcbce7a5e334837msarett    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2449168820625c35a8c19f66c661efcbce7a5e334837msarett
2450168820625c35a8c19f66c661efcbce7a5e334837msarett    while (iter.next()) {
2451a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawBitmapLattice(bitmap, lattice, dst, looper.paint());
2452168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2453168820625c35a8c19f66c661efcbce7a5e334837msarett
2454168820625c35a8c19f66c661efcbce7a5e334837msarett    LOOPER_END
2455168820625c35a8c19f66c661efcbce7a5e334837msarett}
2456168820625c35a8c19f66c661efcbce7a5e334837msarett
2457f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comclass SkDeviceFilteredPaint {
2458f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.compublic:
24591f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2460112e7e277702e104357f2d44742253ee1b0109acfmalita        uint32_t filteredFlags = device->filterTextFlags(paint);
2461112e7e277702e104357f2d44742253ee1b0109acfmalita        if (filteredFlags != paint.getFlags()) {
2462a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com            SkPaint* newPaint = fLazy.set(paint);
2463112e7e277702e104357f2d44742253ee1b0109acfmalita            newPaint->setFlags(filteredFlags);
2464f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = newPaint;
2465f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        } else {
2466f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = &paint;
2467f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        }
2468f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    }
2469f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2470f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    const SkPaint& paint() const { return *fPaint; }
2471f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2472f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comprivate:
24732c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
24742c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint     fLazy;
2475f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com};
2476f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2477e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2478e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                          const SkPaint& paint) {
247996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
24808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24824e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2483a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawText(text, byteLength, x, y, dfp.paint());
24848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24864e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
24878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2489e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2490e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                             const SkPaint& paint) {
249105c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, 0);
249205c4a4322e7d4f3417b7df33825bab8603d52051fmalita
249396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
249487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
24958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24964e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2497a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawPosText(text, byteLength, &pos->fX, 2, textOffset,
2498f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
24998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2500b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
25014e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
25028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2504e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2505e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              SkScalar constY, const SkPaint& paint) {
250605c4a4322e7d4f3417b7df33825bab8603d52051fmalita
250705c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, constY);
250805c4a4322e7d4f3417b7df33825bab8603d52051fmalita
250996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
251087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
25118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
25124e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2513a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawPosText(text, byteLength, xpos, 1, textOffset,
2514f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
25158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2516b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
25174e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
25188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2520e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2521e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                const SkMatrix* matrix, const SkPaint& paint) {
252296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
252387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
25248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
2525a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawTextOnPath(text, byteLength, path,
25264e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                     matrix, looper.paint());
25278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2528b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
2529945ec3a2bec668ca845071a65df8ec55e8f43819commit-bot@chromium.org    LOOPER_END
25304325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org}
25314325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org
253245561a0b15fe045ba272c328684c3f7ae290785areedvoid SkCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
253345561a0b15fe045ba272c328684c3f7ae290785areed                                 const SkRect* cullRect, const SkPaint& paint) {
253445561a0b15fe045ba272c328684c3f7ae290785areed    if (cullRect && this->quickReject(*cullRect)) {
253545561a0b15fe045ba272c328684c3f7ae290785areed        return;
253645561a0b15fe045ba272c328684c3f7ae290785areed    }
253745561a0b15fe045ba272c328684c3f7ae290785areed
253845561a0b15fe045ba272c328684c3f7ae290785areed    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
253945561a0b15fe045ba272c328684c3f7ae290785areed
254045561a0b15fe045ba272c328684c3f7ae290785areed    while (iter.next()) {
2541a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawTextRSXform(text, byteLength, xform, looper.paint());
254245561a0b15fe045ba272c328684c3f7ae290785areed    }
254345561a0b15fe045ba272c328684c3f7ae290785areed
254445561a0b15fe045ba272c328684c3f7ae290785areed    LOOPER_END
254545561a0b15fe045ba272c328684c3f7ae290785areed}
254645561a0b15fe045ba272c328684c3f7ae290785areed
254700d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
254800d5c2c6523321d25b32905ff4822f083a4173eefmalita                              const SkPaint& paint) {
25497ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
255085d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    SkRect storage;
255196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
255219653d1d004610b4ba07ce563a5701164e120e45fmalita    if (paint.canComputeFastBounds()) {
255385d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita        storage = blob->bounds().makeOffset(x, y);
255487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        SkRect tmp;
255587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(storage, &tmp))) {
255687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
255787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
255887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &storage;
25597ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita    }
25607ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
2561024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // We cannot filter in the looper as we normally do, because the paint is
2562024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // incomplete at this point (text-related attributes are embedded within blob run paints).
2563024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    SkDrawFilter* drawFilter = fMCRec->fFilter;
256496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fMCRec->fFilter = nullptr;
2565024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
256685d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds)
256700d5c2c6523321d25b32905ff4822f083a4173eefmalita
2568aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    while (iter.next()) {
2569aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2570a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawTextBlob(blob, x, y, dfp.paint(), drawFilter);
257100d5c2c6523321d25b32905ff4822f083a4173eefmalita    }
257200d5c2c6523321d25b32905ff4822f083a4173eefmalita
2573aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    LOOPER_END
2574024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
2575024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    fMCRec->fFilter = drawFilter;
257600d5c2c6523321d25b32905ff4822f083a4173eefmalita}
257700d5c2c6523321d25b32905ff4822f083a4173eefmalita
2578e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com// These will become non-virtual, so they always call the (virtual) onDraw... method
2579e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2580e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                        const SkPaint& paint) {
25819881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()");
2582ac09554dce518e9d4496771f648f3ae17eca857creed    if (byteLength) {
2583ac09554dce518e9d4496771f648f3ae17eca857creed        this->onDrawText(text, byteLength, x, y, paint);
2584ac09554dce518e9d4496771f648f3ae17eca857creed    }
2585e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2586e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2587e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                           const SkPaint& paint) {
25889881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()");
2589ac09554dce518e9d4496771f648f3ae17eca857creed    if (byteLength) {
2590ac09554dce518e9d4496771f648f3ae17eca857creed        this->onDrawPosText(text, byteLength, pos, paint);
2591ac09554dce518e9d4496771f648f3ae17eca857creed    }
2592e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2593e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2594e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                            SkScalar constY, const SkPaint& paint) {
25959881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()");
2596ac09554dce518e9d4496771f648f3ae17eca857creed    if (byteLength) {
2597ac09554dce518e9d4496771f648f3ae17eca857creed        this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2598ac09554dce518e9d4496771f648f3ae17eca857creed    }
2599e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2600e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2601e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              const SkMatrix* matrix, const SkPaint& paint) {
26029881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()");
2603ac09554dce518e9d4496771f648f3ae17eca857creed    if (byteLength) {
2604ac09554dce518e9d4496771f648f3ae17eca857creed        this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2605ac09554dce518e9d4496771f648f3ae17eca857creed    }
2606e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
260745561a0b15fe045ba272c328684c3f7ae290785areedvoid SkCanvas::drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
260845561a0b15fe045ba272c328684c3f7ae290785areed                               const SkRect* cullRect, const SkPaint& paint) {
260945561a0b15fe045ba272c328684c3f7ae290785areed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextRSXform()");
261045561a0b15fe045ba272c328684c3f7ae290785areed    if (byteLength) {
261145561a0b15fe045ba272c328684c3f7ae290785areed        this->onDrawTextRSXform(text, byteLength, xform, cullRect, paint);
261245561a0b15fe045ba272c328684c3f7ae290785areed    }
261345561a0b15fe045ba272c328684c3f7ae290785areed}
261400d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
261500d5c2c6523321d25b32905ff4822f083a4173eefmalita                            const SkPaint& paint) {
2616e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(blob);
26179881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()");
2618e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    this->onDrawTextBlob(blob, x, y, paint);
261900d5c2c6523321d25b32905ff4822f083a4173eefmalita}
2620e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com
2621e88a1cb20e6b4c9f099070112225a88693a4630bMike Reedvoid SkCanvas::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode,
2622e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed                                    const SkPaint& paint) {
2623199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
2624199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
2625199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon
2626199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    while (iter.next()) {
2627199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon        // In the common case of one iteration we could std::move vertices here.
26282f6b5a47a50cdd218bc3302273be3a4a71add8fbMike Reed        iter.fDevice->drawVertices(vertices, bmode, looper.paint());
2629199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    }
2630199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon
2631199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    LOOPER_END
2632199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon}
2633199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon
2634b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
26357d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                         const SkPoint texCoords[4], SkBlendMode bmode,
26367d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                         const SkPaint& paint) {
26379881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()");
263896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == cubics) {
2639b3c9d1c33caf325aada244204215eb790c228c12dandov        return;
2640b3c9d1c33caf325aada244204215eb790c228c12dandov    }
26416cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2642faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed    this->onDrawPatch(cubics, colors, texCoords, bmode, paint);
26439340c2685c0bb0e1e70008acaaf3d1448f074c38msarett}
26449340c2685c0bb0e1e70008acaaf3d1448f074c38msarett
26459340c2685c0bb0e1e70008acaaf3d1448f074c38msarettvoid SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2646faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed                           const SkPoint texCoords[4], SkBlendMode bmode,
26477d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                           const SkPaint& paint) {
2648ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // Since a patch is always within the convex hull of the control points, we discard it when its
2649ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // bounding rectangle is completely outside the current clip.
2650ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    SkRect bounds;
2651b3c9d1c33caf325aada244204215eb790c228c12dandov    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2652ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    if (this->quickReject(bounds)) {
2653ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov        return;
2654ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
26556cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
265696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
26576cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2658ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    while (iter.next()) {
2659a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawPatch(cubics, colors, texCoords, bmode, paint);
2660ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
26616cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2662ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    LOOPER_END
2663ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov}
2664ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov
2665a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) {
2666e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(dr);
2667e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (x || y) {
2668e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        SkMatrix matrix = SkMatrix::MakeTrans(x, y);
2669e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        this->onDrawDrawable(dr, &matrix);
2670e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    } else {
2671e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        this->onDrawDrawable(dr, nullptr);
2672a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    }
2673a8db72864a43ad1fbba3c2892cf5cd88060a43efreed}
2674a8db72864a43ad1fbba3c2892cf5cd88060a43efreed
2675a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2676e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(dr);
2677e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (matrix && matrix->isIdentity()) {
2678e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        matrix = nullptr;
26796a070dc06af4e9f305f9d08a69e34d18ade473cbreed    }
2680e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    this->onDrawDrawable(dr, matrix);
26816a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
26826a070dc06af4e9f305f9d08a69e34d18ade473cbreed
2683a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
26842a62e853c27cfacafd5c15ac1077cc13140589bareed    // drawable bounds are no longer reliable (e.g. android displaylist)
26852a62e853c27cfacafd5c15ac1077cc13140589bareed    // so don't use them for quick-reject
2686a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    dr->draw(this, matrix);
26876a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
26886a070dc06af4e9f305f9d08a69e34d18ade473cbreed
268971c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
2690faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed                           const SkColor colors[], int count, SkBlendMode bmode,
269171c3c760a83123ee0b3127b8c65c6394ce541c50reed                           const SkRect* cull, const SkPaint* paint) {
269271c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (cull && this->quickReject(*cull)) {
269371c3c760a83123ee0b3127b8c65c6394ce541c50reed        return;
269471c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
269571c3c760a83123ee0b3127b8c65c6394ce541c50reed
269671c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkPaint pnt;
269771c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (paint) {
269871c3c760a83123ee0b3127b8c65c6394ce541c50reed        pnt = *paint;
269971c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
27009d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
270196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr)
270271c3c760a83123ee0b3127b8c65c6394ce541c50reed    while (iter.next()) {
2703a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawAtlas(atlas, xform, tex, colors, count, bmode, pnt);
270471c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
270571c3c760a83123ee0b3127b8c65c6394ce541c50reed    LOOPER_END
270671c3c760a83123ee0b3127b8c65c6394ce541c50reed}
270771c3c760a83123ee0b3127b8c65c6394ce541c50reed
2708f70b531daaf47db1ee95c70da9843f1dd1f418d3reedvoid SkCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
2709f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    SkASSERT(key);
2710f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
2711f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    SkPaint paint;
2712f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, nullptr)
2713f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    while (iter.next()) {
2714a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawAnnotation(rect, key, value);
2715f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    }
2716f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    LOOPER_END
2717f70b531daaf47db1ee95c70da9843f1dd1f418d3reed}
2718f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
27198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
27208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual
27218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves.
27228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
27238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2724374772bd61951f01bf84fe17bf53d8867681c9aereedvoid SkCanvas::drawColor(SkColor c, SkBlendMode mode) {
27259881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()");
27268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
27278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(c);
2729374772bd61951f01bf84fe17bf53d8867681c9aereed    paint.setBlendMode(mode);
27308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
27318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
27349881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)");
27353661bc997620899695041010a750d11dbe8a972dMike Reed    const SkPoint pt = { x, y };
27368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
27378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27393661bc997620899695041010a750d11dbe8a972dMike Reedvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint) {
27409881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()");
27418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pts[2];
27424b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
27438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[0].set(x0, y0);
27448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[1].set(x1, y1);
27458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kLines_PointMode, 2, pts, paint);
27468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27483661bc997620899695041010a750d11dbe8a972dMike Reedvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint) {
27499881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()");
27508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (radius < 0) {
27518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        radius = 0;
27528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
27538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
27558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
27564ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    this->drawOval(r, paint);
27578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
27608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const SkPaint& paint) {
27619881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()");
27628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rx > 0 && ry > 0) {
27634ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        SkRRect rrect;
27644ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        rrect.setRectXY(r, rx, ry);
27654ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->drawRRect(rrect, paint);
27668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
27678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawRect(r, paint);
27688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
27698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
27728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       SkScalar sweepAngle, bool useCenter,
27738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       const SkPaint& paint) {
27749881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
277521af9ca1b1f54d9ba1de055aa8475928d5c8ecdfbsalomon    if (oval.isEmpty() || !sweepAngle) {
277621af9ca1b1f54d9ba1de055aa8475928d5c8ecdfbsalomon        return;
27778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
277821af9ca1b1f54d9ba1de055aa8475928d5c8ecdfbsalomon    this->onDrawArc(oval, startAngle, sweepAngle, useCenter, paint);
27798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
27828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPath& path, SkScalar hOffset,
27838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                SkScalar vOffset, const SkPaint& paint) {
27849881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()");
27858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix    matrix;
27864b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
27878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(hOffset, vOffset);
27888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
27898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2791f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com///////////////////////////////////////////////////////////////////////////////
27921c2c441fede0ae9573afc098017011e3439624a9reed
27931c2c441fede0ae9573afc098017011e3439624a9reed/**
27941c2c441fede0ae9573afc098017011e3439624a9reed *  This constant is trying to balance the speed of ref'ing a subpicture into a parent picture,
27951c2c441fede0ae9573afc098017011e3439624a9reed *  against the playback cost of recursing into the subpicture to get at its actual ops.
27961c2c441fede0ae9573afc098017011e3439624a9reed *
27971c2c441fede0ae9573afc098017011e3439624a9reed *  For now we pick a conservatively small value, though measurement (and other heuristics like
27981c2c441fede0ae9573afc098017011e3439624a9reed *  the type of ops contained) may justify changing this value.
27991c2c441fede0ae9573afc098017011e3439624a9reed */
28001c2c441fede0ae9573afc098017011e3439624a9reed#define kMaxPictureOpsToUnrollInsteadOfRef  1
28019b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2802d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
2803e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(picture);
2804e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed
28051c2c441fede0ae9573afc098017011e3439624a9reed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()");
2806e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (matrix && matrix->isIdentity()) {
2807e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        matrix = nullptr;
2808e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    }
2809e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) {
2810e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2811e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        picture->playback(this);
2812e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    } else {
2813e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        this->onDrawPicture(picture, matrix, paint);
2814d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
2815d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
28169b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2817d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2818d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed                             const SkPaint* paint) {
2819d028180f0310cf2b23f9744256a41697b0683e67fmalita    if (!paint || paint->canComputeFastBounds()) {
2820d028180f0310cf2b23f9744256a41697b0683e67fmalita        SkRect bounds = picture->cullRect();
2821d028180f0310cf2b23f9744256a41697b0683e67fmalita        if (paint) {
2822d028180f0310cf2b23f9744256a41697b0683e67fmalita            paint->computeFastBounds(bounds, &bounds);
2823d028180f0310cf2b23f9744256a41697b0683e67fmalita        }
2824d028180f0310cf2b23f9744256a41697b0683e67fmalita        if (matrix) {
2825d028180f0310cf2b23f9744256a41697b0683e67fmalita            matrix->mapRect(&bounds);
2826d028180f0310cf2b23f9744256a41697b0683e67fmalita        }
2827d028180f0310cf2b23f9744256a41697b0683e67fmalita        if (this->quickReject(bounds)) {
2828d028180f0310cf2b23f9744256a41697b0683e67fmalita            return;
2829d028180f0310cf2b23f9744256a41697b0683e67fmalita        }
2830d028180f0310cf2b23f9744256a41697b0683e67fmalita    }
2831d028180f0310cf2b23f9744256a41697b0683e67fmalita
2832a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2833c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips    picture->playback(this);
28348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
283695302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack#ifdef SK_EXPERIMENTAL_SHADOWING
283795302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblackvoid SkCanvas::drawShadowedPicture(const SkPicture* picture,
283895302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack                                   const SkMatrix* matrix,
2839e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack                                   const SkPaint* paint,
2840e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack                                   const SkShadowParams& params) {
284195302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    RETURN_ON_NULL(picture);
284295302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
284395302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawShadowedPicture()");
284495302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
2845e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack    this->onDrawShadowedPicture(picture, matrix, paint, params);
284695302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack}
284795302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
284895302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblackvoid SkCanvas::onDrawShadowedPicture(const SkPicture* picture,
284995302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack                                     const SkMatrix* matrix,
2850e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack                                     const SkPaint* paint,
2851e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack                                     const SkShadowParams& params) {
2852904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    if (!paint || paint->canComputeFastBounds()) {
2853904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        SkRect bounds = picture->cullRect();
2854904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        if (paint) {
2855904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack            paint->computeFastBounds(bounds, &bounds);
2856904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        }
2857904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        if (matrix) {
2858904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack            matrix->mapRect(&bounds);
2859904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        }
2860904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        if (this->quickReject(bounds)) {
2861904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack            return;
2862904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        }
2863904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    }
2864904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
2865904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2866904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
2867e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack    sk_sp<SkImage> povDepthMap;
2868e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack    sk_sp<SkImage> diffuseMap;
2869e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack
2870904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    // povDepthMap
2871904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    {
2872904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        SkLights::Builder builder;
2873772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack        builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 1.0f, 1.0f),
2874772b5ee446d7545eec4ca7d6dc9d75461e2a9c38vjiaoblack                                                     SkVector3::Make(0.0f, 0.0f, 1.0f)));
2875904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        sk_sp<SkLights> povLight = builder.finish();
2876904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
2877904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        SkImageInfo info = SkImageInfo::Make(picture->cullRect().width(),
2878904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                             picture->cullRect().height(),
2879904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                             kBGRA_8888_SkColorType,
2880904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                             kOpaque_SkAlphaType);
2881904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
2882904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        // Create a new surface (that matches the backend of canvas)
2883904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        // to create the povDepthMap
2884904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        sk_sp<SkSurface> surf(this->makeSurface(info));
2885904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
2886904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        // Wrap another SPFCanvas around the surface
2887904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas =
2888904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas());
2889904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
2890904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        // set the depth map canvas to have the light as the user's POV
2891904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        depthMapCanvas->setLights(std::move(povLight));
2892904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
2893904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        depthMapCanvas->drawPicture(picture);
2894904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        povDepthMap = surf->makeImageSnapshot();
2895904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    }
2896904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
2897904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    // diffuseMap
2898904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    {
2899904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        SkImageInfo info = SkImageInfo::Make(picture->cullRect().width(),
2900904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                             picture->cullRect().height(),
2901904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                             kBGRA_8888_SkColorType,
2902904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                             kOpaque_SkAlphaType);
2903904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
2904904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        sk_sp<SkSurface> surf(this->makeSurface(info));
2905904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        surf->getCanvas()->drawPicture(picture);
2906904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
2907904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack        diffuseMap = surf->makeImageSnapshot();
2908904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    }
2909904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
2910904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    sk_sp<SkShader> povDepthShader = povDepthMap->makeShader(SkShader::kClamp_TileMode,
2911904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                                             SkShader::kClamp_TileMode);
2912904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    sk_sp<SkShader> diffuseShader = diffuseMap->makeShader(SkShader::kClamp_TileMode,
2913904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                                           SkShader::kClamp_TileMode);
2914b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
2915b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack    // TODO: pass the depth to the shader in vertices, or uniforms
2916b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack    //       so we don't have to render depth and color separately
2917b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack    for (int i = 0; i < fLights->numLights(); ++i) {
2918b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        // skip over ambient lights; they don't cast shadows
2919b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        // lights that have shadow maps do not need updating (because lights are immutable)
2920b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        sk_sp<SkImage> depthMap;
2921b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        SkISize shMapSize;
2922b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
2923b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        if (fLights->light(i).getShadowMap() != nullptr) {
2924b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            continue;
2925b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        }
2926b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
2927b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        if (fLights->light(i).isRadial()) {
2928b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            shMapSize.fHeight = 1;
2929b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            shMapSize.fWidth = (int) picture->cullRect().width();
2930b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
2931b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkImageInfo info = SkImageInfo::Make(diffuseMap->width(), 1,
2932b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                 kBGRA_8888_SkColorType,
2933b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                 kOpaque_SkAlphaType);
2934b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
2935b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // Create new surface (that matches the backend of canvas)
2936b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // for each shadow map
2937b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            sk_sp<SkSurface> surf(this->makeSurface(info));
2938b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
2939b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // Wrap another SPFCanvas around the surface
2940b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkCanvas* depthMapCanvas = surf->getCanvas();
2941b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
2942b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkLights::Builder builder;
2943b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            builder.add(fLights->light(i));
2944b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            sk_sp<SkLights> curLight = builder.finish();
2945b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
2946b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            sk_sp<SkShader> shadowMapShader;
2947b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            shadowMapShader = SkRadialShadowMapShader::Make(
2948b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                    povDepthShader, curLight,
2949b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                    (int) picture->cullRect().width(),
2950b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                    (int) picture->cullRect().height());
2951b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
2952b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkPaint shadowMapPaint;
2953b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            shadowMapPaint.setShader(std::move(shadowMapShader));
2954b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
2955b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            depthMapCanvas->setLights(curLight);
2956b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
2957b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            depthMapCanvas->drawRect(SkRect::MakeIWH(diffuseMap->width(),
2958b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                     diffuseMap->height()),
2959b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                     shadowMapPaint);
2960b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
2961b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            depthMap = surf->makeImageSnapshot();
2962b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
2963b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        } else {
2964b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // TODO: compute the correct size of the depth map from the light properties
2965b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // TODO: maybe add a kDepth_8_SkColorType
2966b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // TODO: find actual max depth of picture
2967b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            shMapSize = SkShadowPaintFilterCanvas::ComputeDepthMapSize(
2968b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                    fLights->light(i), 255,
2969b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                    (int) picture->cullRect().width(),
2970b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                    (int) picture->cullRect().height());
2971b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
2972b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkImageInfo info = SkImageInfo::Make(shMapSize.fWidth, shMapSize.fHeight,
2973b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                 kBGRA_8888_SkColorType,
2974b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                 kOpaque_SkAlphaType);
2975b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
2976b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // Create a new surface (that matches the backend of canvas)
2977b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // for each shadow map
2978b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            sk_sp<SkSurface> surf(this->makeSurface(info));
2979b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
2980b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // Wrap another SPFCanvas around the surface
2981b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas =
2982b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                    sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas());
2983b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            depthMapCanvas->setShadowParams(params);
2984b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
2985b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // set the depth map canvas to have the light we're drawing.
2986b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkLights::Builder builder;
2987b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            builder.add(fLights->light(i));
2988b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            sk_sp<SkLights> curLight = builder.finish();
2989b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            depthMapCanvas->setLights(std::move(curLight));
2990b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
2991b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            depthMapCanvas->drawPicture(picture);
2992b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            depthMap = surf->makeImageSnapshot();
2993b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        }
2994b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
2995b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        if (params.fType == SkShadowParams::kNoBlur_ShadowType) {
2996b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            fLights->light(i).setShadowMap(std::move(depthMap));
2997b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        } else if (params.fType == SkShadowParams::kVariance_ShadowType) {
2998b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            // we blur the variance map
2999b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkPaint blurPaint;
3000b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            blurPaint.setImageFilter(SkImageFilter::MakeBlur(params.fShadowRadius,
3001b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                             params.fShadowRadius, nullptr));
3002b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3003b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            SkImageInfo blurInfo = SkImageInfo::Make(shMapSize.fWidth, shMapSize.fHeight,
3004b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                     kBGRA_8888_SkColorType,
3005b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                     kOpaque_SkAlphaType);
3006b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3007b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            sk_sp<SkSurface> blurSurf(this->makeSurface(blurInfo));
3008b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3009b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            blurSurf->getCanvas()->drawImage(std::move(depthMap), 0, 0, &blurPaint);
3010b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3011b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack            fLights->light(i).setShadowMap(blurSurf->makeImageSnapshot());
3012b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack        }
3013b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack    }
3014b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack
3015b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack    SkPaint shadowPaint;
3016904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    sk_sp<SkShader> shadowShader = SkShadowShader::Make(std::move(povDepthShader),
3017904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                                        std::move(diffuseShader),
3018b2796fdd9eab88836795d6a54cf6811af6ecdc81vjiaoblack                                                        fLights,
3019904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack                                                        diffuseMap->width(),
3020e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack                                                        diffuseMap->height(),
3021e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack                                                        params);
3022904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3023904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    shadowPaint.setShader(shadowShader);
3024904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack
3025904527d165ce98c9fbaa9c05d3890070e3132170vjiaoblack    this->drawRect(SkRect::MakeIWH(diffuseMap->width(), diffuseMap->height()), shadowPaint);
302695302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack}
302795302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack#endif
302895302da19d8b0a3bcd9d9be0e79f486760787f09vjiaoblack
30298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
30308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
30318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30323aafe111b6cc388400092851cc53bbbdfcb8a81creedSkCanvas::LayerIter::LayerIter(SkCanvas* canvas) {
303399fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert(sizeof(fStorage) >= sizeof(SkDrawIter), "fStorage_too_small");
30348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(canvas);
30368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30373aafe111b6cc388400092851cc53bbbdfcb8a81creed    fImpl = new (fStorage) SkDrawIter(canvas);
30388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
30398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
30408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() {
30428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl->~SkDrawIter();
30438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
30448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() {
30468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
30478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
30488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30491f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::LayerIter::device() const {
305099330ba6227137866a0dbd63478d36f335203ebdMike Reed    return fImpl->fDevice;
30518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
30528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const {
3054a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    return fImpl->fDevice->ctm();
30558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
30568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const {
30588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* paint = fImpl->getPaint();
305996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
30608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &fDefaultPaint;
30618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
30628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *paint;
30638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
30648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3065a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedvoid SkCanvas::LayerIter::clip(SkRegion* rgn) const {
3066a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    return fImpl->fDevice->onAsRgnClip(rgn);
3067a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed}
3068a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
30698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); }
30708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); }
307120a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
307220a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com///////////////////////////////////////////////////////////////////////////////
307320a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
30743107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.orgstatic bool supported_for_raster_canvas(const SkImageInfo& info) {
30753107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.alphaType()) {
30763107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kPremul_SkAlphaType:
30773107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kOpaque_SkAlphaType:
30783107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
30793107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
30803107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
30813107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
30823107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
30833107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.colorType()) {
30843107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kAlpha_8_SkColorType:
30853107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kRGB_565_SkColorType:
308628fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:
30879e3dbdff53f2d9957626a17a279730cda70f17bajunov        case kRGBA_F16_SkColorType:
30883107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
30893107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
30903107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
30913107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
30923107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
30933107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    return true;
30943107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org}
30953107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
30965df4934b3e40cdc378e225d1dda39f015cae9baeMike Reedstd::unique_ptr<SkCanvas> SkCanvas::MakeRasterDirect(const SkImageInfo& info, void* pixels,
30975df4934b3e40cdc378e225d1dda39f015cae9baeMike Reed                                                     size_t rowBytes) {
309842b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!supported_for_raster_canvas(info)) {
309996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
310042b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
3101eb849e5fd10cbe00cbc31307ba97fd9efca0b41bskia.committer@gmail.com
310242b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    SkBitmap bitmap;
310342b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!bitmap.installPixels(info, pixels, rowBytes)) {
310496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
310542b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
31065df4934b3e40cdc378e225d1dda39f015cae9baeMike Reed    return skstd::make_unique<SkCanvas>(bitmap);
310742b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org}
3108d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
3109d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed///////////////////////////////////////////////////////////////////////////////
3110d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
3111d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
3112a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                                                 const SkPaint* paint, const SkRect& bounds)
3113d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    : fCanvas(canvas)
3114d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    , fSaveCount(canvas->getSaveCount())
3115d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed{
311649f085dddff10473b6ebf832a974288300224e60bsalomon    if (paint) {
3117a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        SkRect newBounds = bounds;
3118d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (matrix) {
3119a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips            matrix->mapRect(&newBounds);
3120d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        }
3121a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        canvas->saveLayer(&newBounds, paint);
312249f085dddff10473b6ebf832a974288300224e60bsalomon    } else if (matrix) {
3123d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->save();
3124d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
31256cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
312649f085dddff10473b6ebf832a974288300224e60bsalomon    if (matrix) {
3127d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->concat(*matrix);
3128d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
3129d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
3130d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
3131d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
3132d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    fCanvas->restoreToCount(fSaveCount);
3133d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
3134e8f3062a36d3682f4019309a32b5b84dc9eddf8creed
3135ee424acbb87bf999be132a437527e656e37541d7Florin Malita///////////////////////////////////////////////////////////////////////////////
3136ee424acbb87bf999be132a437527e656e37541d7Florin Malita
3137ee424acbb87bf999be132a437527e656e37541d7Florin MalitaSkNoDrawCanvas::SkNoDrawCanvas(int width, int height)
3138ee424acbb87bf999be132a437527e656e37541d7Florin Malita    : INHERITED(SkIRect::MakeWH(width, height), kConservativeRasterClip_InitFlag) {}
3139ee424acbb87bf999be132a437527e656e37541d7Florin Malita
3140439ace939b6aaa58408ece0e9e89b633353571aeFlorin MalitaSkNoDrawCanvas::SkNoDrawCanvas(const SkIRect& bounds)
3141439ace939b6aaa58408ece0e9e89b633353571aeFlorin Malita    : INHERITED(bounds, kConservativeRasterClip_InitFlag) {}
3142439ace939b6aaa58408ece0e9e89b633353571aeFlorin Malita
3143ee424acbb87bf999be132a437527e656e37541d7Florin MalitaSkCanvas::SaveLayerStrategy SkNoDrawCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
3144ee424acbb87bf999be132a437527e656e37541d7Florin Malita    (void)this->INHERITED::getSaveLayerStrategy(rec);
3145ee424acbb87bf999be132a437527e656e37541d7Florin Malita    return kNoLayer_SaveLayerStrategy;
3146ee424acbb87bf999be132a437527e656e37541d7Florin Malita}
3147ee424acbb87bf999be132a437527e656e37541d7Florin Malita
3148ee424acbb87bf999be132a437527e656e37541d7Florin Malita///////////////////////////////////////////////////////////////////////////////
314973603f3c52ffd89fe9d035be827b566a0e7d3b79reed
315073603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kDifference_Op         == (int)kDifference_SkClipOp, "");
315173603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kIntersect_Op          == (int)kIntersect_SkClipOp, "");
315273603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kUnion_Op              == (int)kUnion_SkClipOp, "");
315373603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kXOR_Op                == (int)kXOR_SkClipOp, "");
315473603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kReverseDifference_Op  == (int)kReverseDifference_SkClipOp, "");
315573603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kReplace_Op            == (int)kReplace_SkClipOp, "");
3156356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
3157356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed///////////////////////////////////////////////////////////////////////////////////////////////////
3158356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
3159356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedSkRasterHandleAllocator::Handle SkCanvas::accessTopRasterHandle() const {
3160356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    if (fAllocator && fMCRec->fTopLayer->fDevice) {
3161713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita        const auto& dev = fMCRec->fTopLayer->fDevice;
3162356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        SkRasterHandleAllocator::Handle handle = dev->getRasterHandle();
3163356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        SkIPoint origin = dev->getOrigin();
3164356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        SkMatrix ctm = this->getTotalMatrix();
3165356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        ctm.preTranslate(SkIntToScalar(-origin.x()), SkIntToScalar(-origin.y()));
3166356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
3167356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        SkIRect clip = fMCRec->fRasterClip.getBounds();
3168356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        clip.offset(-origin.x(), -origin.y());
3169108f55ed5d0b63baf653e4e443cc469df887c811Mike Reed        if (!clip.intersect(0, 0, dev->width(), dev->height())) {
3170356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed            clip.setEmpty();
3171356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        }
3172356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
3173356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        fAllocator->updateHandle(handle, ctm, clip);
3174356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        return handle;
3175356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    }
3176356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    return nullptr;
3177356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed}
3178356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
3179356f7c2600ef54237fb8678cf63d5953f065b7daMike Reedstatic bool install(SkBitmap* bm, const SkImageInfo& info,
3180356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                    const SkRasterHandleAllocator::Rec& rec) {
3181356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    return bm->installPixels(info, rec.fPixels, rec.fRowBytes, nullptr,
3182356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                             rec.fReleaseProc, rec.fReleaseCtx);
3183356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed}
3184356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
3185356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedSkRasterHandleAllocator::Handle SkRasterHandleAllocator::allocBitmap(const SkImageInfo& info,
3186356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                                                                     SkBitmap* bm) {
3187356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    SkRasterHandleAllocator::Rec rec;
3188356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    if (!this->allocHandle(info, &rec) || !install(bm, info, rec)) {
3189356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        return nullptr;
3190356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    }
3191356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    return rec.fHandle;
3192356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed}
3193356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
3194356f7c2600ef54237fb8678cf63d5953f065b7daMike Reedstd::unique_ptr<SkCanvas>
3195356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedSkRasterHandleAllocator::MakeCanvas(std::unique_ptr<SkRasterHandleAllocator> alloc,
3196356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                                    const SkImageInfo& info, const Rec* rec) {
3197356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    if (!alloc || !supported_for_raster_canvas(info)) {
3198356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        return nullptr;
3199356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    }
3200356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
3201356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    SkBitmap bm;
3202356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    Handle hndl;
3203356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
3204356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    if (rec) {
3205356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        hndl = install(&bm, info, *rec) ? rec->fHandle : nullptr;
3206356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    } else {
3207356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        hndl = alloc->allocBitmap(info, &bm);
3208356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    }
3209356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    return hndl ? std::unique_ptr<SkCanvas>(new SkCanvas(bm, std::move(alloc), hndl)) : nullptr;
3210356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed}
3211