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"
23ab244f045a0740fa6106ed21a4e5824cd09f84f3Florin Malita#include "SkLights.h"
245df4934b3e40cdc378e225d1dda39f015cae9baeMike Reed#include "SkMakeUnique.h"
25262a71b7f95ce98ff3dd8dba845afbd724470903reed#include "SkMatrixUtils.h"
2674bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org#include "SkMetaData.h"
27ee424acbb87bf999be132a437527e656e37541d7Florin Malita#include "SkNoDrawCanvas.h"
28fbfa25802709139c2f14e304319c9541da65ca27msarett#include "SkNx.h"
29c83a29759a5c2966da5ab973e4fd90763e4c962breed#include "SkPaintPriv.h"
30b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkPatchUtils.h"
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPicture.h"
320017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com#include "SkRasterClip.h"
33356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed#include "SkRasterHandleAllocator.h"
344ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com#include "SkRRect.h"
354418dbac3386f26c8da62ab242be9c178961eb18robertphillips#include "SkSpecialImage.h"
362a475eae622adc1e8fa29206be1eaf862c23548eCary Clark#include "SkString.h"
3797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com#include "SkSurface_Base.h"
387ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita#include "SkTextBlob.h"
3952c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com#include "SkTextFormatParams.h"
40a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com#include "SkTLazy.h"
418f757f540a8378c7b1354aab3d4650eaa920b17adanakj#include "SkTraceEvent.h"
42d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include <new>
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
44644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
457354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips#include "GrContext.h"
463b65598bceb65736486db27ed49a56d787032747Brian Osman#include "SkGr.h"
47e6f5d5623160a69e1585f5121a3695092327dfe0vjiaoblack
48644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#endif
49ebfce6d9b42198e04288a15953f40c395a7b6139Mike Reed#include "SkClipOpPriv.h"
50199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon#include "SkVertices.h"
51644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org
52e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed#define RETURN_ON_NULL(ptr)     do { if (nullptr == (ptr)) return; } while (0)
53e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed
54139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reedclass SkNoPixelsDevice : public SkBaseDevice {
55139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reedpublic:
56139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    SkNoPixelsDevice(const SkIRect& bounds, const SkSurfaceProps& props)
57139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed        : SkBaseDevice(SkImageInfo::MakeUnknown(bounds.width(), bounds.height()), props)
58566e53c7003920ff45c72498754060804b657c68Mike Reed    {
59e393a629491e9a52dd6662983d2bfd424541957eMike Reed        // this fails if we enable this assert: DiscardableImageMapTest.GetDiscardableImagesInRectMaxImage
60e393a629491e9a52dd6662983d2bfd424541957eMike Reed        //SkASSERT(bounds.width() >= 0 && bounds.height() >= 0);
61566e53c7003920ff45c72498754060804b657c68Mike Reed    }
62139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed
63139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void resetForNextPicture(const SkIRect& bounds) {
64e393a629491e9a52dd6662983d2bfd424541957eMike Reed        //SkASSERT(bounds.width() >= 0 && bounds.height() >= 0);
65139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed        this->privateResize(bounds.width(), bounds.height());
66139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    }
67139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed
68139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reedprotected:
69139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    // We don't track the clip at all (for performance), but we have to respond to some queries.
70139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    // We pretend to be wide-open. We could pretend to always be empty, but that *seems* worse.
71139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void onSave() override {}
72139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void onRestore() override {}
73139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void onClipRect(const SkRect& rect, SkClipOp, bool aa) override {}
74139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) override {}
75139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void onClipPath(const SkPath& path, SkClipOp, bool aa) override {}
76139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void onClipRegion(const SkRegion& deviceRgn, SkClipOp) override {}
77139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void onSetDeviceClipRestriction(SkIRect* mutableClipRestriction) override {}
78139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    bool onClipIsAA() const override { return false; }
79139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void onAsRgnClip(SkRegion* rgn) const override {
80139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed        rgn->setRect(SkIRect::MakeWH(this->width(), this->height()));
81139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    }
82139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    ClipType onGetClipType() const override {
83139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed        return kRect_ClipType;
84139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    }
85139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed
86139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawPaint(const SkPaint& paint) override {}
87139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawPoints(SkCanvas::PointMode, size_t, const SkPoint[], const SkPaint&) override {}
88139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawRect(const SkRect&, const SkPaint&) override {}
89139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawOval(const SkRect&, const SkPaint&) override {}
90139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawRRect(const SkRRect&, const SkPaint&) override {}
91139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawPath(const SkPath&, const SkPaint&, const SkMatrix*, bool) override {}
92b964238f0bded00bae59c26c5f366a7780a0ef5fHal Canary    void drawBitmap(const SkBitmap&, SkScalar x, SkScalar y, const SkPaint&) override {}
93139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawSprite(const SkBitmap&, int, int, const SkPaint&) override {}
94139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint&,
95139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed                        SkCanvas::SrcRectConstraint) override {}
96139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawText(const void*, size_t, SkScalar, SkScalar, const SkPaint&) override {}
97139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawPosText(const void*, size_t, const SkScalar[], int, const SkPoint&,
98139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed                     const SkPaint&) override {}
99139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawDevice(SkBaseDevice*, int, int, const SkPaint&) override {}
1002f6b5a47a50cdd218bc3302273be3a4a71add8fbMike Reed    void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) override {}
101139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed
102139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reedprivate:
103139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    typedef SkBaseDevice INHERITED;
104139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed};
105139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed
106139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed///////////////////////////////////////////////////////////////////////////////////////////////////
107139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed
108c83a29759a5c2966da5ab973e4fd90763e4c962breed/*
109c83a29759a5c2966da5ab973e4fd90763e4c962breed *  Return true if the drawing this rect would hit every pixels in the canvas.
110c83a29759a5c2966da5ab973e4fd90763e4c962breed *
111c83a29759a5c2966da5ab973e4fd90763e4c962breed *  Returns false if
112c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - rect does not contain the canvas' bounds
113c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - paint is not fill
114c83a29759a5c2966da5ab973e4fd90763e4c962breed *  - paint would blur or otherwise change the coverage of the rect
115c83a29759a5c2966da5ab973e4fd90763e4c962breed */
116c83a29759a5c2966da5ab973e4fd90763e4c962breedbool SkCanvas::wouldOverwriteEntireSurface(const SkRect* rect, const SkPaint* paint,
117c83a29759a5c2966da5ab973e4fd90763e4c962breed                                           ShaderOverrideOpacity overrideOpacity) const {
11899fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert((int)SkPaintPriv::kNone_ShaderOverrideOpacity ==
11999fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  (int)kNone_ShaderOverrideOpacity,
12099fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  "need_matching_enums0");
12199fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert((int)SkPaintPriv::kOpaque_ShaderOverrideOpacity ==
12299fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  (int)kOpaque_ShaderOverrideOpacity,
12399fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  "need_matching_enums1");
12499fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert((int)SkPaintPriv::kNotOpaque_ShaderOverrideOpacity ==
12599fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  (int)kNotOpaque_ShaderOverrideOpacity,
12699fe82260633fcf5d92cca38d12ef0937ecca61cbungeman                  "need_matching_enums2");
127c83a29759a5c2966da5ab973e4fd90763e4c962breed
128c83a29759a5c2966da5ab973e4fd90763e4c962breed    const SkISize size = this->getBaseLayerSize();
129c83a29759a5c2966da5ab973e4fd90763e4c962breed    const SkRect bounds = SkRect::MakeIWH(size.width(), size.height());
130a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
131a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    // if we're clipped at all, we can't overwrite the entire surface
132a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    {
133a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        SkBaseDevice* base = this->getDevice();
134a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        SkBaseDevice* top = this->getTopDevice();
135a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        if (base != top) {
136a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            return false;   // we're in a saveLayer, so conservatively don't assume we'll overwrite
137a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        }
138a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        if (!base->clipIsWideOpen()) {
139a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            return false;
140a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        }
141c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
142c83a29759a5c2966da5ab973e4fd90763e4c962breed
143c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (rect) {
144c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary        if (!this->getTotalMatrix().isScaleTranslate()) {
145c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false; // conservative
146c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
147c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary
148c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary        SkRect devRect;
149c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary        this->getTotalMatrix().mapRectScaleTranslate(&devRect, *rect);
150c5769b2e49a63516f313f42969983f2b9e4d59e0halcanary        if (!devRect.contains(bounds)) {
151c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false;
152c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
153c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
154c83a29759a5c2966da5ab973e4fd90763e4c962breed
155c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (paint) {
156c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkPaint::Style paintStyle = paint->getStyle();
157c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (!(paintStyle == SkPaint::kFill_Style ||
158c83a29759a5c2966da5ab973e4fd90763e4c962breed              paintStyle == SkPaint::kStrokeAndFill_Style)) {
159c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false;
160c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
161c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (paint->getMaskFilter() || paint->getLooper()
162c83a29759a5c2966da5ab973e4fd90763e4c962breed            || paint->getPathEffect() || paint->getImageFilter()) {
163c83a29759a5c2966da5ab973e4fd90763e4c962breed            return false; // conservative
164c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
165c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
166c83a29759a5c2966da5ab973e4fd90763e4c962breed    return SkPaintPriv::Overwrites(paint, (SkPaintPriv::ShaderOverrideOpacity)overrideOpacity);
167c83a29759a5c2966da5ab973e4fd90763e4c962breed}
168c83a29759a5c2966da5ab973e4fd90763e4c962breed
169c83a29759a5c2966da5ab973e4fd90763e4c962breed///////////////////////////////////////////////////////////////////////////////////////////////////
170c83a29759a5c2966da5ab973e4fd90763e4c962breed
171d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedstatic bool gIgnoreSaveLayerBounds;
172d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedvoid SkCanvas::Internal_Private_SetIgnoreSaveLayerBounds(bool ignore) {
173d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    gIgnoreSaveLayerBounds = ignore;
174d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed}
175d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareedbool SkCanvas::Internal_Private_GetIgnoreSaveLayerBounds() {
176d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    return gIgnoreSaveLayerBounds;
177d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed}
178d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed
1790acf1b4b3645772d220c720313821bac389751b5reedstatic bool gTreatSpriteAsBitmap;
1800acf1b4b3645772d220c720313821bac389751b5reedvoid SkCanvas::Internal_Private_SetTreatSpriteAsBitmap(bool spriteAsBitmap) {
1810acf1b4b3645772d220c720313821bac389751b5reed    gTreatSpriteAsBitmap = spriteAsBitmap;
1820acf1b4b3645772d220c720313821bac389751b5reed}
1830acf1b4b3645772d220c720313821bac389751b5reedbool SkCanvas::Internal_Private_GetTreatSpriteAsBitmap() {
1840acf1b4b3645772d220c720313821bac389751b5reed    return gTreatSpriteAsBitmap;
1850acf1b4b3645772d220c720313821bac389751b5reed}
1860acf1b4b3645772d220c720313821bac389751b5reed
187da17f758442f16747af39f8fbaed9c097048519creed@google.com// experimental for faster tiled drawing...
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define SK_TRACE_SAVERESTORE
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_TRACE_SAVERESTORE
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gLayerCounter;
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gRecCounter;
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int gCanvasCounter;
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_layer()
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_layer()
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_rec()
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_rec()
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define inc_canvas()
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define dec_canvas()
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2112c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.orgtypedef SkTLazy<SkPaint> SkLazyPaint;
2122c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org
213c83a29759a5c2966da5ab973e4fd90763e4c962breedvoid SkCanvas::predrawNotify(bool willOverwritesEntireSurface) {
21497af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    if (fSurfaceBase) {
215c83a29759a5c2966da5ab973e4fd90763e4c962breed        fSurfaceBase->aboutToDraw(willOverwritesEntireSurface
216c83a29759a5c2966da5ab973e4fd90763e4c962breed                                  ? SkSurface::kDiscard_ContentChangeMode
217c83a29759a5c2966da5ab973e4fd90763e4c962breed                                  : SkSurface::kRetain_ContentChangeMode);
218c83a29759a5c2966da5ab973e4fd90763e4c962breed    }
219c83a29759a5c2966da5ab973e4fd90763e4c962breed}
220c83a29759a5c2966da5ab973e4fd90763e4c962breed
221c83a29759a5c2966da5ab973e4fd90763e4c962breedvoid SkCanvas::predrawNotify(const SkRect* rect, const SkPaint* paint,
222c83a29759a5c2966da5ab973e4fd90763e4c962breed                             ShaderOverrideOpacity overrideOpacity) {
223c83a29759a5c2966da5ab973e4fd90763e4c962breed    if (fSurfaceBase) {
224c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkSurface::ContentChangeMode mode = SkSurface::kRetain_ContentChangeMode;
225c83a29759a5c2966da5ab973e4fd90763e4c962breed        // Since willOverwriteAllPixels() may not be complete free to call, we only do so if
226c83a29759a5c2966da5ab973e4fd90763e4c962breed        // there is an outstanding snapshot, since w/o that, there will be no copy-on-write
227c83a29759a5c2966da5ab973e4fd90763e4c962breed        // and therefore we don't care which mode we're in.
228c83a29759a5c2966da5ab973e4fd90763e4c962breed        //
229c83a29759a5c2966da5ab973e4fd90763e4c962breed        if (fSurfaceBase->outstandingImageSnapshot()) {
230c83a29759a5c2966da5ab973e4fd90763e4c962breed            if (this->wouldOverwriteEntireSurface(rect, paint, overrideOpacity)) {
231c83a29759a5c2966da5ab973e4fd90763e4c962breed                mode = SkSurface::kDiscard_ContentChangeMode;
232c83a29759a5c2966da5ab973e4fd90763e4c962breed            }
233c83a29759a5c2966da5ab973e4fd90763e4c962breed        }
234c83a29759a5c2966da5ab973e4fd90763e4c962breed        fSurfaceBase->aboutToDraw(mode);
23597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    }
23697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com}
23797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2401f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com/*  This is the record we keep for each SkBaseDevice that the user installs.
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The clip/matrix/proc are fields that reflect the top of the save/restore
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stack. Whenever the canvas changes, it marks a dirty flag, and then before
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    these are used (assuming we're not on a layer) we rebuild these cache
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    values: they reflect the top of the save stack, but translated and clipped
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    by the device's XY offset and bitmap-bounds.
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct DeviceCM {
248713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    DeviceCM*                      fNext;
249713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    sk_sp<SkBaseDevice>            fDevice;
250713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    SkRasterClip                   fClip;
251713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    std::unique_ptr<const SkPaint> fPaint; // may be null (in the future)
252713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    SkMatrix                       fStashedMatrix; // original CTM; used by imagefilter in saveLayer
25353f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita    sk_sp<SkImage>                 fClipImage;
25453f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita    SkMatrix                       fClipMatrix;
255713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita
25653f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita    DeviceCM(sk_sp<SkBaseDevice> device, const SkPaint* paint, const SkMatrix& stashed,
257b34ab04884f6219b93c1f143c83a1fc60fded40cMike Klein             const SkImage* clipImage, const SkMatrix* clipMatrix)
25896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        : fNext(nullptr)
259713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita        , fDevice(std::move(device))
260713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita        , fPaint(paint ? skstd::make_unique<SkPaint>(*paint) : nullptr)
2618c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        , fStashedMatrix(stashed)
262b34ab04884f6219b93c1f143c83a1fc60fded40cMike Klein        , fClipImage(sk_ref_sp(const_cast<SkImage*>(clipImage)))
26353f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita        , fClipMatrix(clipMatrix ? *clipMatrix : SkMatrix::I())
264713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    {}
2654b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
266feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    void reset(const SkIRect& bounds) {
267feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(!fPaint);
268feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(!fNext);
269feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fDevice);
270feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fClip.setRect(bounds);
271feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    }
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  This is the record we keep for each save/restore level in the stack.
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Since a level optionally copies the matrix and/or stack, we have pointers
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for these fields. If the value is copied for this level, the copy is
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    stored in the ...Storage field, and the pointer points to that. If the
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    value is not copied for this level, we ignore ...Storage, and just point
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    at the corresponding value in the previous level in the stack.
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkCanvas::MCRec {
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2831f836ee096bb988adef4b9757b2629c7afeda36dreed    SkDrawFilter*   fFilter;    // the current filter (or null)
284d954498c01ccf0417feacf89e45d0c62a06a813breed    DeviceCM*       fLayer;
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  If there are any layers in the stack, this points to the top-most
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        one that is at or below this level in the stack (so we know what
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bitmap/device to draw into from this level. This value is NOT
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        reference counted, since the real owner is either our fLayer field,
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        or a previous one in a lower level.)
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
291a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    DeviceCM*           fTopLayer;
292a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    SkConservativeClip  fRasterClip;
293a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    SkMatrix            fMatrix;
294a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    int                 fDeferredSaveCount;
2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
296a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    MCRec() {
29796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fFilter     = nullptr;
29896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fLayer      = nullptr;
29996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fTopLayer   = nullptr;
3002ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fMatrix.reset();
3012ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fDeferredSaveCount = 0;
302b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
303d954498c01ccf0417feacf89e45d0c62a06a813breed        // don't bother initializing fNext
304d954498c01ccf0417feacf89e45d0c62a06a813breed        inc_rec();
305d954498c01ccf0417feacf89e45d0c62a06a813breed    }
306343fe49b82d5b220d64c64f253bb362026006632Jim Van Verth    MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix) {
307d954498c01ccf0417feacf89e45d0c62a06a813breed        fFilter = SkSafeRef(prev.fFilter);
30896fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fLayer = nullptr;
309d954498c01ccf0417feacf89e45d0c62a06a813breed        fTopLayer = prev.fTopLayer;
3102ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fDeferredSaveCount = 0;
311b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // don't bother initializing fNext
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        inc_rec();
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~MCRec() {
31682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        SkSafeUnref(fFilter);
317385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        delete fLayer;
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dec_rec();
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
320feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
321feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    void reset(const SkIRect& bounds) {
322feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fLayer);
323feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        SkASSERT(fDeferredSaveCount == 0);
324feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
325feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fMatrix.reset();
326feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fRasterClip.setRect(bounds);
327feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein        fLayer->reset(bounds);
328feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    }
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
331a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedclass SkDrawIter {
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
333a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    SkDrawIter(SkCanvas* canvas)
334a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        : fDevice(nullptr), fCurrLayer(canvas->fMCRec->fTopLayer), fPaint(nullptr)
335a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    {}
3364b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool next() {
338f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        const DeviceCM* rec = fCurrLayer;
339f68c5e2f9f05b3af2bae0979ace2684b6041b6e3reed@google.com        if (rec && rec->fDevice) {
340713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita            fDevice = rec->fDevice.get();
341713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita            fPaint  = rec->fPaint.get();
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fCurrLayer = rec->fNext;
34396fcdcc219d2a0d3579719b84b28bede76efba64halcanary            // fCurrLayer may be nullptr now
3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return true;
3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3484b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
3496f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getX() const { return fDevice->getOrigin().x(); }
3506f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int getY() const { return fDevice->getOrigin().y(); }
3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* getPaint() const { return fPaint; }
3526f8f292aa768869a9e85c314b124875f57504f2creed@google.com
35399330ba6227137866a0dbd63478d36f335203ebdMike Reed    SkBaseDevice*   fDevice;
35499330ba6227137866a0dbd63478d36f335203ebdMike Reed
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const DeviceCM* fCurrLayer;
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint*  fPaint;     // May be null.
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
360713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita#define FOR_EACH_TOP_DEVICE( code )                       \
361713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    do {                                                  \
362713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita        DeviceCM* layer = fMCRec->fTopLayer;              \
363713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita        while (layer) {                                   \
364713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita            SkBaseDevice* device = layer->fDevice.get();  \
365713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita            if (device) {                                 \
366713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita                code;                                     \
367713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita            }                                             \
368713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita            layer = layer->fNext;                         \
369713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita        }                                                 \
3707627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    } while (0)
3717627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
374dbc3cefb0b624808ddb86d444e6103f216e12fa5reedstatic SkPaint* set_if_needed(SkLazyPaint* lazy, const SkPaint& orig) {
375dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    return lazy->isValid() ? lazy->get() : lazy->set(orig);
376dbc3cefb0b624808ddb86d444e6103f216e12fa5reed}
377dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
378dbc3cefb0b624808ddb86d444e6103f216e12fa5reed/**
379dbc3cefb0b624808ddb86d444e6103f216e12fa5reed *  If the paint has an imagefilter, but it can be simplified to just a colorfilter, return that
38096fcdcc219d2a0d3579719b84b28bede76efba64halcanary *  colorfilter, else return nullptr.
381dbc3cefb0b624808ddb86d444e6103f216e12fa5reed */
382d053ce9c54d4e5937a142278359e5a4cde18095ereedstatic sk_sp<SkColorFilter> image_to_color_filter(const SkPaint& paint) {
383dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkImageFilter* imgf = paint.getImageFilter();
384dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    if (!imgf) {
38596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
386dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
387dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
388d053ce9c54d4e5937a142278359e5a4cde18095ereed    SkColorFilter* imgCFPtr;
389d053ce9c54d4e5937a142278359e5a4cde18095ereed    if (!imgf->asAColorFilter(&imgCFPtr)) {
39096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
391dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
392d053ce9c54d4e5937a142278359e5a4cde18095ereed    sk_sp<SkColorFilter> imgCF(imgCFPtr);
393dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
394dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkColorFilter* paintCF = paint.getColorFilter();
39596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paintCF) {
396dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        // there is no existing paint colorfilter, so we can just return the imagefilter's
397dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        return imgCF;
398dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    }
399dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
400dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    // The paint has both a colorfilter(paintCF) and an imagefilter-which-is-a-colorfilter(imgCF)
401dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    // and we need to combine them into a single colorfilter.
402d053ce9c54d4e5937a142278359e5a4cde18095ereed    return SkColorFilter::MakeComposeFilter(std::move(imgCF), sk_ref_sp(paintCF));
403dbc3cefb0b624808ddb86d444e6103f216e12fa5reed}
404dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
40587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco/**
40687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * There are many bounds in skia. A circle's bounds is just its center extended by its radius.
40787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * However, if we stroke a circle, then the "bounds" of that is larger, since it will now draw
40887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * outside of its raw-bounds by 1/2 the stroke width.  SkPaint has lots of optional
40987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * effects/attributes that can modify the effective bounds of a given primitive -- maskfilters,
41087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * patheffects, stroking, etc.  This function takes a raw bounds and a paint, and returns the
41187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * conservative "effective" bounds based on the settings in the paint... with one exception. This
41287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * function does *not* look at the imagefilter, which can also modify the effective bounds. It is
41387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco * deliberately ignored.
41487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco */
41587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblancostatic const SkRect& apply_paint_to_bounds_sans_imagefilter(const SkPaint& paint,
41687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                                                            const SkRect& rawBounds,
41787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                                                            SkRect* storage) {
41887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    SkPaint tmpUnfiltered(paint);
41987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    tmpUnfiltered.setImageFilter(nullptr);
42087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    if (tmpUnfiltered.canComputeFastBounds()) {
42187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        return tmpUnfiltered.computeFastBounds(rawBounds, storage);
42287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    } else {
42387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        return rawBounds;
42487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    }
42587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco}
42687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco
4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass AutoDrawLooper {
4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
42987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    // "rawBounds" is the original bounds of the primitive about to be drawn, unmodified by the
43087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    // paint. It's used to determine the size of the offscreen layer for filters.
43187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco    // If null, the clip will be used instead.
4323aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint, bool skipLayerForImageFilter = false,
43387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                   const SkRect* rawBounds = nullptr) : fOrigPaint(paint) {
4344e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fCanvas = canvas;
43553d9f1cfbd5ddbf57c2f22b9e613ce48e5b2896cfmalita#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fFilter = canvas->getDrawFilter();
4377765000709dc64eb23be7df47d1f995d1f787115fmalita#else
4387765000709dc64eb23be7df47d1f995d1f787115fmalita        fFilter = nullptr;
4397765000709dc64eb23be7df47d1f995d1f787115fmalita#endif
4404a8126e7f81384526629b1e21bf89b632ea13cd9reed        fPaint = &fOrigPaint;
4414e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fSaveCount = canvas->getSaveCount();
4425c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        fTempLayerForImageFilter = false;
4434e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = false;
4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
445d053ce9c54d4e5937a142278359e5a4cde18095ereed        auto simplifiedCF = image_to_color_filter(fOrigPaint);
446dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        if (simplifiedCF) {
447dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
448d053ce9c54d4e5937a142278359e5a4cde18095ereed            paint->setColorFilter(std::move(simplifiedCF));
44996fcdcc219d2a0d3579719b84b28bede76efba64halcanary            paint->setImageFilter(nullptr);
450dbc3cefb0b624808ddb86d444e6103f216e12fa5reed            fPaint = paint;
451dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        }
452dbc3cefb0b624808ddb86d444e6103f216e12fa5reed
453dbc3cefb0b624808ddb86d444e6103f216e12fa5reed        if (!skipLayerForImageFilter && fPaint->getImageFilter()) {
4545c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            /**
4555c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  We implement ImageFilters for a given draw by creating a layer, then applying the
4565c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  imagefilter to the pixels of that layer (its backing surface/image), and then
4575c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  we call restore() to xfer that layer to the main canvas.
4585c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *
4595c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  1. SaveLayer (with a paint containing the current imagefilter and xfermode)
4605c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  2. Generate the src pixels:
4615c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      Remove the imagefilter and the xfermode from the paint that we (AutoDrawLooper)
4625c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      return (fPaint). We then draw the primitive (using srcover) into a cleared
4635c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      buffer/surface.
4645c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *  3. Restore the layer created in #1
4655c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      The imagefilter is passed the buffer/surface from the layer (now filled with the
4665c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      src pixels of the primitive). It returns a new "filtered" buffer, which we
4675c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             *      draw onto the previous layer using the xfermode from the original paint.
4685c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed             */
4698926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            SkPaint tmp;
470693fdbd6b81a860657612e7604430dd55d6e721bMike Reed            tmp.setImageFilter(fPaint->refImageFilter());
471374772bd61951f01bf84fe17bf53d8867681c9aereed            tmp.setBlendMode(fPaint->getBlendMode());
47287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            SkRect storage;
47387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            if (rawBounds) {
47487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                // Make rawBounds include all paint outsets except for those due to image filters.
47587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco                rawBounds = &apply_paint_to_bounds_sans_imagefilter(*fPaint, *rawBounds, &storage);
47687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            }
477bfd5f171e6a3eccd7c4bede652a85fd76bcbce2areed            (void)canvas->internalSaveLayer(SkCanvas::SaveLayerRec(rawBounds, &tmp),
47876033be81b82c44fd5d4fdf2672eb22e505da1f0reed                                            SkCanvas::kFullLayer_SaveLayerStrategy);
4795c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            fTempLayerForImageFilter = true;
4805c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            // we remove the imagefilter/xfermode inside doNext()
4818926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
4828926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
48379fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        if (SkDrawLooper* looper = paint.getLooper()) {
48473fe7b07e6391da81dfc48d600d7b3141be1f471Herb Derby            fLooperContext = looper->makeContext(canvas, &fAlloc);
485129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fIsSimple = false;
486129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
48796fcdcc219d2a0d3579719b84b28bede76efba64halcanary            fLooperContext = nullptr;
488129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // can we be marked as simple?
4895c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed            fIsSimple = !fFilter && !fTempLayerForImageFilter;
4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
49274b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
4934e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    ~AutoDrawLooper() {
4945c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed        if (fTempLayerForImageFilter) {
4958926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            fCanvas->internalRestore();
4968926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        }
4974e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fCanvas->getSaveCount() == fSaveCount);
4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
49974b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
5004e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    const SkPaint& paint() const {
5014e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkASSERT(fPaint);
5024e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return *fPaint;
5034e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
50474b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
505129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool next(SkDrawFilter::Type drawType) {
506129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        if (fDone) {
507129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return false;
508129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else if (fIsSimple) {
509129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            fDone = true;
510129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return !fPaint->nothingToDraw();
511129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        } else {
512129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            return this->doNext(drawType);
513129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        }
514fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
51574b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
51773fe7b07e6391da81dfc48d600d7b3141be1f471Herb Derby    SkLazyPaint     fLazyPaintInit;       // base paint storage in case we need to modify it
518dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkLazyPaint     fLazyPaintPerLooper;  // per-draw-looper storage, so the looper can modify it
5192c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkCanvas*       fCanvas;
5202c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint&  fOrigPaint;
5212c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkDrawFilter*   fFilter;
5222c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
5232c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    int             fSaveCount;
5245c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    bool            fTempLayerForImageFilter;
5252c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    bool            fDone;
526129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool            fIsSimple;
52779fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    SkDrawLooper::Context* fLooperContext;
52814a6430b7bcf92bcabf4aef18805969d1335aab1Florin Malita    SkSTArenaAlloc<48>     fAlloc;
529129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com
530129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool doNext(SkDrawFilter::Type drawType);
5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
533129ec22cb054592261e001294c430c9dd4e90ff4reed@google.combool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
53496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fPaint = nullptr;
535129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkASSERT(!fIsSimple);
5365c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    SkASSERT(fLooperContext || fFilter || fTempLayerForImageFilter);
537632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com
538dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkPaint* paint = fLazyPaintPerLooper.set(fLazyPaintInit.isValid() ?
539dbc3cefb0b624808ddb86d444e6103f216e12fa5reed                                             *fLazyPaintInit.get() : fOrigPaint);
5408926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
5415c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    if (fTempLayerForImageFilter) {
54296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        paint->setImageFilter(nullptr);
543374772bd61951f01bf84fe17bf53d8867681c9aereed        paint->setBlendMode(SkBlendMode::kSrcOver);
544129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
5458926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
54679fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
547129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        fDone = true;
548129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        return false;
549129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
550129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fFilter) {
551971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        if (!fFilter->filter(paint, drawType)) {
552971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            fDone = true;
553971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            return false;
554971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        }
55596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == fLooperContext) {
556129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // no looper means we only draw once
557632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com            fDone = true;
558632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com        }
559129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
560129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    fPaint = paint;
5618926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
562129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    // if we only came in here for the imagefilter, mark us as done
56379fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (!fLooperContext && !fFilter) {
5644e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = true;
5654e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
5664e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
567632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    // call this after any possible paint modifiers
568632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    if (fPaint->nothingToDraw()) {
56996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fPaint = nullptr;
5704e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return false;
5714e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
5724e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    return true;
5734e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com}
5744e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls //////////////////
5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5773aafe111b6cc388400092851cc53bbbdfcb8a81creed#define LOOPER_BEGIN_DRAWBITMAP(paint, skipLayerForFilter, bounds)  \
5783aafe111b6cc388400092851cc53bbbdfcb8a81creed    this->predrawNotify();                                          \
5793aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper looper(this, paint, skipLayerForFilter, bounds); \
5803aafe111b6cc388400092851cc53bbbdfcb8a81creed    while (looper.next(SkDrawFilter::kBitmap_Type)) {               \
581262a71b7f95ce98ff3dd8dba845afbd724470903reed        SkDrawIter iter(this);
582262a71b7f95ce98ff3dd8dba845afbd724470903reed
583262a71b7f95ce98ff3dd8dba845afbd724470903reed
5848926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com#define LOOPER_BEGIN_DRAWDEVICE(paint, type)                        \
58597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
5863aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper  looper(this, paint, true);                      \
5878926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (looper.next(type)) {                                     \
5888926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkDrawIter          iter(this);
5898926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
59078cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org#define LOOPER_BEGIN(paint, type, bounds)                           \
59197af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
5923aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper  looper(this, paint, false, bounds);             \
5934e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    while (looper.next(type)) {                                     \
5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawIter          iter(this);
5954b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
596c83a29759a5c2966da5ab973e4fd90763e4c962breed#define LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, type, bounds, auxOpaque)  \
597c83a29759a5c2966da5ab973e4fd90763e4c962breed    this->predrawNotify(bounds, &paint, auxOpaque);                 \
5983aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper  looper(this, paint, false, bounds);             \
599c83a29759a5c2966da5ab973e4fd90763e4c962breed    while (looper.next(type)) {                                     \
600c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkDrawIter          iter(this);
601c83a29759a5c2966da5ab973e4fd90763e4c962breed
6024e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_END    }
6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////
6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
606fbfa25802709139c2f14e304319c9541da65ca27msarettstatic inline SkRect qr_clip_bounds(const SkIRect& bounds) {
607fbfa25802709139c2f14e304319c9541da65ca27msarett    if (bounds.isEmpty()) {
608fbfa25802709139c2f14e304319c9541da65ca27msarett        return SkRect::MakeEmpty();
609fbfa25802709139c2f14e304319c9541da65ca27msarett    }
610fbfa25802709139c2f14e304319c9541da65ca27msarett
611fbfa25802709139c2f14e304319c9541da65ca27msarett    // Expand bounds out by 1 in case we are anti-aliasing.  We store the
612fbfa25802709139c2f14e304319c9541da65ca27msarett    // bounds as floats to enable a faster quick reject implementation.
613fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect dst;
614fbfa25802709139c2f14e304319c9541da65ca27msarett    SkNx_cast<float>(Sk4i::Load(&bounds.fLeft) + Sk4i(-1,-1,1,1)).store(&dst.fLeft);
615fbfa25802709139c2f14e304319c9541da65ca27msarett    return dst;
616fbfa25802709139c2f14e304319c9541da65ca27msarett}
617fbfa25802709139c2f14e304319c9541da65ca27msarett
618feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtkleinvoid SkCanvas::resetForNextPicture(const SkIRect& bounds) {
619feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    this->restoreToCount(1);
620feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fMCRec->reset(bounds);
621feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
622feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    // We're peering through a lot of structs here.  Only at this scope do we
623139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    // know that the device is a SkNoPixelsDevice.
624713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    static_cast<SkNoPixelsDevice*>(fMCRec->fLayer->fDevice.get())->resetForNextPicture(bounds);
625fbfa25802709139c2f14e304319c9541da65ca27msarett    fDeviceClipBounds = qr_clip_bounds(bounds);
6269637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    fIsScaleTranslate = true;
627feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein}
628feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
629d954498c01ccf0417feacf89e45d0c62a06a813breedSkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
63042b73eb00367c8315974b1c374308d20efa78897reed    if (device && device->forceConservativeRasterClip()) {
63142b73eb00367c8315974b1c374308d20efa78897reed        flags = InitFlags(flags | kConservativeRasterClip_InitFlag);
63242b73eb00367c8315974b1c374308d20efa78897reed    }
63342b73eb00367c8315974b1c374308d20efa78897reed
63445a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    fAllowSimplifyClip = false;
6352ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount = 1;
63696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fMetaData = nullptr;
6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.push_back();
639a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    new (fMCRec) MCRec;
6405f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev    fMCRec->fRasterClip.setDeviceClipRestriction(&fClipRestrictionRect);
6419637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    fIsScaleTranslate = true;
6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
643a499f905e9340e4935447f2562fd92e8853382b1reed    SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage));
644a499f905e9340e4935447f2562fd92e8853382b1reed    fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
64553f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita    new (fDeviceCMStorage) DeviceCM(sk_ref_sp(device), nullptr, fMCRec->fMatrix, nullptr, nullptr);
646b679ca8926a832274b14fdb512f88f64b61d32eareed
6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = fMCRec->fLayer;
6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
64996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fSurfaceBase = nullptr;
650f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
651f92c86642a1875da54d54b447f006cb9dfbbb35creed    if (device) {
652efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        // The root device and the canvas should always have the same pixel geometry
653efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        SkASSERT(fProps.pixelGeometry() == device->surfaceProps().pixelGeometry());
65478e276889795454891cbba48ab11927968114953reed        fMCRec->fRasterClip.setRect(device->getGlobalBounds());
655fbfa25802709139c2f14e304319c9541da65ca27msarett        fDeviceClipBounds = qr_clip_bounds(device->getGlobalBounds());
656c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
657c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
658f92c86642a1875da54d54b447f006cb9dfbbb35creed    }
659fbfa25802709139c2f14e304319c9541da65ca27msarett
660f92c86642a1875da54d54b447f006cb9dfbbb35creed    return device;
6618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
663cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.comSkCanvas::SkCanvas()
664e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6654a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
666e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
6678d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    inc_canvas();
668ba124485687130183643994f1b4b68d629fbbebaskia.committer@gmail.com
66996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    this->init(nullptr, kDefault_InitFlags);
6708d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org}
6718d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org
67296a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reedSkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props)
673e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
67496a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reed    , fProps(SkSurfacePropsCopyOrDefault(props))
675e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
676e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    inc_canvas();
677b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
678566e53c7003920ff45c72498754060804b657c68Mike Reed    this->init(new SkNoPixelsDevice(SkIRect::MakeWH(SkTMax(width, 0), SkTMax(height, 0)), fProps),
679385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary               kDefault_InitFlags)->unref();
680d954498c01ccf0417feacf89e45d0c62a06a813breed}
681e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org
68278e276889795454891cbba48ab11927968114953reedSkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags)
683d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6844a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
685d954498c01ccf0417feacf89e45d0c62a06a813breed{
686d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
687b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
688566e53c7003920ff45c72498754060804b657c68Mike Reed    SkIRect r = bounds.isEmpty() ? SkIRect::MakeEmpty() : bounds;
689566e53c7003920ff45c72498754060804b657c68Mike Reed    this->init(new SkNoPixelsDevice(r, fProps), flags)->unref();
69027a5e656c3d6ef22f9cb34de18e1b960da3aa241reed}
6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
692d954498c01ccf0417feacf89e45d0c62a06a813breedSkCanvas::SkCanvas(SkBaseDevice* device)
693d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6947b05ff11ebc51f3f3abd1c1756337a04f563537erobertphillips    , fProps(device->surfaceProps())
695d954498c01ccf0417feacf89e45d0c62a06a813breed{
696d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
697b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
698d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(device, kDefault_InitFlags);
6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
701fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillipsSkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags)
702fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7037b05ff11ebc51f3f3abd1c1756337a04f563537erobertphillips    , fProps(device->surfaceProps())
704fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips{
705fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    inc_canvas();
706fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips
707fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    this->init(device, flags);
708fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips}
709fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips
7104a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
7113716fd067a5621bb94a6cb08d72afec8bf3acedareed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7124a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(props)
7133716fd067a5621bb94a6cb08d72afec8bf3acedareed{
7143716fd067a5621bb94a6cb08d72afec8bf3acedareed    inc_canvas();
715b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
716704cd32e4a92d6c3eae6bfae4adcc20126bf4437Hal Canary    sk_sp<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps));
717704cd32e4a92d6c3eae6bfae4adcc20126bf4437Hal Canary    this->init(device.get(), kDefault_InitFlags);
7184a8126e7f81384526629b1e21bf89b632ea13cd9reed}
71929c857d0f3a1cb837f73406eeb6ba9771879b5e7reed
720356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedSkCanvas::SkCanvas(const SkBitmap& bitmap, std::unique_ptr<SkRasterHandleAllocator> alloc,
721356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                   SkRasterHandleAllocator::Handle hndl)
7224a8126e7f81384526629b1e21bf89b632ea13cd9reed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7234a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
724356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    , fAllocator(std::move(alloc))
7254a8126e7f81384526629b1e21bf89b632ea13cd9reed{
7264a8126e7f81384526629b1e21bf89b632ea13cd9reed    inc_canvas();
727b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
728356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    sk_sp<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps, hndl));
729704cd32e4a92d6c3eae6bfae4adcc20126bf4437Hal Canary    this->init(device.get(), kDefault_InitFlags);
7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
732356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedSkCanvas::SkCanvas(const SkBitmap& bitmap) : SkCanvas(bitmap, nullptr, nullptr) {}
733356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
73431f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
73531f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt SarettSkCanvas::SkCanvas(const SkBitmap& bitmap, ColorBehavior)
73631f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
73731f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
73831f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    , fAllocator(nullptr)
73931f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett{
74031f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    inc_canvas();
74131f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett
74231f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    SkBitmap tmp(bitmap);
74331f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    *const_cast<SkImageInfo*>(&tmp.info()) = tmp.info().makeColorSpace(nullptr);
74431f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    sk_sp<SkBaseDevice> device(new SkBitmapDevice(tmp, fProps, nullptr));
74531f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    this->init(device.get(), kDefault_InitFlags);
74631f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett}
74731f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett#endif
74831f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett
7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() {
7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // free up the contents of our deque
7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->restoreToCount(1);    // restore everything but the last
7527c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->internalRestore();    // restore the last, since we're going away
7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
755385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    delete fMetaData;
756b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org
7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dec_canvas();
7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
76053d9f1cfbd5ddbf57c2f22b9e613ce48e5b2896cfmalita#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const {
7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fFilter;
7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
76651985e3f5e608d369e52832b7ce489d85d402422reed    this->checkForDeferredSave();
7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7707765000709dc64eb23be7df47d1f995d1f787115fmalita#endif
7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
77274bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.orgSkMetaData& SkCanvas::getMetaData() {
77374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // metadata users are rare, so we lazily allocate it. If that changes we
77474bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // can decide to just make it a field in the device (rather than a ptr)
77596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == fMetaData) {
77674bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org        fMetaData = new SkMetaData;
77774bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    }
77874bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    return *fMetaData;
77974bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org}
78074bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org
7818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
783bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.orgvoid SkCanvas::flush() {
784ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed    this->onFlush();
785ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed}
786ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed
787ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reedvoid SkCanvas::onFlush() {
7881f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getDevice();
789bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    if (device) {
790bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org        device->flush();
791bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    }
792bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org}
793bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org
794afc7cce5d68663934128d76963cd501f771d71desenorblancoSkISize SkCanvas::getBaseLayerSize() const {
795afc7cce5d68663934128d76963cd501f771d71desenorblanco    SkBaseDevice* d = this->getDevice();
7964ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
7974ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
7984ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
799afc7cce5d68663934128d76963cd501f771d71desenorblancoSkIRect SkCanvas::getTopLayerBounds() const {
8004ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
801afc7cce5d68663934128d76963cd501f771d71desenorblanco    if (!d) {
802afc7cce5d68663934128d76963cd501f771d71desenorblanco        return SkIRect::MakeEmpty();
803afc7cce5d68663934128d76963cd501f771d71desenorblanco    }
804afc7cce5d68663934128d76963cd501f771d71desenorblanco    return SkIRect::MakeXYWH(d->getOrigin().x(), d->getOrigin().y(), d->width(), d->height());
805210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com}
806210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com
8071f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getDevice() const {
8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
809c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com    MCRec* rec = (MCRec*) fMCStack.front();
8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
811713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    return rec->fLayer->fDevice.get();
8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8140ed3b640c9da71fbbd73c65a4ec1992f85596271Florin MalitaSkBaseDevice* SkCanvas::getTopDevice() const {
815713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    return fMCRec->fTopLayer->fDevice.get();
8169266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com}
8179266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com
81896472deea70169396b8e1f576e470138f55fdb1freedbool SkCanvas::readPixels(const SkImageInfo& dstInfo, void* dstP, size_t rowBytes, int x, int y) {
819a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
820a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!device) {
821a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
822a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
823db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
82403dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    return device->readPixels(dstInfo, dstP, rowBytes, x, y);
82551df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com}
82651df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
82712e946b4bfdf598bffb276776ea6e25439e25265Mike Reedbool SkCanvas::readPixels(const SkPixmap& pm, int x, int y) {
82812e946b4bfdf598bffb276776ea6e25439e25265Mike Reed    return pm.addr() && this->readPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), x, y);
82912e946b4bfdf598bffb276776ea6e25439e25265Mike Reed}
83012e946b4bfdf598bffb276776ea6e25439e25265Mike Reed
83112e946b4bfdf598bffb276776ea6e25439e25265Mike Reedbool SkCanvas::readPixels(const SkBitmap& bm, int x, int y) {
83212e946b4bfdf598bffb276776ea6e25439e25265Mike Reed    SkPixmap pm;
83312e946b4bfdf598bffb276776ea6e25439e25265Mike Reed    return bm.peekPixels(&pm) && this->readPixels(pm, x, y);
83412e946b4bfdf598bffb276776ea6e25439e25265Mike Reed}
83512e946b4bfdf598bffb276776ea6e25439e25265Mike Reed
8364cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
8374edb5d219eb99aa1e8fbe5e37260d3b34314e54bMike Reed    SkPixmap pm;
8384edb5d219eb99aa1e8fbe5e37260d3b34314e54bMike Reed    if (bitmap.peekPixels(&pm)) {
839cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        return this->writePixels(pm.info(), pm.addr(), pm.rowBytes(), x, y);
8404cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8414cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    return false;
8424cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
8434cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
84403dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarettbool SkCanvas::writePixels(const SkImageInfo& srcInfo, const void* pixels, size_t rowBytes,
8454cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                           int x, int y) {
8464cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
8474cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!device) {
8484cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
8494cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8504cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
85103dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // This check gives us an early out and prevents generation ID churn on the surface.
85203dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // This is purely optional: it is a subset of the checks performed by SkWritePixelsRec.
85303dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    SkIRect srcRect = SkIRect::MakeXYWH(x, y, srcInfo.width(), srcInfo.height());
85403dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    if (!srcRect.intersect(0, 0, device->width(), device->height())) {
85503dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett        return false;
8564cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8574cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
85803dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // Tell our owning surface to bump its generation ID.
85903dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    const bool completeOverwrite =
86003dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett            srcRect.size() == SkISize::Make(device->width(), device->height());
861c83a29759a5c2966da5ab973e4fd90763e4c962breed    this->predrawNotify(completeOverwrite);
8624af35f348b2e2f6c428819118eb7a2f2fff53a74reed
86303dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // This can still fail, most notably in the case of a invalid color type or alpha type
86403dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // conversion.  We could pull those checks into this function and avoid the unnecessary
86503dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // generation ID bump.  But then we would be performing those checks twice, since they
86603dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // are also necessary at the bitmap/pixmap entry points.
86703dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    return device->writePixels(srcInfo, pixels, rowBytes, x, y);
8684cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
86951df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8722ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::checkForDeferredSave() {
8732ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
8742ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        this->doSave();
8752ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
8762ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
8772ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
878f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::getSaveCount() const {
8792ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#ifdef SK_DEBUG
8802ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int count = 0;
8812ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkDeque::Iter iter(fMCStack, SkDeque::Iter::kFront_IterStart);
8822ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    for (;;) {
8832ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        const MCRec* rec = (const MCRec*)iter.next();
8842ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (!rec) {
8852ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            break;
8862ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
8872ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        count += 1 + rec->fDeferredSaveCount;
8882ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
8892ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkASSERT(count == fSaveCount);
8902ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#endif
8912ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return fSaveCount;
892f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
893f0090cb80ab10a49e511aa5450ae38917fa058d9reed
894f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::save() {
8952ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount += 1;
8962ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fMCRec->fDeferredSaveCount += 1;
8972ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;  // return our prev value
8982ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
8992ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
9002ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::doSave() {
901f0090cb80ab10a49e511aa5450ae38917fa058d9reed    this->willSave();
902a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita
903a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    SkASSERT(fMCRec->fDeferredSaveCount > 0);
904a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    fMCRec->fDeferredSaveCount -= 1;
9052ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
906f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
907f0090cb80ab10a49e511aa5450ae38917fa058d9reed
908f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restore() {
9092ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
9102ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        SkASSERT(fSaveCount > 1);
9112ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fSaveCount -= 1;
9122ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fMCRec->fDeferredSaveCount -= 1;
9132ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    } else {
9142ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        // check for underflow
9152ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (fMCStack.count() > 1) {
9162ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->willRestore();
9172ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            SkASSERT(fSaveCount > 1);
918a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed            fSaveCount -= 1;
9192ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->internalRestore();
9202ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->didRestore();
9212ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
922f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
923f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
924f0090cb80ab10a49e511aa5450ae38917fa058d9reed
925f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restoreToCount(int count) {
926f0090cb80ab10a49e511aa5450ae38917fa058d9reed    // sanity check
927f0090cb80ab10a49e511aa5450ae38917fa058d9reed    if (count < 1) {
928f0090cb80ab10a49e511aa5450ae38917fa058d9reed        count = 1;
929f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
930f0f14113431ace669f278fdd97b50950f2cf4c80mtklein
931f0090cb80ab10a49e511aa5450ae38917fa058d9reed    int n = this->getSaveCount() - count;
932f0090cb80ab10a49e511aa5450ae38917fa058d9reed    for (int i = 0; i < n; ++i) {
933f0090cb80ab10a49e511aa5450ae38917fa058d9reed        this->restore();
934f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
935f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
936f0090cb80ab10a49e511aa5450ae38917fa058d9reed
9372ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::internalSave() {
9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    MCRec* newTop = (MCRec*)fMCStack.push_back();
939d954498c01ccf0417feacf89e45d0c62a06a813breed    new (newTop) MCRec(*fMCRec);    // balanced in restore()
9408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = newTop;
9414b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
942c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    FOR_EACH_TOP_DEVICE(device->save());
9438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9454960eeec4a1f2a772654883d7f3615d47bcd5dc3reedbool SkCanvas::BoundsAffectsClip(SaveLayerFlags saveLayerFlags) {
9464960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    return !(saveLayerFlags & SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag);
9478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9494960eeec4a1f2a772654883d7f3615d47bcd5dc3reedbool SkCanvas::clipRectBounds(const SkRect* bounds, SaveLayerFlags saveLayerFlags,
9509b3aa54bc9605257c701cf465813f5fb1d7ba39ereed                              SkIRect* intersection, const SkImageFilter* imageFilter) {
951918e144408ba218df919528f8b48c544f4767883Mike Reed    SkIRect clipBounds = this->getDeviceClipBounds();
952918e144408ba218df919528f8b48c544f4767883Mike Reed    if (clipBounds.isEmpty()) {
953a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        return false;
954f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
955c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
95696e657d0e103b8358a77ecd913f6086929f792b8reed    const SkMatrix& ctm = fMCRec->fMatrix;  // this->getTotalMatrix()
95796e657d0e103b8358a77ecd913f6086929f792b8reed
958c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (imageFilter) {
959e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco        clipBounds = imageFilter->filterBounds(clipBounds, ctm);
960db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco        if (bounds && !imageFilter->canComputeFastBounds()) {
961db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco            bounds = nullptr;
962db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco        }
963c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
964bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ir;
96549f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
9668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect r;
9674b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
96896e657d0e103b8358a77ecd913f6086929f792b8reed        ctm.mapRect(&r, *bounds);
9698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r.roundOut(&ir);
9708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // early exit if the layer's bounds are clipped out
9718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!ir.intersect(clipBounds)) {
9724960eeec4a1f2a772654883d7f3615d47bcd5dc3reed            if (BoundsAffectsClip(saveLayerFlags)) {
973a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed                fMCRec->fTopLayer->fDevice->clipRegion(SkRegion(), SkClipOp::kIntersect); // empty
9741f836ee096bb988adef4b9757b2629c7afeda36dreed                fMCRec->fRasterClip.setEmpty();
975fbfa25802709139c2f14e304319c9541da65ca27msarett                fDeviceClipBounds.setEmpty();
976bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            }
977a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org            return false;
9788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // no user bounds, so just use the clip
9808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ir = clipBounds;
9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
982180aec43451dd951fdaae81a92efc710ba093260reed    SkASSERT(!ir.isEmpty());
9838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9844960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    if (BoundsAffectsClip(saveLayerFlags)) {
985180aec43451dd951fdaae81a92efc710ba093260reed        // Simplify the current clips since they will be applied properly during restore()
986180aec43451dd951fdaae81a92efc710ba093260reed        fMCRec->fRasterClip.setRect(ir);
987fbfa25802709139c2f14e304319c9541da65ca27msarett        fDeviceClipBounds = qr_clip_bounds(ir);
988a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
989a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
990a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    if (intersection) {
991a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        *intersection = ir;
992a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
993a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return true;
994a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org}
995a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
9964960eeec4a1f2a772654883d7f3615d47bcd5dc3reed
9974960eeec4a1f2a772654883d7f3615d47bcd5dc3reedint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
9984960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    return this->saveLayer(SaveLayerRec(bounds, paint, 0));
999d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
1000d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
10014960eeec4a1f2a772654883d7f3615d47bcd5dc3reedint SkCanvas::saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint) {
10024960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    return this->saveLayer(SaveLayerRec(bounds, paint, kPreserveLCDText_SaveLayerFlag));
10034960eeec4a1f2a772654883d7f3615d47bcd5dc3reed}
10044960eeec4a1f2a772654883d7f3615d47bcd5dc3reed
10054960eeec4a1f2a772654883d7f3615d47bcd5dc3reedint SkCanvas::saveLayer(const SaveLayerRec& origRec) {
100653f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita    SkTCopyOnFirstWrite<SaveLayerRec> rec(origRec);
1007d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    if (gIgnoreSaveLayerBounds) {
100853f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita        rec.writable()->fBounds = nullptr;
1009d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    }
101053f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita
101153f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita    SaveLayerStrategy strategy = this->getSaveLayerStrategy(*rec);
1012a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed    fSaveCount += 1;
101353f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita    this->internalSaveLayer(*rec, strategy);
10142ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;
10158926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
10168926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
1017a2217ef965e57fdbbf989989e7ec1f2c04f62d39reedvoid SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter,
1018c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed                                    SkBaseDevice* dst, const SkIPoint& dstOrigin,
1019a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed                                    const SkMatrix& ctm) {
1020a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    SkDraw draw;
1021a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    SkRasterClip rc;
1022a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    rc.setRect(SkIRect::MakeWH(dst->width(), dst->height()));
1023a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    if (!dst->accessPixels(&draw.fDst)) {
1024a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        draw.fDst.reset(dst->imageInfo(), nullptr, 0);
1025a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    }
1026a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    draw.fMatrix = &SkMatrix::I();
1027a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    draw.fRC = &rc;
10287354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips
10297354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips    SkPaint p;
1030c61abeed8958a757c6b49937f28b63066148dd67Mike Reed    if (filter) {
1031c61abeed8958a757c6b49937f28b63066148dd67Mike Reed        p.setImageFilter(filter->makeWithLocalMatrix(ctm));
1032c61abeed8958a757c6b49937f28b63066148dd67Mike Reed    }
1033a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed
1034c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    int x = src->getOrigin().x() - dstOrigin.x();
1035c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    int y = src->getOrigin().y() - dstOrigin.y();
1036a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    auto special = src->snapSpecial();
1037a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    if (special) {
103853f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita        dst->drawSpecial(special.get(), x, y, p, nullptr, SkMatrix::I());
1039a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    }
10407354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips}
104170ee31b2fa127eee6c0cea61cf05508e9d3ca7b1reed
1042129ed1cd6d792f3f6cf563aefa9756fc6308289dreedstatic SkImageInfo make_layer_info(const SkImageInfo& prev, int w, int h, bool isOpaque,
1043129ed1cd6d792f3f6cf563aefa9756fc6308289dreed                                   const SkPaint* paint) {
1044129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    // need to force L32 for now if we have an image filter. Once filters support other colortypes
1045129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    // e.g. sRGB or F16, we can remove this check
104652ede1d905728cdcaa98db1e4a33724f5a85c62dbrianosman    // SRGBTODO: Can we remove this check now?
1047129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    const bool hasImageFilter = paint && paint->getImageFilter();
1048129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
1049129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    SkAlphaType alphaType = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
1050129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    if ((prev.bytesPerPixel() < 4) || hasImageFilter) {
1051129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        // force to L32
1052129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        return SkImageInfo::MakeN32(w, h, alphaType);
1053129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    } else {
1054129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        // keep the same characteristics as the prev
1055693fdbd6b81a860657612e7604430dd55d6e721bMike Reed        return SkImageInfo::Make(w, h, prev.colorType(), alphaType, prev.refColorSpace());
1056129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    }
1057129ed1cd6d792f3f6cf563aefa9756fc6308289dreed}
1058129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
10594960eeec4a1f2a772654883d7f3615d47bcd5dc3reedvoid SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy strategy) {
10604960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    const SkRect* bounds = rec.fBounds;
10614960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    const SkPaint* paint = rec.fPaint;
10624960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    SaveLayerFlags saveLayerFlags = rec.fSaveLayerFlags;
10634960eeec4a1f2a772654883d7f3615d47bcd5dc3reed
10648c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkLazyPaint lazyP;
10658c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkImageFilter* imageFilter = paint ? paint->getImageFilter() : NULL;
10668c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkMatrix stashedMatrix = fMCRec->fMatrix;
10678c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkMatrix remainder;
10688c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkSize scale;
10698c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    /*
10708c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  ImageFilters (so far) do not correctly handle matrices (CTM) that contain rotation/skew/etc.
10718c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  but they do handle scaling. To accommodate this, we do the following:
10728c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *
10738c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  1. Stash off the current CTM
10748c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  2. Decompose the CTM into SCALE and REMAINDER
10758c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  3. Wack the CTM to be just SCALE, and wrap the imagefilter with a MatrixImageFilter that
10768c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *     contains the REMAINDER
10778c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  4. Proceed as usual, allowing the client to draw into the layer (now with a scale-only CTM)
10788c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  5. During restore, we process the MatrixImageFilter, which applies REMAINDER to the output
10798c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *     of the original imagefilter, and draw that (via drawSprite)
10808c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  6. Unwack the CTM to its original state (i.e. stashedMatrix)
10818c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *
10828c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  Perhaps in the future we could augment #5 to apply REMAINDER as part of the draw (no longer
10838c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  a sprite operation) to avoid the extra buffer/overhead of MatrixImageFilter.
10848c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     */
108596a04f329926099f0002f97883242793ff04f61creed    if (imageFilter && !stashedMatrix.isScaleTranslate() && !imageFilter->canHandleComplexCTM() &&
10868c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        stashedMatrix.decomposeScale(&scale, &remainder))
10878c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    {
10888c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        // We will restore the matrix (which we are overwriting here) in restore via fStashedMatrix
10898c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        this->internalSetMatrix(SkMatrix::MakeScale(scale.width(), scale.height()));
10908c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        SkPaint* p = lazyP.set(*paint);
10918c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        p->setImageFilter(SkImageFilter::MakeMatrixFilter(remainder,
10928c30a8196dd5903d2d23b4d0a5dc888e802bf698reed                                                          SkFilterQuality::kLow_SkFilterQuality,
10938c30a8196dd5903d2d23b4d0a5dc888e802bf698reed                                                          sk_ref_sp(imageFilter)));
10948c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        imageFilter = p->getImageFilter();
10958c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        paint = p;
10968c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    }
10978c30a8196dd5903d2d23b4d0a5dc888e802bf698reed
1098a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // do this before we create the layer. We don't call the public save() since
1099a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // that would invoke a possibly overridden virtual
11002ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
1101a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1102a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    SkIRect ir;
11038c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, imageFilter)) {
11042ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
11058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1107e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
1108e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // the clipRectBounds() call above?
1109e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    if (kNoLayer_SaveLayerStrategy == strategy) {
11102ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1111e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    }
1112e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
11134960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    bool isOpaque = SkToBool(saveLayerFlags & kIsOpaque_SaveLayerFlag);
11148dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    SkPixelGeometry geo = fProps.pixelGeometry();
11158dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    if (paint) {
111676033be81b82c44fd5d4fdf2672eb22e505da1f0reed        // TODO: perhaps add a query to filters so we might preserve opaqueness...
1117daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        if (paint->getImageFilter() || paint->getColorFilter()) {
111876033be81b82c44fd5d4fdf2672eb22e505da1f0reed            isOpaque = false;
11198dc0ccb8d33d1af7dd13228509e61fe915bc7705reed            geo = kUnknown_SkPixelGeometry;
1120b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com        }
1121b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    }
11228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11235139e501c5ac3a511e35c78395c907a176113451robertphillips    SkBaseDevice* priorDevice = this->getTopDevice();
1124c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    if (nullptr == priorDevice) {   // Do we still need this check???
1125b2db898573e3cdcc8234eebf51961bfc4977ebbcreed        SkDebugf("Unable to find device for layer.");
11262ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1127b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    }
1128b2db898573e3cdcc8234eebf51961bfc4977ebbcreed
11295139e501c5ac3a511e35c78395c907a176113451robertphillips    SkImageInfo info = make_layer_info(priorDevice->imageInfo(), ir.width(), ir.height(), isOpaque,
1130129ed1cd6d792f3f6cf563aefa9756fc6308289dreed                                       paint);
1131129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
1132704cd32e4a92d6c3eae6bfae4adcc20126bf4437Hal Canary    sk_sp<SkBaseDevice> newDevice;
113361f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    {
113470ee31b2fa127eee6c0cea61cf05508e9d3ca7b1reed        const bool preserveLCDText = kOpaque_SkAlphaType == info.alphaType() ||
11354960eeec4a1f2a772654883d7f3615d47bcd5dc3reed                                     (saveLayerFlags & kPreserveLCDText_SaveLayerFlag);
1136daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
113770ee31b2fa127eee6c0cea61cf05508e9d3ca7b1reed        const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo,
1138356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                                                                             preserveLCDText,
1139356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                                                                             fAllocator.get());
11405139e501c5ac3a511e35c78395c907a176113451robertphillips        newDevice.reset(priorDevice->onCreateDevice(createInfo, paint));
11415139e501c5ac3a511e35c78395c907a176113451robertphillips        if (!newDevice) {
11427503d60847c4ad22df87458aecd917772b23d293reed            return;
114361f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        }
1144e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com    }
114553f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita    DeviceCM* layer = new DeviceCM(newDevice, paint, stashedMatrix, rec.fClipMask, rec.fClipMatrix);
11468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1147b43a3e0160b3854a04305decd1d9e766a3889b3aMike Reed    // only have a "next" if this new layer doesn't affect the clip (rare)
1148b43a3e0160b3854a04305decd1d9e766a3889b3aMike Reed    layer->fNext = BoundsAffectsClip(saveLayerFlags) ? nullptr : fMCRec->fTopLayer;
11498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = layer;
11508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
1151a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed
1152c61abeed8958a757c6b49937f28b63066148dd67Mike Reed    if ((rec.fSaveLayerFlags & kInitWithPrevious_SaveLayerFlag) || rec.fBackdrop) {
1153c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        DrawDeviceWithFilter(priorDevice, rec.fBackdrop, newDevice.get(), { ir.fLeft, ir.fTop },
1154a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed                             fMCRec->fMatrix);
1155a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    }
1156c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
1157c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    newDevice->setOrigin(fMCRec->fMatrix, ir.fLeft, ir.fTop);
1158c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
1159c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    newDevice->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
1160c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    if (layer->fNext) {
1161c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        // need to punch a hole in the previous device, so we don't draw there, given that
1162c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        // the new top-layer will allow drawing to happen "below" it.
1163c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        SkRegion hole(ir);
1164c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        do {
1165c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed            layer = layer->fNext;
1166c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed            layer->fDevice->clipRegion(hole, SkClipOp::kDifference);
1167c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        } while (layer->fNext);
1168c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    }
11698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1171d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
1172bada1885da479d948f065182d6dfa85a1140bda5reed    if (0xFF == alpha) {
1173bada1885da479d948f065182d6dfa85a1140bda5reed        return this->saveLayer(bounds, nullptr);
1174bada1885da479d948f065182d6dfa85a1140bda5reed    } else {
1175bada1885da479d948f065182d6dfa85a1140bda5reed        SkPaint tmpPaint;
1176bada1885da479d948f065182d6dfa85a1140bda5reed        tmpPaint.setAlpha(alpha);
1177bada1885da479d948f065182d6dfa85a1140bda5reed        return this->saveLayer(bounds, &tmpPaint);
1178bada1885da479d948f065182d6dfa85a1140bda5reed    }
1179d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
1180d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
11818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() {
11828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fMCStack.count() != 0);
11838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
118488edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    // reserve our layer (if any)
11858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM* layer = fMCRec->fLayer;   // may be null
11868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
118796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fMCRec->fLayer = nullptr;
11888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now do the normal restore()
11908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->~MCRec();       // balanced in save()
11918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCStack.pop_back();
11928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.back();
11938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1194c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    if (fMCRec) {
1195c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        FOR_EACH_TOP_DEVICE(device->restore(fMCRec->fMatrix));
1196c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    }
1197c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
11988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
11998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        since if we're being recorded, we don't want to record this (the
12008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        recorder will have already recorded the restore).
12018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
120249f085dddff10473b6ebf832a974288300224e60bsalomon    if (layer) {
1203b43a3e0160b3854a04305decd1d9e766a3889b3aMike Reed        if (fMCRec) {
12046f8f292aa768869a9e85c314b124875f57504f2creed@google.com            const SkIPoint& origin = layer->fDevice->getOrigin();
1205713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita            this->internalDrawDevice(layer->fDevice.get(), origin.x(), origin.y(),
120653f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita                                     layer->fPaint.get(),
120753f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita                                     layer->fClipImage.get(), layer->fClipMatrix);
12088c30a8196dd5903d2d23b4d0a5dc888e802bf698reed            // restore what we smashed in internalSaveLayer
12098c30a8196dd5903d2d23b4d0a5dc888e802bf698reed            fMCRec->fMatrix = layer->fStashedMatrix;
12108926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // reset this, since internalDrawDevice will have set it to true
1211385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            delete layer;
1212b679ca8926a832274b14fdb512f88f64b61d32eareed        } else {
1213b679ca8926a832274b14fdb512f88f64b61d32eareed            // we're at the root
1214a499f905e9340e4935447f2562fd92e8853382b1reed            SkASSERT(layer == (void*)fDeviceCMStorage);
1215b679ca8926a832274b14fdb512f88f64b61d32eareed            layer->~DeviceCM();
12168c30a8196dd5903d2d23b4d0a5dc888e802bf698reed            // no need to update fMCRec, 'cause we're killing the canvas
12178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
121888edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
1219fbfa25802709139c2f14e304319c9541da65ca27msarett
1220fbfa25802709139c2f14e304319c9541da65ca27msarett    if (fMCRec) {
12219637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett        fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate();
1222fbfa25802709139c2f14e304319c9541da65ca27msarett        fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1223fbfa25802709139c2f14e304319c9541da65ca27msarett    }
12248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1226e8f3062a36d3682f4019309a32b5b84dc9eddf8creedsk_sp<SkSurface> SkCanvas::makeSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
122796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == props) {
12284a8126e7f81384526629b1e21bf89b632ea13cd9reed        props = &fProps;
12294a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
12304a8126e7f81384526629b1e21bf89b632ea13cd9reed    return this->onNewSurface(info, *props);
123176f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
123276f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
1233e8f3062a36d3682f4019309a32b5b84dc9eddf8creedsk_sp<SkSurface> SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
123476f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    SkBaseDevice* dev = this->getDevice();
1235e8f3062a36d3682f4019309a32b5b84dc9eddf8creed    return dev ? dev->makeSurface(info, props) : nullptr;
123676f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
123776f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
1238c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkImageInfo SkCanvas::imageInfo() const {
1239ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed    return this->onImageInfo();
1240ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed}
1241ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed
1242ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reedSkImageInfo SkCanvas::onImageInfo() const {
1243c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1244c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (dev) {
1245c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return dev->imageInfo();
1246c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1247900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        return SkImageInfo::MakeUnknown(0, 0);
1248c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1249c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1250c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1251898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosmanbool SkCanvas::getProps(SkSurfaceProps* props) const {
1252ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed    return this->onGetProps(props);
1253ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed}
1254ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed
1255ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reedbool SkCanvas::onGetProps(SkSurfaceProps* props) const {
1256898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman    SkBaseDevice* dev = this->getDevice();
1257898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman    if (dev) {
1258898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman        if (props) {
1259898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman            *props = fProps;
1260898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman        }
1261898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman        return true;
1262898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman    } else {
1263898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman        return false;
1264898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman    }
1265898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman}
1266898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman
12676ceeebd37a43d879c120b6ba100ae1febdd67a18reedbool SkCanvas::peekPixels(SkPixmap* pmap) {
12686ceeebd37a43d879c120b6ba100ae1febdd67a18reed    return this->onPeekPixels(pmap);
1269c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1270c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1271884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onPeekPixels(SkPixmap* pmap) {
1272c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1273884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->peekPixels(pmap);
1274c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1275c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
12766b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.orgvoid* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
1277884e97cb04db7ed053a866567ee9c6e4c01f993areed    SkPixmap pmap;
1278884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (!this->onAccessTopLayerPixels(&pmap)) {
127996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
1280884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1281884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (info) {
1282884e97cb04db7ed053a866567ee9c6e4c01f993areed        *info = pmap.info();
1283884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1284884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (rowBytes) {
1285884e97cb04db7ed053a866567ee9c6e4c01f993areed        *rowBytes = pmap.rowBytes();
1286884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1287884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (origin) {
12880ed3b640c9da71fbbd73c65a4ec1992f85596271Florin Malita        *origin = this->getTopDevice()->getOrigin();
12896b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    }
1290884e97cb04db7ed053a866567ee9c6e4c01f993areed    return pmap.writable_addr();
12919c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
12929c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1293884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
12949c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
1295884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->accessPixels(pmap);
12969c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
12979c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1298520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////
12998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
130053f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malitavoid SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, const SkPaint* paint,
130153f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita                                  SkImage* clipImage, const SkMatrix& clipMatrix) {
13028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint tmp;
130396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
13048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &tmp;
13058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13064b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
13078926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1308a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed
13098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
13101f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        SkBaseDevice* dstDev = iter.fDevice;
131176dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        paint = &looper.paint();
131276dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkImageFilter* filter = paint->getImageFilter();
131376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
131453f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita        if (filter || clipImage) {
1315833dcf48844dd053ddf7ecea20e3e1c2b6b47e01Robert Phillips            sk_sp<SkSpecialImage> specialImage = srcDev->snapSpecial();
1316833dcf48844dd053ddf7ecea20e3e1c2b6b47e01Robert Phillips            if (specialImage) {
131753f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita                dstDev->drawSpecial(specialImage.get(), pos.x(), pos.y(), *paint,
131853f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita                                    clipImage, clipMatrix);
1319833dcf48844dd053ddf7ecea20e3e1c2b6b47e01Robert Phillips            }
132076dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        } else {
1321a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            dstDev->drawDevice(srcDev, pos.x(), pos.y(), *paint);
132276dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        }
13238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1324a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed
13254e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
13268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
132832704674f64cb6a14356dfebe060cd3484c06cc7reed/////////////////////////////////////////////////////////////////////////////
1329da420b976e61071cfe5de10556b4b23e519091d6reed
133092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::translate(SkScalar dx, SkScalar dy) {
1331fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed    if (dx || dy) {
1332fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        this->checkForDeferredSave();
1333fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        fMCRec->fMatrix.preTranslate(dx,dy);
1334cbdf007bc2eb85056a1a5c75c088202becba2d16mtklein
1335fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        // Translate shouldn't affect the is-scale-translateness of the matrix.
1336fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
1337cbdf007bc2eb85056a1a5c75c088202becba2d16mtklein
1338c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
1339c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
1340fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        this->didTranslate(dx,dy);
1341fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed    }
13428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
134492362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::scale(SkScalar sx, SkScalar sy) {
1345d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1346d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setScale(sx, sy);
1347d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
135092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::rotate(SkScalar degrees) {
1351d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1352d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setRotate(degrees);
1353d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
13548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13567438bfc0804d021aa92cdd5ea644994a4248f3dbbungemanvoid SkCanvas::rotate(SkScalar degrees, SkScalar px, SkScalar py) {
13577438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman    SkMatrix m;
13587438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman    m.setRotate(degrees, px, py);
13597438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman    this->concat(m);
13607438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman}
13617438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman
136292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::skew(SkScalar sx, SkScalar sy) {
1363d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1364d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setSkew(sx, sy);
1365d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
136644c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
136744c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
136892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::concat(const SkMatrix& matrix) {
1369d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    if (matrix.isIdentity()) {
1370d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        return;
1371d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    }
1372d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org
13732ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
13741f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix.preConcat(matrix);
13759637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate();
13767627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
13777627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
13787627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
137944c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didConcat(matrix);
138044c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
138144c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
13828c30a8196dd5903d2d23b4d0a5dc888e802bf698reedvoid SkCanvas::internalSetMatrix(const SkMatrix& matrix) {
13831f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix = matrix;
13849da5a5a198e5dc9148f7f30a6089377590eee55bmsarett    fIsScaleTranslate = matrix.isScaleTranslate();
1385c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
1386c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
13878c30a8196dd5903d2d23b4d0a5dc888e802bf698reed}
13888c30a8196dd5903d2d23b4d0a5dc888e802bf698reed
13898c30a8196dd5903d2d23b4d0a5dc888e802bf698reedvoid SkCanvas::setMatrix(const SkMatrix& matrix) {
13908c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    this->checkForDeferredSave();
13918c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    this->internalSetMatrix(matrix);
139244c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didSetMatrix(matrix);
13938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() {
13968c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    this->setMatrix(SkMatrix::I());
13978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
14008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1401c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::clipRect(const SkRect& rect, SkClipOp op, bool doAA) {
14022ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14038f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
14048f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRect(rect, op, edgeStyle);
14058f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
14068f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
1407c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
1408a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    const bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
14097627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
14107627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    FOR_EACH_TOP_DEVICE(device->clipRect(rect, op, isAA));
14117627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
1412c64eff55049b1192052b791549a32a03be1c43e3reed    AutoValidateClip avc(this);
1413a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    fMCRec->fRasterClip.op(rect, fMCRec->fMatrix, this->getTopLayerBounds(), (SkRegion::Op)op,
1414a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon                           isAA);
1415fbfa25802709139c2f14e304319c9541da65ca27msarett    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
14168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14185f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Ilievvoid SkCanvas::androidFramework_setDeviceClipRestriction(const SkIRect& rect) {
14195f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev    fClipRestrictionRect = rect;
1420d519d484949161df6d4b2ecadc282427cab532cfMike Reed    if (fClipRestrictionRect.isEmpty()) {
1421d519d484949161df6d4b2ecadc282427cab532cfMike Reed        // we notify the device, but we *dont* resolve deferred saves (since we're just
1422d519d484949161df6d4b2ecadc282427cab532cfMike Reed        // removing the restriction if the rect is empty. how I hate this api.
1423d519d484949161df6d4b2ecadc282427cab532cfMike Reed        FOR_EACH_TOP_DEVICE(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect));
1424d519d484949161df6d4b2ecadc282427cab532cfMike Reed    } else {
14255f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev        this->checkForDeferredSave();
1426d519d484949161df6d4b2ecadc282427cab532cfMike Reed        FOR_EACH_TOP_DEVICE(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect));
14275f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev        AutoValidateClip avc(this);
14285f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev        fMCRec->fRasterClip.op(fClipRestrictionRect, SkRegion::kIntersect_Op);
14295f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev        fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
14305f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev    }
14315f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev}
14325f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev
1433c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::clipRRect(const SkRRect& rrect, SkClipOp op, bool doAA) {
14342ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14358f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
14364ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
14378f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(rrect.getBounds(), op, edgeStyle);
14388f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
14398f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRRect(rrect, op, edgeStyle);
14404ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
14418f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
144214e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
1443c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
1444a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    AutoValidateClip avc(this);
144514e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
1446a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
14477627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
14487627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    FOR_EACH_TOP_DEVICE(device->clipRRect(rrect, op, isAA));
1449a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
1450a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    fMCRec->fRasterClip.op(rrect, fMCRec->fMatrix, this->getTopLayerBounds(), (SkRegion::Op)op,
1451a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon                           isAA);
1452a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
14534ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
14544ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1455c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::clipPath(const SkPath& path, SkClipOp op, bool doAA) {
14562ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14578f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
145839f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips
145939f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips    if (!path.isInverseFillType() && fMCRec->fMatrix.rectStaysRect()) {
146039f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        SkRect r;
146139f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        if (path.isRect(&r)) {
146239f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            this->onClipRect(r, op, edgeStyle);
146339f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            return;
146439f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        }
146539f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        SkRRect rrect;
146639f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        if (path.isOval(&r)) {
146739f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            rrect.setOval(r);
146839f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            this->onClipRRect(rrect, op, edgeStyle);
146939f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            return;
147039f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        }
147139f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        if (path.isRRect(&rrect)) {
147239f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            this->onClipRRect(rrect, op, edgeStyle);
147339f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            return;
147439f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        }
14758f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
147639f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips
147739f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips    this->onClipPath(path, op, edgeStyle);
14788f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
14798f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
1480c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
14815c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
14825c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1483a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
14847627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
14857627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    FOR_EACH_TOP_DEVICE(device->clipPath(path, op, isAA));
14865c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1487a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    const SkPath* rasterClipPath = &path;
1488a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    const SkMatrix* matrix = &fMCRec->fMatrix;
1489a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    fMCRec->fRasterClip.op(*rasterClipPath, *matrix, this->getTopLayerBounds(), (SkRegion::Op)op,
1490a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon                           isAA);
1491fbfa25802709139c2f14e304319c9541da65ca27msarett    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
14928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1494c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::clipRegion(const SkRegion& rgn, SkClipOp op) {
14952ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14968f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRegion(rgn, op);
14978f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
14988f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
1499c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::onClipRegion(const SkRegion& rgn, SkClipOp op) {
15007627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    FOR_EACH_TOP_DEVICE(device->clipRegion(rgn, op));
150127d07f0acb85eea4062075dfbe9148ce12d92c66Mike Reed
1502a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    AutoValidateClip avc(this);
150327d07f0acb85eea4062075dfbe9148ce12d92c66Mike Reed
150473603f3c52ffd89fe9d035be827b566a0e7d3b79reed    fMCRec->fRasterClip.op(rgn, (SkRegion::Op)op);
1505fbfa25802709139c2f14e304319c9541da65ca27msarett    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
15068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1508819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG
1509819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const {
1510819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    // construct clipRgn from the clipstack
15111f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    const SkBaseDevice* device = this->getDevice();
1512ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    if (!device) {
15135c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org        SkASSERT(this->isClipEmpty());
1514ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return;
1515ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
1516819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1517819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif
1518819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1519a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedbool SkCanvas::androidFramework_isClipAA() const {
1520a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    bool containsAA = false;
1521a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
1522a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    FOR_EACH_TOP_DEVICE(containsAA |= device->onClipIsAA());
1523a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
1524a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    return containsAA;
1525a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed}
1526a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
1527a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedclass RgnAccumulator {
1528a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    SkRegion* fRgn;
1529a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedpublic:
1530a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    RgnAccumulator(SkRegion* total) : fRgn(total) {}
1531a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void accumulate(SkBaseDevice* device, SkRegion* rgn) {
1532a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        SkIPoint origin = device->getOrigin();
1533a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        if (origin.x() | origin.y()) {
1534a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            rgn->translate(origin.x(), origin.y());
1535a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        }
1536a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        fRgn->op(*rgn, SkRegion::kUnion_Op);
1537a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    }
1538a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed};
1539a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
1540a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedvoid SkCanvas::temporary_internal_getRgnClip(SkRegion* rgn) {
1541a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    RgnAccumulator accum(rgn);
1542a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    SkRegion tmp;
1543a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
1544a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    rgn->setEmpty();
1545a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    FOR_EACH_TOP_DEVICE(device->onAsRgnClip(&tmp); accum.accumulate(device, &tmp));
154690c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com}
154790c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com
15485c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com///////////////////////////////////////////////////////////////////////////////
15495c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1550754de5f65b466f721d952a379194cc94de376f42reed@google.combool SkCanvas::isClipEmpty() const {
155102be3c1c3f53858263df82b1db466b5bb7059ab0Mike Reed    return fMCRec->fRasterClip.isEmpty();
155202be3c1c3f53858263df82b1db466b5bb7059ab0Mike Reed
155302be3c1c3f53858263df82b1db466b5bb7059ab0Mike Reed    // TODO: should we only use the conservative answer in a recording canvas?
155402be3c1c3f53858263df82b1db466b5bb7059ab0Mike Reed#if 0
1555a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    SkBaseDevice* dev = this->getTopDevice();
1556a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    // if no device we return true
1557a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    return !dev || dev->onGetClipType() == SkBaseDevice::kEmpty_ClipType;
155802be3c1c3f53858263df82b1db466b5bb7059ab0Mike Reed#endif
1559754de5f65b466f721d952a379194cc94de376f42reed@google.com}
1560754de5f65b466f721d952a379194cc94de376f42reed@google.com
15615c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgbool SkCanvas::isClipRect() const {
1562a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    SkBaseDevice* dev = this->getTopDevice();
1563a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    // if no device we return false
1564a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    return dev && dev->onGetClipType() == SkBaseDevice::kRect_ClipType;
15655c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
15665c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
1567fbfa25802709139c2f14e304319c9541da65ca27msarettstatic inline bool is_nan_or_clipped(const Sk4f& devRect, const Sk4f& devClip) {
1568fbfa25802709139c2f14e304319c9541da65ca27msarett#if !defined(SKNX_NO_SIMD) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
1569fbfa25802709139c2f14e304319c9541da65ca27msarett    __m128 lLtT = _mm_unpacklo_ps(devRect.fVec, devClip.fVec);
1570fbfa25802709139c2f14e304319c9541da65ca27msarett    __m128 RrBb = _mm_unpackhi_ps(devClip.fVec, devRect.fVec);
1571fbfa25802709139c2f14e304319c9541da65ca27msarett    __m128 mask = _mm_cmplt_ps(lLtT, RrBb);
1572fbfa25802709139c2f14e304319c9541da65ca27msarett    return 0xF != _mm_movemask_ps(mask);
1573fbfa25802709139c2f14e304319c9541da65ca27msarett#elif !defined(SKNX_NO_SIMD) && defined(SK_ARM_HAS_NEON)
1574fbfa25802709139c2f14e304319c9541da65ca27msarett    float32x4_t lLtT = vzipq_f32(devRect.fVec, devClip.fVec).val[0];
1575fbfa25802709139c2f14e304319c9541da65ca27msarett    float32x4_t RrBb = vzipq_f32(devClip.fVec, devRect.fVec).val[1];
1576fbfa25802709139c2f14e304319c9541da65ca27msarett    uint32x4_t mask = vcltq_f32(lLtT, RrBb);
1577fbfa25802709139c2f14e304319c9541da65ca27msarett    return 0xFFFFFFFFFFFFFFFF != (uint64_t) vmovn_u32(mask);
1578fbfa25802709139c2f14e304319c9541da65ca27msarett#else
1579fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect devRectAsRect;
1580fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect devClipAsRect;
1581fbfa25802709139c2f14e304319c9541da65ca27msarett    devRect.store(&devRectAsRect.fLeft);
1582fbfa25802709139c2f14e304319c9541da65ca27msarett    devClip.store(&devClipAsRect.fLeft);
1583fbfa25802709139c2f14e304319c9541da65ca27msarett    return !devRectAsRect.isFinite() || !devRectAsRect.intersect(devClipAsRect);
1584fbfa25802709139c2f14e304319c9541da65ca27msarett#endif
1585fbfa25802709139c2f14e304319c9541da65ca27msarett}
1586fbfa25802709139c2f14e304319c9541da65ca27msarett
1587fbfa25802709139c2f14e304319c9541da65ca27msarett// It's important for this function to not be inlined.  Otherwise the compiler will share code
1588fbfa25802709139c2f14e304319c9541da65ca27msarett// between the fast path and the slow path, resulting in two slow paths.
1589fbfa25802709139c2f14e304319c9541da65ca27msarettstatic SK_NEVER_INLINE bool quick_reject_slow_path(const SkRect& src, const SkRect& deviceClip,
1590fbfa25802709139c2f14e304319c9541da65ca27msarett                                                   const SkMatrix& matrix) {
1591fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect deviceRect;
1592fbfa25802709139c2f14e304319c9541da65ca27msarett    matrix.mapRect(&deviceRect, src);
1593fbfa25802709139c2f14e304319c9541da65ca27msarett    return !deviceRect.isFinite() || !deviceRect.intersect(deviceClip);
1594fbfa25802709139c2f14e304319c9541da65ca27msarett}
1595d22a817ff57986407facd16af36320fc86ce02damsarett
1596fbfa25802709139c2f14e304319c9541da65ca27msarettbool SkCanvas::quickReject(const SkRect& src) const {
1597fbfa25802709139c2f14e304319c9541da65ca27msarett#ifdef SK_DEBUG
1598fbfa25802709139c2f14e304319c9541da65ca27msarett    // Verify that fDeviceClipBounds are set properly.
1599fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect tmp = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
16001f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fRasterClip.isEmpty()) {
16010c685ee188a5e500df25a34fa6edfceb4cbb795cmsarett        SkASSERT(fDeviceClipBounds.isEmpty());
1602fbfa25802709139c2f14e304319c9541da65ca27msarett    } else {
1603fbfa25802709139c2f14e304319c9541da65ca27msarett        SkASSERT(tmp == fDeviceClipBounds);
16048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16069637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    // Verify that fIsScaleTranslate is set properly.
16079637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
1608fbfa25802709139c2f14e304319c9541da65ca27msarett#endif
1609d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
16109637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    if (!fIsScaleTranslate) {
1611fbfa25802709139c2f14e304319c9541da65ca27msarett        return quick_reject_slow_path(src, fDeviceClipBounds, fMCRec->fMatrix);
16128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1613fbfa25802709139c2f14e304319c9541da65ca27msarett
1614fbfa25802709139c2f14e304319c9541da65ca27msarett    // We inline the implementation of mapScaleTranslate() for the fast path.
1615fbfa25802709139c2f14e304319c9541da65ca27msarett    float sx = fMCRec->fMatrix.getScaleX();
1616fbfa25802709139c2f14e304319c9541da65ca27msarett    float sy = fMCRec->fMatrix.getScaleY();
1617fbfa25802709139c2f14e304319c9541da65ca27msarett    float tx = fMCRec->fMatrix.getTranslateX();
1618fbfa25802709139c2f14e304319c9541da65ca27msarett    float ty = fMCRec->fMatrix.getTranslateY();
1619fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f scale(sx, sy, sx, sy);
1620fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f trans(tx, ty, tx, ty);
1621fbfa25802709139c2f14e304319c9541da65ca27msarett
1622fbfa25802709139c2f14e304319c9541da65ca27msarett    // Apply matrix.
1623fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f ltrb = Sk4f::Load(&src.fLeft) * scale + trans;
1624fbfa25802709139c2f14e304319c9541da65ca27msarett
1625fbfa25802709139c2f14e304319c9541da65ca27msarett    // Make sure left < right, top < bottom.
1626fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f rblt(ltrb[2], ltrb[3], ltrb[0], ltrb[1]);
1627fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f min = Sk4f::Min(ltrb, rblt);
1628fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f max = Sk4f::Max(ltrb, rblt);
1629fbfa25802709139c2f14e304319c9541da65ca27msarett    // We can extract either pair [0,1] or [2,3] from min and max and be correct, but on
1630fbfa25802709139c2f14e304319c9541da65ca27msarett    // ARM this sequence generates the fastest (a single instruction).
1631fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f devRect = Sk4f(min[2], min[3], max[0], max[1]);
1632fbfa25802709139c2f14e304319c9541da65ca27msarett
1633fbfa25802709139c2f14e304319c9541da65ca27msarett    // Check if the device rect is NaN or outside the clip.
1634fbfa25802709139c2f14e304319c9541da65ca27msarett    return is_nan_or_clipped(devRect, Sk4f::Load(&fDeviceClipBounds.fLeft));
16358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16373b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkPath& path) const {
16383b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com    return path.isEmpty() || this->quickReject(path.getBounds());
16398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
164142e8c53b3ef58f887a623b410d9783b4d4ab4921Mike ReedSkRect SkCanvas::onGetLocalClipBounds() const {
164242e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    SkIRect ibounds = this->onGetDeviceClipBounds();
1643918e144408ba218df919528f8b48c544f4767883Mike Reed    if (ibounds.isEmpty()) {
164442e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed        return SkRect::MakeEmpty();
16458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1647d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    SkMatrix inverse;
1648d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    // if we can't invert the CTM, we can't return local clip bounds
16491f836ee096bb988adef4b9757b2629c7afeda36dreed    if (!fMCRec->fMatrix.invert(&inverse)) {
165042e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed        return SkRect::MakeEmpty();
1651d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    }
1652d9c0f0b57affec7a472879c5919acac6637d926areed@android.com
165342e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    SkRect bounds;
165442e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    SkRect r;
165542e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    // adjust it outwards in case we are antialiasing
165642e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    const int inset = 1;
1657fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com
165842e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
165942e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed           ibounds.fRight + inset, ibounds.fBottom + inset);
166042e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    inverse.mapRect(&bounds, r);
166142e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    return bounds;
16628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
166442e8c53b3ef58f887a623b410d9783b4d4ab4921Mike ReedSkIRect SkCanvas::onGetDeviceClipBounds() const {
1665a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    return fMCRec->fRasterClip.getBounds();
1666bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com}
1667bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
16688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const {
16691f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fMatrix;
16708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16721105224f9701e57ec5ce0354d6a380b664f5c638Brian OsmanGrRenderTargetContext* SkCanvas::internal_private_accessTopLayerRenderTargetContext() {
16739c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
16741105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman    return dev ? dev->accessRenderTargetContext() : nullptr;
16759c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
16769c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1677644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.orgGrContext* SkCanvas::getGrContext() {
1678644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
167986ae3d161412961c27a406465b0ec5749cc2e753reed    return device ? device->context() : nullptr;
1680644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org}
1681e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
1682ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1683ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                          const SkPaint& paint) {
16849881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()");
1685ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (outer.isEmpty()) {
1686ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1687ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1688ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (inner.isEmpty()) {
1689ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        this->drawRRect(outer, paint);
1690ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1691ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1692ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1693ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // We don't have this method (yet), but technically this is what we should
1694e0b728726d3b44bf18219b8c5bc5599332be7c34Cary Clark    // be able to return ...
1695e0b728726d3b44bf18219b8c5bc5599332be7c34Cary Clark    // if (!outer.contains(inner))) {
1696ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    //
1697ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // For now at least check for containment of bounds
1698e0b728726d3b44bf18219b8c5bc5599332be7c34Cary Clark    if (!outer.getBounds().contains(inner.getBounds())) {
1699e0b728726d3b44bf18219b8c5bc5599332be7c34Cary Clark        return;
1700e0b728726d3b44bf18219b8c5bc5599332be7c34Cary Clark    }
1701ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1702ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->onDrawDRRect(outer, inner, paint);
1703ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
1704ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
170541af966ab338e95eee81ab618ab28195075338f7reed// These need to stop being virtual -- clients need to override the onDraw... versions
170641af966ab338e95eee81ab618ab28195075338f7reed
170741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPaint(const SkPaint& paint) {
170841af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPaint(paint);
170941af966ab338e95eee81ab618ab28195075338f7reed}
171041af966ab338e95eee81ab618ab28195075338f7reed
171141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
17126e3ce40bd93e5de16b0086cb70320ff3283e72cfBrian Osman    // To avoid redundant logic in our culling code and various backends, we always sort rects
17136e3ce40bd93e5de16b0086cb70320ff3283e72cfBrian Osman    // before passing them along.
17146e3ce40bd93e5de16b0086cb70320ff3283e72cfBrian Osman    this->onDrawRect(r.makeSorted(), paint);
171541af966ab338e95eee81ab618ab28195075338f7reed}
171641af966ab338e95eee81ab618ab28195075338f7reed
1717dca352e2d42cfe698573947b3d11abc1eaade160msarettvoid SkCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
1718dca352e2d42cfe698573947b3d11abc1eaade160msarett    if (region.isEmpty()) {
1719dca352e2d42cfe698573947b3d11abc1eaade160msarett        return;
1720dca352e2d42cfe698573947b3d11abc1eaade160msarett    }
1721dca352e2d42cfe698573947b3d11abc1eaade160msarett
1722dca352e2d42cfe698573947b3d11abc1eaade160msarett    if (region.isRect()) {
1723dca352e2d42cfe698573947b3d11abc1eaade160msarett        return this->drawIRect(region.getBounds(), paint);
1724dca352e2d42cfe698573947b3d11abc1eaade160msarett    }
1725dca352e2d42cfe698573947b3d11abc1eaade160msarett
1726dca352e2d42cfe698573947b3d11abc1eaade160msarett    this->onDrawRegion(region, paint);
1727dca352e2d42cfe698573947b3d11abc1eaade160msarett}
1728dca352e2d42cfe698573947b3d11abc1eaade160msarett
172941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) {
17306e3ce40bd93e5de16b0086cb70320ff3283e72cfBrian Osman    // To avoid redundant logic in our culling code and various backends, we always sort rects
17316e3ce40bd93e5de16b0086cb70320ff3283e72cfBrian Osman    // before passing them along.
17326e3ce40bd93e5de16b0086cb70320ff3283e72cfBrian Osman    this->onDrawOval(r.makeSorted(), paint);
173341af966ab338e95eee81ab618ab28195075338f7reed}
173441af966ab338e95eee81ab618ab28195075338f7reed
173541af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
173641af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawRRect(rrect, paint);
173741af966ab338e95eee81ab618ab28195075338f7reed}
173841af966ab338e95eee81ab618ab28195075338f7reed
173941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
174041af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPoints(mode, count, pts, paint);
174141af966ab338e95eee81ab618ab28195075338f7reed}
174241af966ab338e95eee81ab618ab28195075338f7reed
1743e88a1cb20e6b4c9f099070112225a88693a4630bMike Reedvoid SkCanvas::drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode,
1744e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed                            const SkPaint& paint) {
1745e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    RETURN_ON_NULL(vertices);
1746e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    this->onDrawVerticesObject(vertices.get(), mode, paint);
1747e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed}
1748e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed
1749e88a1cb20e6b4c9f099070112225a88693a4630bMike Reedvoid SkCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) {
1750199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    RETURN_ON_NULL(vertices);
1751e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    this->onDrawVerticesObject(vertices, mode, paint);
175241af966ab338e95eee81ab618ab28195075338f7reed}
175341af966ab338e95eee81ab618ab28195075338f7reed
175441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
175541af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPath(path, paint);
175641af966ab338e95eee81ab618ab28195075338f7reed}
175741af966ab338e95eee81ab618ab28195075338f7reed
1758a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
1759e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
1760a85d4d0814818e4ddabb9237da209d61d6cd5854reed    this->onDrawImage(image, x, y, paint);
176141af966ab338e95eee81ab618ab28195075338f7reed}
176241af966ab338e95eee81ab618ab28195075338f7reed
1763e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
1764e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             const SkPaint* paint, SrcRectConstraint constraint) {
1765e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
1766e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (dst.isEmpty() || src.isEmpty()) {
1767e47829b6b1eeb6b0c97ccb3df3016d197046824creed        return;
1768e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
1769e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->onDrawImageRect(image, &src, dst, paint, constraint);
1770e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
177141af966ab338e95eee81ab618ab28195075338f7reed
177284984efeb64787b88c5f8bd6929cfe2d58a3ba06reedvoid SkCanvas::drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
177384984efeb64787b88c5f8bd6929cfe2d58a3ba06reed                             const SkPaint* paint, SrcRectConstraint constraint) {
1774e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
1775e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawImageRect(image, SkRect::Make(isrc), dst, paint, constraint);
177684984efeb64787b88c5f8bd6929cfe2d58a3ba06reed}
177784984efeb64787b88c5f8bd6929cfe2d58a3ba06reed
1778e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
1779e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             SrcRectConstraint constraint) {
1780e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
1781e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), dst, paint,
1782e47829b6b1eeb6b0c97ccb3df3016d197046824creed                        constraint);
1783e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1784e47829b6b1eeb6b0c97ccb3df3016d197046824creed
17854c21dc5ddf3b482293ed34eead876d8d61a662c3reedvoid SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
17864c21dc5ddf3b482293ed34eead876d8d61a662c3reed                             const SkPaint* paint) {
1787e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
17884c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (dst.isEmpty()) {
17894c21dc5ddf3b482293ed34eead876d8d61a662c3reed        return;
17904c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
1791552bca9afadd81d263041d04e2605d8d897940b6msarett    if (SkLatticeIter::Valid(image->width(), image->height(), center)) {
1792552bca9afadd81d263041d04e2605d8d897940b6msarett        this->onDrawImageNine(image, center, dst, paint);
1793552bca9afadd81d263041d04e2605d8d897940b6msarett    } else {
1794e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, dst, paint);
17954c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
17964c21dc5ddf3b482293ed34eead876d8d61a662c3reed}
17974c21dc5ddf3b482293ed34eead876d8d61a662c3reed
1798168820625c35a8c19f66c661efcbce7a5e334837msarettvoid SkCanvas::drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
1799168820625c35a8c19f66c661efcbce7a5e334837msarett                                const SkPaint* paint) {
1800168820625c35a8c19f66c661efcbce7a5e334837msarett    RETURN_ON_NULL(image);
1801168820625c35a8c19f66c661efcbce7a5e334837msarett    if (dst.isEmpty()) {
1802168820625c35a8c19f66c661efcbce7a5e334837msarett        return;
1803168820625c35a8c19f66c661efcbce7a5e334837msarett    }
180471df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett
180571df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    SkIRect bounds;
180671df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    Lattice latticePlusBounds = lattice;
180771df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    if (!latticePlusBounds.fBounds) {
180871df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        bounds = SkIRect::MakeWH(image->width(), image->height());
180971df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        latticePlusBounds.fBounds = &bounds;
181071df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    }
181171df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett
181271df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    if (SkLatticeIter::Valid(image->width(), image->height(), latticePlusBounds)) {
181371df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        this->onDrawImageLattice(image, latticePlusBounds, dst, paint);
1814168820625c35a8c19f66c661efcbce7a5e334837msarett    } else {
1815168820625c35a8c19f66c661efcbce7a5e334837msarett        this->drawImageRect(image, dst, paint);
1816168820625c35a8c19f66c661efcbce7a5e334837msarett    }
1817168820625c35a8c19f66c661efcbce7a5e334837msarett}
1818168820625c35a8c19f66c661efcbce7a5e334837msarett
181941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
18204c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing()) {
18212df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
18222df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
182341af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawBitmap(bitmap, dx, dy, paint);
182441af966ab338e95eee81ab618ab28195075338f7reed}
182541af966ab338e95eee81ab618ab28195075338f7reed
1826e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
1827a5517e2b190a8083b38964972b031c13e99f1012reed                              const SkPaint* paint, SrcRectConstraint constraint) {
1828e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (bitmap.drawsNothing() || dst.isEmpty() || src.isEmpty()) {
1829a5517e2b190a8083b38964972b031c13e99f1012reed        return;
1830a5517e2b190a8083b38964972b031c13e99f1012reed    }
1831e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->onDrawBitmapRect(bitmap, &src, dst, paint, constraint);
183241af966ab338e95eee81ab618ab28195075338f7reed}
183341af966ab338e95eee81ab618ab28195075338f7reed
183484984efeb64787b88c5f8bd6929cfe2d58a3ba06reedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
183584984efeb64787b88c5f8bd6929cfe2d58a3ba06reed                              const SkPaint* paint, SrcRectConstraint constraint) {
1836e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawBitmapRect(bitmap, SkRect::Make(isrc), dst, paint, constraint);
1837e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1838e47829b6b1eeb6b0c97ccb3df3016d197046824creed
1839e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
1840e47829b6b1eeb6b0c97ccb3df3016d197046824creed                              SrcRectConstraint constraint) {
1841e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, paint,
1842e47829b6b1eeb6b0c97ccb3df3016d197046824creed                         constraint);
184384984efeb64787b88c5f8bd6929cfe2d58a3ba06reed}
184484984efeb64787b88c5f8bd6929cfe2d58a3ba06reed
184541af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
184641af966ab338e95eee81ab618ab28195075338f7reed                              const SkPaint* paint) {
18474c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing() || dst.isEmpty()) {
18482df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
18492df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
1850552bca9afadd81d263041d04e2605d8d897940b6msarett    if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), center)) {
1851552bca9afadd81d263041d04e2605d8d897940b6msarett        this->onDrawBitmapNine(bitmap, center, dst, paint);
1852552bca9afadd81d263041d04e2605d8d897940b6msarett    } else {
1853a5517e2b190a8083b38964972b031c13e99f1012reed        this->drawBitmapRect(bitmap, dst, paint);
18544c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
185541af966ab338e95eee81ab618ab28195075338f7reed}
185641af966ab338e95eee81ab618ab28195075338f7reed
1857c573a40ed5024b463e47088d307e3164a486dba5msarettvoid SkCanvas::drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
1858c573a40ed5024b463e47088d307e3164a486dba5msarett                                 const SkPaint* paint) {
1859168820625c35a8c19f66c661efcbce7a5e334837msarett    if (bitmap.drawsNothing() || dst.isEmpty()) {
1860c573a40ed5024b463e47088d307e3164a486dba5msarett        return;
1861c573a40ed5024b463e47088d307e3164a486dba5msarett    }
186271df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett
186371df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    SkIRect bounds;
186471df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    Lattice latticePlusBounds = lattice;
186571df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    if (!latticePlusBounds.fBounds) {
186671df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        bounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
186771df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        latticePlusBounds.fBounds = &bounds;
186871df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    }
186971df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett
187071df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), latticePlusBounds)) {
187171df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        this->onDrawBitmapLattice(bitmap, latticePlusBounds, dst, paint);
1872552bca9afadd81d263041d04e2605d8d897940b6msarett    } else {
1873168820625c35a8c19f66c661efcbce7a5e334837msarett        this->drawBitmapRect(bitmap, dst, paint);
1874c573a40ed5024b463e47088d307e3164a486dba5msarett    }
1875c573a40ed5024b463e47088d307e3164a486dba5msarett}
1876c573a40ed5024b463e47088d307e3164a486dba5msarett
187771c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
18787d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                         const SkColor colors[], int count, SkBlendMode mode,
187971c3c760a83123ee0b3127b8c65c6394ce541c50reed                         const SkRect* cull, const SkPaint* paint) {
1880e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(atlas);
188171c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (count <= 0) {
188271c3c760a83123ee0b3127b8c65c6394ce541c50reed        return;
188371c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
1884c485907f0420e5f9cf8223e9ba53812cd8dd5368Joe Gregorio    SkASSERT(atlas);
188571c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(tex);
1886faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed    this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
188771c3c760a83123ee0b3127b8c65c6394ce541c50reed}
188871c3c760a83123ee0b3127b8c65c6394ce541c50reed
1889f70b531daaf47db1ee95c70da9843f1dd1f418d3reedvoid SkCanvas::drawAnnotation(const SkRect& rect, const char key[], SkData* value) {
1890f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    if (key) {
1891f70b531daaf47db1ee95c70da9843f1dd1f418d3reed        this->onDrawAnnotation(rect, key, value);
1892f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    }
1893f70b531daaf47db1ee95c70da9843f1dd1f418d3reed}
1894f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
1895e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1896e47829b6b1eeb6b0c97ccb3df3016d197046824creed                                    const SkPaint* paint, SrcRectConstraint constraint) {
1897e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (src) {
1898e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, *src, dst, paint, constraint);
1899e47829b6b1eeb6b0c97ccb3df3016d197046824creed    } else {
1900e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()),
1901e47829b6b1eeb6b0c97ccb3df3016d197046824creed                            dst, paint, constraint);
1902e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
1903e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1904e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1905e47829b6b1eeb6b0c97ccb3df3016d197046824creed                                     const SkPaint* paint, SrcRectConstraint constraint) {
1906e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (src) {
1907e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawBitmapRect(bitmap, *src, dst, paint, constraint);
1908e47829b6b1eeb6b0c97ccb3df3016d197046824creed    } else {
1909e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()),
1910e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             dst, paint, constraint);
1911e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
1912e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1913e47829b6b1eeb6b0c97ccb3df3016d197046824creed
19144204da25aa4c6e0b321314aa32fd9affb4865563Mike Reedvoid SkCanvas::private_draw_shadow_rec(const SkPath& path, const SkDrawShadowRec& rec) {
19154204da25aa4c6e0b321314aa32fd9affb4865563Mike Reed    this->onDrawShadowRec(path, rec);
19164204da25aa4c6e0b321314aa32fd9affb4865563Mike Reed}
19174204da25aa4c6e0b321314aa32fd9affb4865563Mike Reed
19184204da25aa4c6e0b321314aa32fd9affb4865563Mike Reedvoid SkCanvas::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
19194204da25aa4c6e0b321314aa32fd9affb4865563Mike Reed    SkPaint paint;
19204204da25aa4c6e0b321314aa32fd9affb4865563Mike Reed    const SkRect& pathBounds = path.getBounds();
19214204da25aa4c6e0b321314aa32fd9affb4865563Mike Reed
19224204da25aa4c6e0b321314aa32fd9affb4865563Mike Reed    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, &pathBounds)
19234204da25aa4c6e0b321314aa32fd9affb4865563Mike Reed    while (iter.next()) {
19244204da25aa4c6e0b321314aa32fd9affb4865563Mike Reed        iter.fDevice->drawShadow(path, rec);
19254204da25aa4c6e0b321314aa32fd9affb4865563Mike Reed    }
19264204da25aa4c6e0b321314aa32fd9affb4865563Mike Reed    LOOPER_END
19274204da25aa4c6e0b321314aa32fd9affb4865563Mike Reed}
19284204da25aa4c6e0b321314aa32fd9affb4865563Mike Reed
19298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
19308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  These are the virtual drawing methods
19318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
19328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
193328361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.orgvoid SkCanvas::onDiscard() {
193449f085dddff10473b6ebf832a974288300224e60bsalomon    if (fSurfaceBase) {
193528361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
193628361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    }
193728361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org}
193828361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org
193941af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPaint(const SkPaint& paint) {
19409881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()");
1941fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    this->internalDrawPaint(paint);
1942fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com}
1943fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
1944fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comvoid SkCanvas::internalDrawPaint(const SkPaint& paint) {
194596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, nullptr, false)
19468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
1948a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawPaint(looper.paint());
19498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19514e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
19528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
195441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
195541af966ab338e95eee81ab618ab28195075338f7reed                            const SkPaint& paint) {
19569881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count));
19578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if ((long)count <= 0) {
19588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
19598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1961822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    SkRect r;
196296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
1963a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com    if (paint.canComputeFastBounds()) {
1964a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        // special-case 2 points (common for drawing a single line)
1965a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        if (2 == count) {
1966a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            r.set(pts[0], pts[1]);
1967a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        } else {
1968a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org            r.set(pts, SkToInt(count));
1969a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
1970822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
197187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) {
197287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
197387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
197487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &r;
1975fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
1976a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com
197796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkASSERT(pts != nullptr);
19788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
197978cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
19804b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
19818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
1982a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawPoints(mode, count, pts, looper.paint());
19838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19844b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
19854e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
19868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19884a16717bc7aa471fad10ec3157774771a76e5106reedstatic bool needs_autodrawlooper(SkCanvas* canvas, const SkPaint& paint) {
19894a16717bc7aa471fad10ec3157774771a76e5106reed    return ((intptr_t)paint.getImageFilter()    |
19904a16717bc7aa471fad10ec3157774771a76e5106reed#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
19914a16717bc7aa471fad10ec3157774771a76e5106reed            (intptr_t)canvas->getDrawFilter()   |
19924a16717bc7aa471fad10ec3157774771a76e5106reed#endif
19934a16717bc7aa471fad10ec3157774771a76e5106reed            (intptr_t)paint.getLooper()         ) != 0;
19944a16717bc7aa471fad10ec3157774771a76e5106reed}
19954a16717bc7aa471fad10ec3157774771a76e5106reed
199641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
19979881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()");
19986e3ce40bd93e5de16b0086cb70320ff3283e72cfBrian Osman    SkASSERT(r.isSorted());
19998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.canComputeFastBounds()) {
2000822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
20016e3ce40bd93e5de16b0086cb70320ff3283e72cfBrian Osman        if (this->quickReject(paint.computeFastBounds(r, &storage))) {
200287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
200387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
20048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20054b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
20064a16717bc7aa471fad10ec3157774771a76e5106reed    if (needs_autodrawlooper(this, paint)) {
2007822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, &r, false)
20088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20094a16717bc7aa471fad10ec3157774771a76e5106reed        while (iter.next()) {
2010a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->drawRect(r, looper.paint());
20114a16717bc7aa471fad10ec3157774771a76e5106reed        }
20128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20134a16717bc7aa471fad10ec3157774771a76e5106reed        LOOPER_END
20144a16717bc7aa471fad10ec3157774771a76e5106reed    } else {
2015822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        this->predrawNotify(&r, &paint, false);
20164a16717bc7aa471fad10ec3157774771a76e5106reed        SkDrawIter iter(this);
20174a16717bc7aa471fad10ec3157774771a76e5106reed        while (iter.next()) {
2018a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->drawRect(r, paint);
20194a16717bc7aa471fad10ec3157774771a76e5106reed        }
20204a16717bc7aa471fad10ec3157774771a76e5106reed    }
20218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
202344df651ebefc284acc2f66425dff3ea0b0e14b36msarettvoid SkCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
202444df651ebefc284acc2f66425dff3ea0b0e14b36msarett    SkRect regionRect = SkRect::Make(region.getBounds());
202544df651ebefc284acc2f66425dff3ea0b0e14b36msarett    if (paint.canComputeFastBounds()) {
2026822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
202744df651ebefc284acc2f66425dff3ea0b0e14b36msarett        if (this->quickReject(paint.computeFastBounds(regionRect, &storage))) {
202844df651ebefc284acc2f66425dff3ea0b0e14b36msarett            return;
202944df651ebefc284acc2f66425dff3ea0b0e14b36msarett        }
203044df651ebefc284acc2f66425dff3ea0b0e14b36msarett    }
203144df651ebefc284acc2f66425dff3ea0b0e14b36msarett
2032822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, &regionRect)
203344df651ebefc284acc2f66425dff3ea0b0e14b36msarett
203444df651ebefc284acc2f66425dff3ea0b0e14b36msarett    while (iter.next()) {
2035a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawRegion(region, looper.paint());
203644df651ebefc284acc2f66425dff3ea0b0e14b36msarett    }
203744df651ebefc284acc2f66425dff3ea0b0e14b36msarett
203844df651ebefc284acc2f66425dff3ea0b0e14b36msarett    LOOPER_END
203944df651ebefc284acc2f66425dff3ea0b0e14b36msarett}
204044df651ebefc284acc2f66425dff3ea0b0e14b36msarett
204141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
20429881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()");
20436e3ce40bd93e5de16b0086cb70320ff3283e72cfBrian Osman    SkASSERT(oval.isSorted());
20444ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
2045822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
20466e3ce40bd93e5de16b0086cb70320ff3283e72cfBrian Osman        if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
204787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
204887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
20494ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
2050306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
2051822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
205246d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
205346d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    while (iter.next()) {
2054a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawOval(oval, looper.paint());
205546d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    }
205646d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
205746d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    LOOPER_END
20584ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
20594ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
2060ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomonvoid SkCanvas::onDrawArc(const SkRect& oval, SkScalar startAngle,
2061ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon                         SkScalar sweepAngle, bool useCenter,
2062ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon                         const SkPaint& paint) {
2063ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
20646e3ce40bd93e5de16b0086cb70320ff3283e72cfBrian Osman    SkASSERT(oval.isSorted());
2065ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    if (paint.canComputeFastBounds()) {
2066ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        SkRect storage;
2067ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        // Note we're using the entire oval as the bounds.
20686e3ce40bd93e5de16b0086cb70320ff3283e72cfBrian Osman        if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
2069ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon            return;
2070ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        }
2071ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    }
2072ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
2073822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
2074ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
2075ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    while (iter.next()) {
2076a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawArc(oval, startAngle, sweepAngle, useCenter, looper.paint());
2077ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    }
2078ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
2079ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    LOOPER_END
2080ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon}
2081ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
208241af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
20839881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()");
20844ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
2085822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
208687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) {
208787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
208887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
20894ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
20904ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
20914ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
20924ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
20934ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->SkCanvas::drawRect(rrect.getBounds(), paint);
2094f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
2095f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    } else if (rrect.isOval()) {
20964ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
2097f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        this->SkCanvas::drawOval(rrect.getBounds(), paint);
2098f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
20994ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
2100f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2101822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &rrect.getBounds())
2102f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2103f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    while (iter.next()) {
2104a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawRRect(rrect, looper.paint());
2105f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    }
2106f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2107f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    LOOPER_END
21084ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
21094ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
2110822128b475c1782788f96e7a1a848d0affb878b1Mike Reedvoid SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
2111ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (paint.canComputeFastBounds()) {
2112822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
211387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(outer.getBounds(), &storage))) {
211487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
211587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
2116ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
211725c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2118822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &outer.getBounds())
211925c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2120ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    while (iter.next()) {
2121a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawDRRect(outer, inner, looper.paint());
2122ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
212325c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2124ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_END
2125ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
21264ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
212741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
21289881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()");
21299364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    if (!path.isFinite()) {
21309364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com        return;
21319364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    }
21329364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com
2133822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    const SkRect& pathBounds = path.getBounds();
2134fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
2135822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
213687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(pathBounds, &storage))) {
213787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
213887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
21398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21400b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org
2141822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    if (pathBounds.width() <= 0 && pathBounds.height() <= 0) {
21426803c219dd3be4a73e7bb5c4bb8a5b1f803624d0commit-bot@chromium.org        if (path.isInverseFillType()) {
2143fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            this->internalDrawPaint(paint);
21446651a3238dd6affa4276ada42ab613abf1d42d1dcaryclark            return;
2145fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        }
2146fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
21478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2148822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, &pathBounds)
21498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
2151a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawPath(path, looper.paint());
21528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21544e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
21558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2157262a71b7f95ce98ff3dd8dba845afbd724470903reedbool SkCanvas::canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint& paint) {
2158262a71b7f95ce98ff3dd8dba845afbd724470903reed    if (!paint.getImageFilter()) {
2159262a71b7f95ce98ff3dd8dba845afbd724470903reed        return false;
2160262a71b7f95ce98ff3dd8dba845afbd724470903reed    }
2161262a71b7f95ce98ff3dd8dba845afbd724470903reed
2162262a71b7f95ce98ff3dd8dba845afbd724470903reed    const SkMatrix& ctm = this->getTotalMatrix();
2163c7e211acd0c9201688de7ff0c9a2271c67440adffmalita    if (!SkTreatAsSprite(ctm, SkISize::Make(w, h), paint)) {
2164262a71b7f95ce98ff3dd8dba845afbd724470903reed        return false;
2165262a71b7f95ce98ff3dd8dba845afbd724470903reed    }
2166262a71b7f95ce98ff3dd8dba845afbd724470903reed
2167262a71b7f95ce98ff3dd8dba845afbd724470903reed    // Currently we can only use the filterSprite code if we are clipped to the bitmap's bounds.
2168262a71b7f95ce98ff3dd8dba845afbd724470903reed    // Once we can filter and the filter will return a result larger than itself, we should be
2169262a71b7f95ce98ff3dd8dba845afbd724470903reed    // able to remove this constraint.
2170262a71b7f95ce98ff3dd8dba845afbd724470903reed    // skbug.com/4526
2171262a71b7f95ce98ff3dd8dba845afbd724470903reed    //
2172262a71b7f95ce98ff3dd8dba845afbd724470903reed    SkPoint pt;
2173262a71b7f95ce98ff3dd8dba845afbd724470903reed    ctm.mapXY(x, y, &pt);
2174262a71b7f95ce98ff3dd8dba845afbd724470903reed    SkIRect ir = SkIRect::MakeXYWH(SkScalarRoundToInt(pt.x()), SkScalarRoundToInt(pt.y()), w, h);
2175262a71b7f95ce98ff3dd8dba845afbd724470903reed    return ir.contains(fMCRec->fRasterClip.getBounds());
2176262a71b7f95ce98ff3dd8dba845afbd724470903reed}
2177262a71b7f95ce98ff3dd8dba845afbd724470903reed
2178a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
21799881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()");
2180a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkRect bounds = SkRect::MakeXYWH(x, y,
2181a85d4d0814818e4ddabb9237da209d61d6cd5854reed                                     SkIntToScalar(image->width()), SkIntToScalar(image->height()));
218296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
218387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        SkRect tmp = bounds;
218487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (paint) {
218587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            paint->computeFastBounds(tmp, &tmp);
218687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
218787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(tmp)) {
218887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
218987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
2190a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
21919d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2192a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
219396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
2194a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2195a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2196262a71b7f95ce98ff3dd8dba845afbd724470903reed
2197a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    sk_sp<SkSpecialImage> special;
2198129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    bool drawAsSprite = this->canDrawBitmapAsSprite(x, y, image->width(), image->height(),
2199129ed1cd6d792f3f6cf563aefa9756fc6308289dreed                                                    *paint);
2200129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    if (drawAsSprite && paint->getImageFilter()) {
2201a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        special = this->getDevice()->makeSpecial(image);
2202a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        if (!special) {
2203129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            drawAsSprite = false;
2204129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        }
2205129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    }
2206129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
2207262a71b7f95ce98ff3dd8dba845afbd724470903reed    LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
2208262a71b7f95ce98ff3dd8dba845afbd724470903reed
2209a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2210262a71b7f95ce98ff3dd8dba845afbd724470903reed        const SkPaint& pnt = looper.paint();
2211a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        if (special) {
2212a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed            SkPoint pt;
2213a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->ctm().mapXY(x, y, &pt);
2214a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->drawSpecial(special.get(),
2215a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed                                      SkScalarRoundToInt(pt.fX),
221653f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita                                      SkScalarRoundToInt(pt.fY), pnt,
221753f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita                                      nullptr, SkMatrix::I());
2218262a71b7f95ce98ff3dd8dba845afbd724470903reed        } else {
2219a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->drawImage(image, x, y, pnt);
2220262a71b7f95ce98ff3dd8dba845afbd724470903reed        }
2221a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
22229d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2223a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2224b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2225b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
222641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
2227562fe4767cc73e08a4e039362bc0336aea66ecfbreed                               const SkPaint* paint, SrcRectConstraint constraint) {
22289881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
222996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2230c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage = dst;
223187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (paint) {
223287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            paint->computeFastBounds(dst, &storage);
223387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
223487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(storage)) {
223587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
223687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
2237a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2238a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
223996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
2240a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2241a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
22429d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2243c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2244c83a29759a5c2966da5ab973e4fd90763e4c962breed                                          image->isOpaque())
22459d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2246a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2247a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawImageRect(image, src, dst, looper.paint(), constraint);
2248a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
22499d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2250a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2251b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2252b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
225341af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
22549881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()");
22558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
22568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
225733366974d43eae80e22284a2e445225c343859dareed    if (bitmap.drawsNothing()) {
225833366974d43eae80e22284a2e445225c343859dareed        return;
225933366974d43eae80e22284a2e445225c343859dareed    }
226033366974d43eae80e22284a2e445225c343859dareed
226133366974d43eae80e22284a2e445225c343859dareed    SkLazyPaint lazy;
226233366974d43eae80e22284a2e445225c343859dareed    if (nullptr == paint) {
226333366974d43eae80e22284a2e445225c343859dareed        paint = lazy.init();
226433366974d43eae80e22284a2e445225c343859dareed    }
226533366974d43eae80e22284a2e445225c343859dareed
2266822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    SkRect bounds;
2267822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    bitmap.getBounds(&bounds);
2268822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    bounds.offset(x, y);
2269822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    bool canFastBounds = paint->canComputeFastBounds();
2270822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    if (canFastBounds) {
2271822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
2272822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        if (this->quickReject(paint->computeFastBounds(bounds, &storage))) {
227387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
227487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
22758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22764b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2277a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    sk_sp<SkSpecialImage> special;
2278822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    bool drawAsSprite = canFastBounds && this->canDrawBitmapAsSprite(x, y, bitmap.width(),
2279822128b475c1782788f96e7a1a848d0affb878b1Mike Reed                                                                     bitmap.height(), *paint);
2280129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    if (drawAsSprite && paint->getImageFilter()) {
2281a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        special = this->getDevice()->makeSpecial(bitmap);
2282a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        if (!special) {
2283129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            drawAsSprite = false;
2284129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        }
2285129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    }
2286129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
2287822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
228833366974d43eae80e22284a2e445225c343859dareed
228933366974d43eae80e22284a2e445225c343859dareed    while (iter.next()) {
2290262a71b7f95ce98ff3dd8dba845afbd724470903reed        const SkPaint& pnt = looper.paint();
2291a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        if (special) {
2292262a71b7f95ce98ff3dd8dba845afbd724470903reed            SkPoint pt;
2293a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->ctm().mapXY(x, y, &pt);
2294a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->drawSpecial(special.get(),
2295a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed                                      SkScalarRoundToInt(pt.fX),
229653f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita                                      SkScalarRoundToInt(pt.fY), pnt,
229753f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita                                      nullptr, SkMatrix::I());
2298262a71b7f95ce98ff3dd8dba845afbd724470903reed        } else {
2299b964238f0bded00bae59c26c5f366a7780a0ef5fHal Canary            iter.fDevice->drawBitmap(bitmap, x, y, looper.paint());
2300262a71b7f95ce98ff3dd8dba845afbd724470903reed        }
230133366974d43eae80e22284a2e445225c343859dareed    }
2302fbfa25802709139c2f14e304319c9541da65ca27msarett
230333366974d43eae80e22284a2e445225c343859dareed    LOOPER_END
23048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23069987ec3791336bad6af5cbe513564786b2df55aareed@google.com// this one is non-virtual, so it can be called safely by other canvas apis
23077112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2308eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      const SkRect& dst, const SkPaint* paint,
2309a5517e2b190a8083b38964972b031c13e99f1012reed                                      SrcRectConstraint constraint) {
231050b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing() || dst.isEmpty()) {
23118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
23128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
231374b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
231496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2315c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage;
231687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
231787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
231887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
23198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23203d60812865bb034851da777a91413ab584929887reed@google.com
232133535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    SkLazyPaint lazy;
232296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
232333535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com        paint = lazy.init();
23248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23257064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
2326c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2327c83a29759a5c2966da5ab973e4fd90763e4c962breed                                          bitmap.isOpaque())
23287064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
232933535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    while (iter.next()) {
2330a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawBitmapRect(bitmap, src, dst, looper.paint(), constraint);
2331f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
23327064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
233333535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    LOOPER_END
23348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
233641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
2337562fe4767cc73e08a4e039362bc0336aea66ecfbreed                                const SkPaint* paint, SrcRectConstraint constraint) {
23389881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()");
23399987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
2340562fe4767cc73e08a4e039362bc0336aea66ecfbreed    this->internalDrawBitmapRect(bitmap, src, dst, paint, constraint);
23419987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
23429987ec3791336bad6af5cbe513564786b2df55aareed@google.com
23434c21dc5ddf3b482293ed34eead876d8d61a662c3reedvoid SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
23444c21dc5ddf3b482293ed34eead876d8d61a662c3reed                               const SkPaint* paint) {
23454c21dc5ddf3b482293ed34eead876d8d61a662c3reed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageNine()");
23469d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
234796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2348c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage;
234987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
235087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
235187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
23523d60812865bb034851da777a91413ab584929887reed@google.com    }
23539d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
23544c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkLazyPaint lazy;
235596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
23564c21dc5ddf3b482293ed34eead876d8d61a662c3reed        paint = lazy.init();
23574c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
23589d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2359c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
23609d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
23614c21dc5ddf3b482293ed34eead876d8d61a662c3reed    while (iter.next()) {
2362a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawImageNine(image, center, dst, looper.paint());
23639987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
23649d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
23654c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_END
23669987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
23679987ec3791336bad6af5cbe513564786b2df55aareed@google.com
236841af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
236941af966ab338e95eee81ab618ab28195075338f7reed                                const SkPaint* paint) {
23709881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()");
23719987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
23729987ec3791336bad6af5cbe513564786b2df55aareed@google.com
237396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2374c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage;
237587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
237687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
237787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
23784c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
23799d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
23804c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkLazyPaint lazy;
238196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
23824c21dc5ddf3b482293ed34eead876d8d61a662c3reed        paint = lazy.init();
23834c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
23849d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2385c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
23869d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
23874c21dc5ddf3b482293ed34eead876d8d61a662c3reed    while (iter.next()) {
2388a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawBitmapNine(bitmap, center, dst, looper.paint());
23894c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
23909d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
23914c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_END
23929987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
23939987ec3791336bad6af5cbe513564786b2df55aareed@google.com
2394168820625c35a8c19f66c661efcbce7a5e334837msarettvoid SkCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
2395168820625c35a8c19f66c661efcbce7a5e334837msarett                                  const SkPaint* paint) {
2396168820625c35a8c19f66c661efcbce7a5e334837msarett    if (nullptr == paint || paint->canComputeFastBounds()) {
2397168820625c35a8c19f66c661efcbce7a5e334837msarett        SkRect storage;
2398168820625c35a8c19f66c661efcbce7a5e334837msarett        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2399168820625c35a8c19f66c661efcbce7a5e334837msarett            return;
2400168820625c35a8c19f66c661efcbce7a5e334837msarett        }
2401168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2402168820625c35a8c19f66c661efcbce7a5e334837msarett
2403168820625c35a8c19f66c661efcbce7a5e334837msarett    SkLazyPaint lazy;
2404168820625c35a8c19f66c661efcbce7a5e334837msarett    if (nullptr == paint) {
2405168820625c35a8c19f66c661efcbce7a5e334837msarett        paint = lazy.init();
2406168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2407168820625c35a8c19f66c661efcbce7a5e334837msarett
2408168820625c35a8c19f66c661efcbce7a5e334837msarett    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2409168820625c35a8c19f66c661efcbce7a5e334837msarett
2410168820625c35a8c19f66c661efcbce7a5e334837msarett    while (iter.next()) {
2411a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawImageLattice(image, lattice, dst, looper.paint());
2412168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2413168820625c35a8c19f66c661efcbce7a5e334837msarett
2414168820625c35a8c19f66c661efcbce7a5e334837msarett    LOOPER_END
2415168820625c35a8c19f66c661efcbce7a5e334837msarett}
2416168820625c35a8c19f66c661efcbce7a5e334837msarett
2417168820625c35a8c19f66c661efcbce7a5e334837msarettvoid SkCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
2418168820625c35a8c19f66c661efcbce7a5e334837msarett                                   const SkRect& dst, const SkPaint* paint) {
2419168820625c35a8c19f66c661efcbce7a5e334837msarett    if (nullptr == paint || paint->canComputeFastBounds()) {
2420168820625c35a8c19f66c661efcbce7a5e334837msarett        SkRect storage;
2421168820625c35a8c19f66c661efcbce7a5e334837msarett        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2422168820625c35a8c19f66c661efcbce7a5e334837msarett            return;
2423168820625c35a8c19f66c661efcbce7a5e334837msarett        }
2424168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2425168820625c35a8c19f66c661efcbce7a5e334837msarett
2426168820625c35a8c19f66c661efcbce7a5e334837msarett    SkLazyPaint lazy;
2427168820625c35a8c19f66c661efcbce7a5e334837msarett    if (nullptr == paint) {
2428168820625c35a8c19f66c661efcbce7a5e334837msarett        paint = lazy.init();
2429168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2430168820625c35a8c19f66c661efcbce7a5e334837msarett
2431168820625c35a8c19f66c661efcbce7a5e334837msarett    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2432168820625c35a8c19f66c661efcbce7a5e334837msarett
2433168820625c35a8c19f66c661efcbce7a5e334837msarett    while (iter.next()) {
2434a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawBitmapLattice(bitmap, lattice, dst, looper.paint());
2435168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2436168820625c35a8c19f66c661efcbce7a5e334837msarett
2437168820625c35a8c19f66c661efcbce7a5e334837msarett    LOOPER_END
2438168820625c35a8c19f66c661efcbce7a5e334837msarett}
2439168820625c35a8c19f66c661efcbce7a5e334837msarett
2440f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comclass SkDeviceFilteredPaint {
2441f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.compublic:
24421f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2443112e7e277702e104357f2d44742253ee1b0109acfmalita        uint32_t filteredFlags = device->filterTextFlags(paint);
2444112e7e277702e104357f2d44742253ee1b0109acfmalita        if (filteredFlags != paint.getFlags()) {
2445a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com            SkPaint* newPaint = fLazy.set(paint);
2446112e7e277702e104357f2d44742253ee1b0109acfmalita            newPaint->setFlags(filteredFlags);
2447f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = newPaint;
2448f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        } else {
2449f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = &paint;
2450f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        }
2451f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    }
2452f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2453f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    const SkPaint& paint() const { return *fPaint; }
2454f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2455f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comprivate:
24562c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
24572c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint     fLazy;
2458f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com};
2459f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2460e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2461e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                          const SkPaint& paint) {
246296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
24638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24654e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2466a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawText(text, byteLength, x, y, dfp.paint());
24678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24694e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
24708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2472e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2473e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                             const SkPaint& paint) {
247405c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, 0);
247505c4a4322e7d4f3417b7df33825bab8603d52051fmalita
247696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
247787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
24788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24794e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2480a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawPosText(text, byteLength, &pos->fX, 2, textOffset,
2481f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
24828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2483b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
24844e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
24858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2487e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2488e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              SkScalar constY, const SkPaint& paint) {
248905c4a4322e7d4f3417b7df33825bab8603d52051fmalita
249005c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, constY);
249105c4a4322e7d4f3417b7df33825bab8603d52051fmalita
249296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
249387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
24948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24954e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2496a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawPosText(text, byteLength, xpos, 1, textOffset,
2497f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
24988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2499b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
25004e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
25018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2503e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2504e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                const SkMatrix* matrix, const SkPaint& paint) {
250596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
250687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
25078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
2508a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawTextOnPath(text, byteLength, path,
25094e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                     matrix, looper.paint());
25108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2511b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
2512945ec3a2bec668ca845071a65df8ec55e8f43819commit-bot@chromium.org    LOOPER_END
25134325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org}
25144325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org
251545561a0b15fe045ba272c328684c3f7ae290785areedvoid SkCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
251645561a0b15fe045ba272c328684c3f7ae290785areed                                 const SkRect* cullRect, const SkPaint& paint) {
251745561a0b15fe045ba272c328684c3f7ae290785areed    if (cullRect && this->quickReject(*cullRect)) {
251845561a0b15fe045ba272c328684c3f7ae290785areed        return;
251945561a0b15fe045ba272c328684c3f7ae290785areed    }
252045561a0b15fe045ba272c328684c3f7ae290785areed
252145561a0b15fe045ba272c328684c3f7ae290785areed    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
252245561a0b15fe045ba272c328684c3f7ae290785areed
252345561a0b15fe045ba272c328684c3f7ae290785areed    while (iter.next()) {
2524a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawTextRSXform(text, byteLength, xform, looper.paint());
252545561a0b15fe045ba272c328684c3f7ae290785areed    }
252645561a0b15fe045ba272c328684c3f7ae290785areed
252745561a0b15fe045ba272c328684c3f7ae290785areed    LOOPER_END
252845561a0b15fe045ba272c328684c3f7ae290785areed}
252945561a0b15fe045ba272c328684c3f7ae290785areed
253000d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
253100d5c2c6523321d25b32905ff4822f083a4173eefmalita                              const SkPaint& paint) {
25327ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
253385d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    SkRect storage;
253496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
253519653d1d004610b4ba07ce563a5701164e120e45fmalita    if (paint.canComputeFastBounds()) {
253685d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita        storage = blob->bounds().makeOffset(x, y);
253787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        SkRect tmp;
253887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(storage, &tmp))) {
253987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
254087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
254187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &storage;
25427ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita    }
25437ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
2544024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // We cannot filter in the looper as we normally do, because the paint is
2545024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // incomplete at this point (text-related attributes are embedded within blob run paints).
2546024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    SkDrawFilter* drawFilter = fMCRec->fFilter;
254796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fMCRec->fFilter = nullptr;
2548024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
254985d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds)
255000d5c2c6523321d25b32905ff4822f083a4173eefmalita
2551aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    while (iter.next()) {
2552aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2553a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawTextBlob(blob, x, y, dfp.paint(), drawFilter);
255400d5c2c6523321d25b32905ff4822f083a4173eefmalita    }
255500d5c2c6523321d25b32905ff4822f083a4173eefmalita
2556aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    LOOPER_END
2557024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
2558024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    fMCRec->fFilter = drawFilter;
255900d5c2c6523321d25b32905ff4822f083a4173eefmalita}
256000d5c2c6523321d25b32905ff4822f083a4173eefmalita
25612a475eae622adc1e8fa29206be1eaf862c23548eCary Clarkvoid SkCanvas::drawString(const SkString& string, SkScalar x, SkScalar y, const SkPaint& paint) {
25622a475eae622adc1e8fa29206be1eaf862c23548eCary Clark    this->drawText(string.c_str(), string.size(), x, y, paint);
25632a475eae622adc1e8fa29206be1eaf862c23548eCary Clark}
25642a475eae622adc1e8fa29206be1eaf862c23548eCary Clark
2565e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com// These will become non-virtual, so they always call the (virtual) onDraw... method
2566e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2567e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                        const SkPaint& paint) {
25689881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()");
2569ac09554dce518e9d4496771f648f3ae17eca857creed    if (byteLength) {
2570ac09554dce518e9d4496771f648f3ae17eca857creed        this->onDrawText(text, byteLength, x, y, paint);
2571ac09554dce518e9d4496771f648f3ae17eca857creed    }
2572e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2573e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2574e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                           const SkPaint& paint) {
25759881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()");
2576ac09554dce518e9d4496771f648f3ae17eca857creed    if (byteLength) {
2577ac09554dce518e9d4496771f648f3ae17eca857creed        this->onDrawPosText(text, byteLength, pos, paint);
2578ac09554dce518e9d4496771f648f3ae17eca857creed    }
2579e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2580e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2581e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                            SkScalar constY, const SkPaint& paint) {
25829881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()");
2583ac09554dce518e9d4496771f648f3ae17eca857creed    if (byteLength) {
2584ac09554dce518e9d4496771f648f3ae17eca857creed        this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2585ac09554dce518e9d4496771f648f3ae17eca857creed    }
2586e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2587e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2588e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              const SkMatrix* matrix, const SkPaint& paint) {
25899881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()");
2590ac09554dce518e9d4496771f648f3ae17eca857creed    if (byteLength) {
2591ac09554dce518e9d4496771f648f3ae17eca857creed        this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2592ac09554dce518e9d4496771f648f3ae17eca857creed    }
2593e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
259445561a0b15fe045ba272c328684c3f7ae290785areedvoid SkCanvas::drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
259545561a0b15fe045ba272c328684c3f7ae290785areed                               const SkRect* cullRect, const SkPaint& paint) {
259645561a0b15fe045ba272c328684c3f7ae290785areed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextRSXform()");
259745561a0b15fe045ba272c328684c3f7ae290785areed    if (byteLength) {
259845561a0b15fe045ba272c328684c3f7ae290785areed        this->onDrawTextRSXform(text, byteLength, xform, cullRect, paint);
259945561a0b15fe045ba272c328684c3f7ae290785areed    }
260045561a0b15fe045ba272c328684c3f7ae290785areed}
260100d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
260200d5c2c6523321d25b32905ff4822f083a4173eefmalita                            const SkPaint& paint) {
2603e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(blob);
26049881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()");
2605e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    this->onDrawTextBlob(blob, x, y, paint);
260600d5c2c6523321d25b32905ff4822f083a4173eefmalita}
2607e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com
2608e88a1cb20e6b4c9f099070112225a88693a4630bMike Reedvoid SkCanvas::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode,
2609e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed                                    const SkPaint& paint) {
2610199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
2611199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
2612199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon
2613199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    while (iter.next()) {
2614199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon        // In the common case of one iteration we could std::move vertices here.
26152f6b5a47a50cdd218bc3302273be3a4a71add8fbMike Reed        iter.fDevice->drawVertices(vertices, bmode, looper.paint());
2616199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    }
2617199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon
2618199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    LOOPER_END
2619199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon}
2620199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon
2621b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
26227d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                         const SkPoint texCoords[4], SkBlendMode bmode,
26237d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                         const SkPaint& paint) {
26249881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()");
262596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == cubics) {
2626b3c9d1c33caf325aada244204215eb790c228c12dandov        return;
2627b3c9d1c33caf325aada244204215eb790c228c12dandov    }
26286cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2629faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed    this->onDrawPatch(cubics, colors, texCoords, bmode, paint);
26309340c2685c0bb0e1e70008acaaf3d1448f074c38msarett}
26319340c2685c0bb0e1e70008acaaf3d1448f074c38msarett
26329340c2685c0bb0e1e70008acaaf3d1448f074c38msarettvoid SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2633faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed                           const SkPoint texCoords[4], SkBlendMode bmode,
26347d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                           const SkPaint& paint) {
2635ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // Since a patch is always within the convex hull of the control points, we discard it when its
2636ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // bounding rectangle is completely outside the current clip.
2637ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    SkRect bounds;
2638b3c9d1c33caf325aada244204215eb790c228c12dandov    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2639ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    if (this->quickReject(bounds)) {
2640ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov        return;
2641ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
26426cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2643435071e8ab865e395bec34ef128a412ceb50f063Mike Reed    const bool interpColorsLinearly = (this->imageInfo().colorSpace() != nullptr);
2644435071e8ab865e395bec34ef128a412ceb50f063Mike Reed
264596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
26466cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2647ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    while (iter.next()) {
2648435071e8ab865e395bec34ef128a412ceb50f063Mike Reed        iter.fDevice->drawPatch(cubics, colors, texCoords, bmode, interpColorsLinearly, paint);
2649ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
26506cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2651ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    LOOPER_END
2652ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov}
2653ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov
2654a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) {
2655e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(dr);
2656e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (x || y) {
2657e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        SkMatrix matrix = SkMatrix::MakeTrans(x, y);
2658e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        this->onDrawDrawable(dr, &matrix);
2659e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    } else {
2660e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        this->onDrawDrawable(dr, nullptr);
2661a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    }
2662a8db72864a43ad1fbba3c2892cf5cd88060a43efreed}
2663a8db72864a43ad1fbba3c2892cf5cd88060a43efreed
2664a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2665e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(dr);
2666e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (matrix && matrix->isIdentity()) {
2667e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        matrix = nullptr;
26686a070dc06af4e9f305f9d08a69e34d18ade473cbreed    }
2669e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    this->onDrawDrawable(dr, matrix);
26706a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
26716a070dc06af4e9f305f9d08a69e34d18ade473cbreed
2672a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
26732a62e853c27cfacafd5c15ac1077cc13140589bareed    // drawable bounds are no longer reliable (e.g. android displaylist)
26742a62e853c27cfacafd5c15ac1077cc13140589bareed    // so don't use them for quick-reject
2675a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    dr->draw(this, matrix);
26766a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
26776a070dc06af4e9f305f9d08a69e34d18ade473cbreed
267871c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
2679faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed                           const SkColor colors[], int count, SkBlendMode bmode,
268071c3c760a83123ee0b3127b8c65c6394ce541c50reed                           const SkRect* cull, const SkPaint* paint) {
268171c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (cull && this->quickReject(*cull)) {
268271c3c760a83123ee0b3127b8c65c6394ce541c50reed        return;
268371c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
268471c3c760a83123ee0b3127b8c65c6394ce541c50reed
268571c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkPaint pnt;
268671c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (paint) {
268771c3c760a83123ee0b3127b8c65c6394ce541c50reed        pnt = *paint;
268871c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
26899d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
269096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr)
269171c3c760a83123ee0b3127b8c65c6394ce541c50reed    while (iter.next()) {
2692a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawAtlas(atlas, xform, tex, colors, count, bmode, pnt);
269371c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
269471c3c760a83123ee0b3127b8c65c6394ce541c50reed    LOOPER_END
269571c3c760a83123ee0b3127b8c65c6394ce541c50reed}
269671c3c760a83123ee0b3127b8c65c6394ce541c50reed
2697f70b531daaf47db1ee95c70da9843f1dd1f418d3reedvoid SkCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
2698f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    SkASSERT(key);
2699f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
2700f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    SkPaint paint;
2701f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, nullptr)
2702f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    while (iter.next()) {
2703a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawAnnotation(rect, key, value);
2704f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    }
2705f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    LOOPER_END
2706f70b531daaf47db1ee95c70da9843f1dd1f418d3reed}
2707f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
27088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
27098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual
27108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves.
27118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
27128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2713374772bd61951f01bf84fe17bf53d8867681c9aereedvoid SkCanvas::drawColor(SkColor c, SkBlendMode mode) {
27149881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()");
27158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
27168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(c);
2718374772bd61951f01bf84fe17bf53d8867681c9aereed    paint.setBlendMode(mode);
27198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
27208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
27239881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)");
27243661bc997620899695041010a750d11dbe8a972dMike Reed    const SkPoint pt = { x, y };
27258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
27268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27283661bc997620899695041010a750d11dbe8a972dMike Reedvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint) {
27299881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()");
27308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pts[2];
27314b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
27328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[0].set(x0, y0);
27338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[1].set(x1, y1);
27348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kLines_PointMode, 2, pts, paint);
27358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27373661bc997620899695041010a750d11dbe8a972dMike Reedvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint) {
27389881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()");
27398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (radius < 0) {
27408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        radius = 0;
27418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
27428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
27448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
27454ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    this->drawOval(r, paint);
27468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
27498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const SkPaint& paint) {
27509881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()");
27518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rx > 0 && ry > 0) {
27524ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        SkRRect rrect;
27534ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        rrect.setRectXY(r, rx, ry);
27544ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->drawRRect(rrect, paint);
27558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
27568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawRect(r, paint);
27578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
27588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
27618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       SkScalar sweepAngle, bool useCenter,
27628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       const SkPaint& paint) {
27639881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
276421af9ca1b1f54d9ba1de055aa8475928d5c8ecdfbsalomon    if (oval.isEmpty() || !sweepAngle) {
276521af9ca1b1f54d9ba1de055aa8475928d5c8ecdfbsalomon        return;
27668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
276721af9ca1b1f54d9ba1de055aa8475928d5c8ecdfbsalomon    this->onDrawArc(oval, startAngle, sweepAngle, useCenter, paint);
27688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
27718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPath& path, SkScalar hOffset,
27728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                SkScalar vOffset, const SkPaint& paint) {
27739881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()");
27748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix    matrix;
27754b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
27768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(hOffset, vOffset);
27778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
27788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2780f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com///////////////////////////////////////////////////////////////////////////////
27811c2c441fede0ae9573afc098017011e3439624a9reed
27821c2c441fede0ae9573afc098017011e3439624a9reed/**
27831c2c441fede0ae9573afc098017011e3439624a9reed *  This constant is trying to balance the speed of ref'ing a subpicture into a parent picture,
27841c2c441fede0ae9573afc098017011e3439624a9reed *  against the playback cost of recursing into the subpicture to get at its actual ops.
27851c2c441fede0ae9573afc098017011e3439624a9reed *
27861c2c441fede0ae9573afc098017011e3439624a9reed *  For now we pick a conservatively small value, though measurement (and other heuristics like
27871c2c441fede0ae9573afc098017011e3439624a9reed *  the type of ops contained) may justify changing this value.
27881c2c441fede0ae9573afc098017011e3439624a9reed */
27891c2c441fede0ae9573afc098017011e3439624a9reed#define kMaxPictureOpsToUnrollInsteadOfRef  1
27909b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2791d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
2792e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(picture);
2793e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed
27941c2c441fede0ae9573afc098017011e3439624a9reed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()");
2795e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (matrix && matrix->isIdentity()) {
2796e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        matrix = nullptr;
2797e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    }
2798e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) {
2799e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2800e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        picture->playback(this);
2801e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    } else {
2802e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        this->onDrawPicture(picture, matrix, paint);
2803d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
2804d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
28059b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2806d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2807d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed                             const SkPaint* paint) {
2808d028180f0310cf2b23f9744256a41697b0683e67fmalita    if (!paint || paint->canComputeFastBounds()) {
2809d028180f0310cf2b23f9744256a41697b0683e67fmalita        SkRect bounds = picture->cullRect();
2810d028180f0310cf2b23f9744256a41697b0683e67fmalita        if (paint) {
2811d028180f0310cf2b23f9744256a41697b0683e67fmalita            paint->computeFastBounds(bounds, &bounds);
2812d028180f0310cf2b23f9744256a41697b0683e67fmalita        }
2813d028180f0310cf2b23f9744256a41697b0683e67fmalita        if (matrix) {
2814d028180f0310cf2b23f9744256a41697b0683e67fmalita            matrix->mapRect(&bounds);
2815d028180f0310cf2b23f9744256a41697b0683e67fmalita        }
2816d028180f0310cf2b23f9744256a41697b0683e67fmalita        if (this->quickReject(bounds)) {
2817d028180f0310cf2b23f9744256a41697b0683e67fmalita            return;
2818d028180f0310cf2b23f9744256a41697b0683e67fmalita        }
2819d028180f0310cf2b23f9744256a41697b0683e67fmalita    }
2820d028180f0310cf2b23f9744256a41697b0683e67fmalita
2821a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2822c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips    picture->playback(this);
28238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
28268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
28278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28283aafe111b6cc388400092851cc53bbbdfcb8a81creedSkCanvas::LayerIter::LayerIter(SkCanvas* canvas) {
282999fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert(sizeof(fStorage) >= sizeof(SkDrawIter), "fStorage_too_small");
28308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(canvas);
28328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28333aafe111b6cc388400092851cc53bbbdfcb8a81creed    fImpl = new (fStorage) SkDrawIter(canvas);
28348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
28358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() {
28388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl->~SkDrawIter();
28398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() {
28428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
28438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28451f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::LayerIter::device() const {
284699330ba6227137866a0dbd63478d36f335203ebdMike Reed    return fImpl->fDevice;
28478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const {
2850a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    return fImpl->fDevice->ctm();
28518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const {
28548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* paint = fImpl->getPaint();
285596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
28568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &fDefaultPaint;
28578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
28588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *paint;
28598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2861a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedvoid SkCanvas::LayerIter::clip(SkRegion* rgn) const {
2862a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    return fImpl->fDevice->onAsRgnClip(rgn);
2863a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed}
2864a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
28658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); }
28668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); }
286720a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
286820a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com///////////////////////////////////////////////////////////////////////////////
286920a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
28703107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.orgstatic bool supported_for_raster_canvas(const SkImageInfo& info) {
28713107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.alphaType()) {
28723107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kPremul_SkAlphaType:
28733107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kOpaque_SkAlphaType:
28743107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
28753107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
28763107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
28773107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
28783107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
28793107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.colorType()) {
28803107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kAlpha_8_SkColorType:
28813107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kRGB_565_SkColorType:
288228fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:
28839e3dbdff53f2d9957626a17a279730cda70f17bajunov        case kRGBA_F16_SkColorType:
28843107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
28853107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
28863107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
28873107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
28883107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
28893107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    return true;
28903107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org}
28913107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
28925df4934b3e40cdc378e225d1dda39f015cae9baeMike Reedstd::unique_ptr<SkCanvas> SkCanvas::MakeRasterDirect(const SkImageInfo& info, void* pixels,
28935df4934b3e40cdc378e225d1dda39f015cae9baeMike Reed                                                     size_t rowBytes) {
289442b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!supported_for_raster_canvas(info)) {
289596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
289642b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
2897eb849e5fd10cbe00cbc31307ba97fd9efca0b41bskia.committer@gmail.com
289842b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    SkBitmap bitmap;
289942b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!bitmap.installPixels(info, pixels, rowBytes)) {
290096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
290142b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
29025df4934b3e40cdc378e225d1dda39f015cae9baeMike Reed    return skstd::make_unique<SkCanvas>(bitmap);
290342b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org}
2904d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2905d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed///////////////////////////////////////////////////////////////////////////////
2906d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2907d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
2908a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                                                 const SkPaint* paint, const SkRect& bounds)
2909d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    : fCanvas(canvas)
2910d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    , fSaveCount(canvas->getSaveCount())
2911d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed{
291249f085dddff10473b6ebf832a974288300224e60bsalomon    if (paint) {
2913a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        SkRect newBounds = bounds;
2914d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (matrix) {
2915a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips            matrix->mapRect(&newBounds);
2916d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        }
2917a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        canvas->saveLayer(&newBounds, paint);
291849f085dddff10473b6ebf832a974288300224e60bsalomon    } else if (matrix) {
2919d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->save();
2920d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
29216cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
292249f085dddff10473b6ebf832a974288300224e60bsalomon    if (matrix) {
2923d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->concat(*matrix);
2924d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
2925d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
2926d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2927d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
2928d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    fCanvas->restoreToCount(fSaveCount);
2929d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
2930e8f3062a36d3682f4019309a32b5b84dc9eddf8creed
2931ee424acbb87bf999be132a437527e656e37541d7Florin Malita///////////////////////////////////////////////////////////////////////////////
2932ee424acbb87bf999be132a437527e656e37541d7Florin Malita
2933ee424acbb87bf999be132a437527e656e37541d7Florin MalitaSkNoDrawCanvas::SkNoDrawCanvas(int width, int height)
2934ee424acbb87bf999be132a437527e656e37541d7Florin Malita    : INHERITED(SkIRect::MakeWH(width, height), kConservativeRasterClip_InitFlag) {}
2935ee424acbb87bf999be132a437527e656e37541d7Florin Malita
2936439ace939b6aaa58408ece0e9e89b633353571aeFlorin MalitaSkNoDrawCanvas::SkNoDrawCanvas(const SkIRect& bounds)
2937439ace939b6aaa58408ece0e9e89b633353571aeFlorin Malita    : INHERITED(bounds, kConservativeRasterClip_InitFlag) {}
2938439ace939b6aaa58408ece0e9e89b633353571aeFlorin Malita
2939ee424acbb87bf999be132a437527e656e37541d7Florin MalitaSkCanvas::SaveLayerStrategy SkNoDrawCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
2940ee424acbb87bf999be132a437527e656e37541d7Florin Malita    (void)this->INHERITED::getSaveLayerStrategy(rec);
2941ee424acbb87bf999be132a437527e656e37541d7Florin Malita    return kNoLayer_SaveLayerStrategy;
2942ee424acbb87bf999be132a437527e656e37541d7Florin Malita}
2943ee424acbb87bf999be132a437527e656e37541d7Florin Malita
2944ee424acbb87bf999be132a437527e656e37541d7Florin Malita///////////////////////////////////////////////////////////////////////////////
294573603f3c52ffd89fe9d035be827b566a0e7d3b79reed
294673603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kDifference_Op         == (int)kDifference_SkClipOp, "");
294773603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kIntersect_Op          == (int)kIntersect_SkClipOp, "");
294873603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kUnion_Op              == (int)kUnion_SkClipOp, "");
294973603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kXOR_Op                == (int)kXOR_SkClipOp, "");
295073603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kReverseDifference_Op  == (int)kReverseDifference_SkClipOp, "");
295173603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kReplace_Op            == (int)kReplace_SkClipOp, "");
2952356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
2953356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed///////////////////////////////////////////////////////////////////////////////////////////////////
2954356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
2955356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedSkRasterHandleAllocator::Handle SkCanvas::accessTopRasterHandle() const {
2956356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    if (fAllocator && fMCRec->fTopLayer->fDevice) {
2957713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita        const auto& dev = fMCRec->fTopLayer->fDevice;
2958356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        SkRasterHandleAllocator::Handle handle = dev->getRasterHandle();
2959356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        SkIPoint origin = dev->getOrigin();
2960356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        SkMatrix ctm = this->getTotalMatrix();
2961356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        ctm.preTranslate(SkIntToScalar(-origin.x()), SkIntToScalar(-origin.y()));
2962356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
2963356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        SkIRect clip = fMCRec->fRasterClip.getBounds();
2964356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        clip.offset(-origin.x(), -origin.y());
2965108f55ed5d0b63baf653e4e443cc469df887c811Mike Reed        if (!clip.intersect(0, 0, dev->width(), dev->height())) {
2966356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed            clip.setEmpty();
2967356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        }
2968356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
2969356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        fAllocator->updateHandle(handle, ctm, clip);
2970356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        return handle;
2971356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    }
2972356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    return nullptr;
2973356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed}
2974356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
2975356f7c2600ef54237fb8678cf63d5953f065b7daMike Reedstatic bool install(SkBitmap* bm, const SkImageInfo& info,
2976356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                    const SkRasterHandleAllocator::Rec& rec) {
2977086a427b0cee3862f25c492fc5082ff24105dc53Mike Reed    return bm->installPixels(info, rec.fPixels, rec.fRowBytes, rec.fReleaseProc, rec.fReleaseCtx);
2978356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed}
2979356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
2980356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedSkRasterHandleAllocator::Handle SkRasterHandleAllocator::allocBitmap(const SkImageInfo& info,
2981356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                                                                     SkBitmap* bm) {
2982356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    SkRasterHandleAllocator::Rec rec;
2983356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    if (!this->allocHandle(info, &rec) || !install(bm, info, rec)) {
2984356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        return nullptr;
2985356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    }
2986356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    return rec.fHandle;
2987356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed}
2988356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
2989356f7c2600ef54237fb8678cf63d5953f065b7daMike Reedstd::unique_ptr<SkCanvas>
2990356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedSkRasterHandleAllocator::MakeCanvas(std::unique_ptr<SkRasterHandleAllocator> alloc,
2991356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                                    const SkImageInfo& info, const Rec* rec) {
2992356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    if (!alloc || !supported_for_raster_canvas(info)) {
2993356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        return nullptr;
2994356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    }
2995356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
2996356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    SkBitmap bm;
2997356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    Handle hndl;
2998356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
2999356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    if (rec) {
3000356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        hndl = install(&bm, info, *rec) ? rec->fHandle : nullptr;
3001356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    } else {
3002356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        hndl = alloc->allocBitmap(info, &bm);
3003356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    }
3004356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    return hndl ? std::unique_ptr<SkCanvas>(new SkCanvas(bm, std::move(alloc), hndl)) : nullptr;
3005356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed}
3006