SkCanvas.cpp revision 343fe49b82d5b220d64c64f253bb362026006632
18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2008 The Android Open Source Project
38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
873fe7b07e6391da81dfc48d600d7b3141be1f471Herb Derby#include "SkArenaAlloc.h"
9986480a71f4e860663ced7ad90a1fe346a164afbMike Reed#include "SkBitmapDevice.h"
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h"
11d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed#include "SkCanvasPriv.h"
12d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include "SkClipStack.h"
13dbc3cefb0b624808ddb86d444e6103f216e12fa5reed#include "SkColorFilter.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h"
153cb3840c9af6f70896cf5565a38d4ee03c02d767reed#include "SkDrawable.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawFilter.h"
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawLooper.h"
18b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr#include "SkImage.h"
19262a71b7f95ce98ff3dd8dba845afbd724470903reed#include "SkImage_Base.h"
20900c36779610dc65c42a5004ee3693fd70961ba4senorblanco#include "SkImageFilter.h"
21900c36779610dc65c42a5004ee3693fd70961ba4senorblanco#include "SkImageFilterCache.h"
22c573a40ed5024b463e47088d307e3164a486dba5msarett#include "SkLatticeIter.h"
235df4934b3e40cdc378e225d1dda39f015cae9baeMike Reed#include "SkMakeUnique.h"
24262a71b7f95ce98ff3dd8dba845afbd724470903reed#include "SkMatrixUtils.h"
2574bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org#include "SkMetaData.h"
26ee424acbb87bf999be132a437527e656e37541d7Florin Malita#include "SkNoDrawCanvas.h"
27fbfa25802709139c2f14e304319c9541da65ca27msarett#include "SkNx.h"
28c83a29759a5c2966da5ab973e4fd90763e4c962breed#include "SkPaintPriv.h"
29b3c9d1c33caf325aada244204215eb790c228c12dandov#include "SkPatchUtils.h"
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPicture.h"
310017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com#include "SkRasterClip.h"
32356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed#include "SkRasterHandleAllocator.h"
334ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com#include "SkRRect.h"
344418dbac3386f26c8da62ab242be9c178961eb18robertphillips#include "SkSpecialImage.h"
352a475eae622adc1e8fa29206be1eaf862c23548eCary Clark#include "SkString.h"
3697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com#include "SkSurface_Base.h"
377ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita#include "SkTextBlob.h"
3852c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com#include "SkTextFormatParams.h"
39a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com#include "SkTLazy.h"
408f757f540a8378c7b1354aab3d4650eaa920b17adanakj#include "SkTraceEvent.h"
41d3ebb48320cf1b7e969974673e4bd7743816985ebungeman#include <new>
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
43644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#if SK_SUPPORT_GPU
447354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips#include "GrContext.h"
45644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org#include "GrRenderTarget.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 {}
92139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    void drawBitmap(const SkBitmap&, const SkMatrix&, 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;
52873fe7b07e6391da81dfc48d600d7b3141be1f471Herb Derby    char            fStorage[48];
52973fe7b07e6391da81dfc48d600d7b3141be1f471Herb Derby    SkArenaAlloc    fAlloc {fStorage};
530129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com
531129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    bool doNext(SkDrawFilter::Type drawType);
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
534129ec22cb054592261e001294c430c9dd4e90ff4reed@google.combool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
53596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fPaint = nullptr;
536129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    SkASSERT(!fIsSimple);
5375c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    SkASSERT(fLooperContext || fFilter || fTempLayerForImageFilter);
538632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com
539dbc3cefb0b624808ddb86d444e6103f216e12fa5reed    SkPaint* paint = fLazyPaintPerLooper.set(fLazyPaintInit.isValid() ?
540dbc3cefb0b624808ddb86d444e6103f216e12fa5reed                                             *fLazyPaintInit.get() : fOrigPaint);
5418926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
5425c476fb2776639bdbf0e974dd38d1c5d4c4ff1aareed    if (fTempLayerForImageFilter) {
54396fcdcc219d2a0d3579719b84b28bede76efba64halcanary        paint->setImageFilter(nullptr);
544374772bd61951f01bf84fe17bf53d8867681c9aereed        paint->setBlendMode(SkBlendMode::kSrcOver);
545129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
5468926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
54779fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
548129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        fDone = true;
549129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com        return false;
550129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
551129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    if (fFilter) {
552971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        if (!fFilter->filter(paint, drawType)) {
553971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            fDone = true;
554971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com            return false;
555971aca75572ed6e0c5e1cc959173dc58ca7b6b8dreed@google.com        }
55696fcdcc219d2a0d3579719b84b28bede76efba64halcanary        if (nullptr == fLooperContext) {
557129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com            // no looper means we only draw once
558632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com            fDone = true;
559632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com        }
560129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    }
561129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    fPaint = paint;
5628926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
563129ec22cb054592261e001294c430c9dd4e90ff4reed@google.com    // if we only came in here for the imagefilter, mark us as done
56479fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    if (!fLooperContext && !fFilter) {
5654e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        fDone = true;
5664e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
5674e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
568632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    // call this after any possible paint modifiers
569632e1a281bc66fb545dce690dff27b51cef41a8ereed@google.com    if (fPaint->nothingToDraw()) {
57096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        fPaint = nullptr;
5714e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        return false;
5724e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    }
5734e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    return true;
5744e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com}
5754e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com
5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////// macros to place around the internal draw calls //////////////////
5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5783aafe111b6cc388400092851cc53bbbdfcb8a81creed#define LOOPER_BEGIN_DRAWBITMAP(paint, skipLayerForFilter, bounds)  \
5793aafe111b6cc388400092851cc53bbbdfcb8a81creed    this->predrawNotify();                                          \
5803aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper looper(this, paint, skipLayerForFilter, bounds); \
5813aafe111b6cc388400092851cc53bbbdfcb8a81creed    while (looper.next(SkDrawFilter::kBitmap_Type)) {               \
582262a71b7f95ce98ff3dd8dba845afbd724470903reed        SkDrawIter iter(this);
583262a71b7f95ce98ff3dd8dba845afbd724470903reed
584262a71b7f95ce98ff3dd8dba845afbd724470903reed
5858926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com#define LOOPER_BEGIN_DRAWDEVICE(paint, type)                        \
58697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
5873aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper  looper(this, paint, true);                      \
5888926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    while (looper.next(type)) {                                     \
5898926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com        SkDrawIter          iter(this);
5908926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
59178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org#define LOOPER_BEGIN(paint, type, bounds)                           \
59297af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com    this->predrawNotify();                                          \
5933aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper  looper(this, paint, false, bounds);             \
5944e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    while (looper.next(type)) {                                     \
5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDrawIter          iter(this);
5964b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
597c83a29759a5c2966da5ab973e4fd90763e4c962breed#define LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, type, bounds, auxOpaque)  \
598c83a29759a5c2966da5ab973e4fd90763e4c962breed    this->predrawNotify(bounds, &paint, auxOpaque);                 \
5993aafe111b6cc388400092851cc53bbbdfcb8a81creed    AutoDrawLooper  looper(this, paint, false, bounds);             \
600c83a29759a5c2966da5ab973e4fd90763e4c962breed    while (looper.next(type)) {                                     \
601c83a29759a5c2966da5ab973e4fd90763e4c962breed        SkDrawIter          iter(this);
602c83a29759a5c2966da5ab973e4fd90763e4c962breed
6034e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com#define LOOPER_END    }
6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////
6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
607fbfa25802709139c2f14e304319c9541da65ca27msarettstatic inline SkRect qr_clip_bounds(const SkIRect& bounds) {
608fbfa25802709139c2f14e304319c9541da65ca27msarett    if (bounds.isEmpty()) {
609fbfa25802709139c2f14e304319c9541da65ca27msarett        return SkRect::MakeEmpty();
610fbfa25802709139c2f14e304319c9541da65ca27msarett    }
611fbfa25802709139c2f14e304319c9541da65ca27msarett
612fbfa25802709139c2f14e304319c9541da65ca27msarett    // Expand bounds out by 1 in case we are anti-aliasing.  We store the
613fbfa25802709139c2f14e304319c9541da65ca27msarett    // bounds as floats to enable a faster quick reject implementation.
614fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect dst;
615fbfa25802709139c2f14e304319c9541da65ca27msarett    SkNx_cast<float>(Sk4i::Load(&bounds.fLeft) + Sk4i(-1,-1,1,1)).store(&dst.fLeft);
616fbfa25802709139c2f14e304319c9541da65ca27msarett    return dst;
617fbfa25802709139c2f14e304319c9541da65ca27msarett}
618fbfa25802709139c2f14e304319c9541da65ca27msarett
619feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtkleinvoid SkCanvas::resetForNextPicture(const SkIRect& bounds) {
620feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    this->restoreToCount(1);
621feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    fMCRec->reset(bounds);
622feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
623feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein    // We're peering through a lot of structs here.  Only at this scope do we
624139e5e08a5d276b8dc988f7dee1b9c0467fcf607Mike Reed    // know that the device is a SkNoPixelsDevice.
625713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    static_cast<SkNoPixelsDevice*>(fMCRec->fLayer->fDevice.get())->resetForNextPicture(bounds);
626fbfa25802709139c2f14e304319c9541da65ca27msarett    fDeviceClipBounds = qr_clip_bounds(bounds);
6279637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    fIsScaleTranslate = true;
628feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein}
629feaadee1c38e1d4e1ec0069a3509ef6fbc5fbeffmtklein
630d954498c01ccf0417feacf89e45d0c62a06a813breedSkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
63142b73eb00367c8315974b1c374308d20efa78897reed    if (device && device->forceConservativeRasterClip()) {
63242b73eb00367c8315974b1c374308d20efa78897reed        flags = InitFlags(flags | kConservativeRasterClip_InitFlag);
63342b73eb00367c8315974b1c374308d20efa78897reed    }
63442b73eb00367c8315974b1c374308d20efa78897reed
63545a75fb4d0ca5daa0ac5e634238970306e3b5838caryclark@google.com    fAllowSimplifyClip = false;
6362ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount = 1;
63796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fMetaData = nullptr;
6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.push_back();
640a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    new (fMCRec) MCRec;
6415f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev    fMCRec->fRasterClip.setDeviceClipRestriction(&fClipRestrictionRect);
6429637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    fIsScaleTranslate = true;
6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
644a499f905e9340e4935447f2562fd92e8853382b1reed    SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage));
645a499f905e9340e4935447f2562fd92e8853382b1reed    fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
64653f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita    new (fDeviceCMStorage) DeviceCM(sk_ref_sp(device), nullptr, fMCRec->fMatrix, nullptr, nullptr);
647b679ca8926a832274b14fdb512f88f64b61d32eareed
6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = fMCRec->fLayer;
6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
65096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fSurfaceBase = nullptr;
651f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
652f92c86642a1875da54d54b447f006cb9dfbbb35creed    if (device) {
653efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        // The root device and the canvas should always have the same pixel geometry
654efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips        SkASSERT(fProps.pixelGeometry() == device->surfaceProps().pixelGeometry());
65578e276889795454891cbba48ab11927968114953reed        fMCRec->fRasterClip.setRect(device->getGlobalBounds());
656fbfa25802709139c2f14e304319c9541da65ca27msarett        fDeviceClipBounds = qr_clip_bounds(device->getGlobalBounds());
657c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
658c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
659f92c86642a1875da54d54b447f006cb9dfbbb35creed    }
660fbfa25802709139c2f14e304319c9541da65ca27msarett
661f92c86642a1875da54d54b447f006cb9dfbbb35creed    return device;
6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
664cde92111d50a96b6d0f3e166fbac7c9bc6eca349reed@google.comSkCanvas::SkCanvas()
665e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6664a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
667e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
6688d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org    inc_canvas();
669ba124485687130183643994f1b4b68d629fbbebaskia.committer@gmail.com
67096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    this->init(nullptr, kDefault_InitFlags);
6718d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org}
6728d84fac294682647694b0d2d8a87ac2bd19b6aabvandebo@chromium.org
67396a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reedSkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props)
674e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
67596a857ef5a40b3d0751ec9ebaaa96d9f20b82b21reed    , fProps(SkSurfacePropsCopyOrDefault(props))
676e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org{
677e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org    inc_canvas();
678b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
679566e53c7003920ff45c72498754060804b657c68Mike Reed    this->init(new SkNoPixelsDevice(SkIRect::MakeWH(SkTMax(width, 0), SkTMax(height, 0)), fProps),
680385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary               kDefault_InitFlags)->unref();
681d954498c01ccf0417feacf89e45d0c62a06a813breed}
682e254310a55d55a710309714c48f7fbbe7a6126f7commit-bot@chromium.org
68378e276889795454891cbba48ab11927968114953reedSkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags)
684d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6854a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
686d954498c01ccf0417feacf89e45d0c62a06a813breed{
687d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
688b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
689566e53c7003920ff45c72498754060804b657c68Mike Reed    SkIRect r = bounds.isEmpty() ? SkIRect::MakeEmpty() : bounds;
690566e53c7003920ff45c72498754060804b657c68Mike Reed    this->init(new SkNoPixelsDevice(r, fProps), flags)->unref();
69127a5e656c3d6ef22f9cb34de18e1b960da3aa241reed}
6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
693d954498c01ccf0417feacf89e45d0c62a06a813breedSkCanvas::SkCanvas(SkBaseDevice* device)
694d954498c01ccf0417feacf89e45d0c62a06a813breed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
6957b05ff11ebc51f3f3abd1c1756337a04f563537erobertphillips    , fProps(device->surfaceProps())
696d954498c01ccf0417feacf89e45d0c62a06a813breed{
697d954498c01ccf0417feacf89e45d0c62a06a813breed    inc_canvas();
698b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
699d954498c01ccf0417feacf89e45d0c62a06a813breed    this->init(device, kDefault_InitFlags);
7008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
702fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillipsSkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags)
703fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7047b05ff11ebc51f3f3abd1c1756337a04f563537erobertphillips    , fProps(device->surfaceProps())
705fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips{
706fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    inc_canvas();
707fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips
708fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips    this->init(device, flags);
709fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips}
710fcf7829b67b798aff4c41c4688daa9c7381991e6robertphillips
7114a8126e7f81384526629b1e21bf89b632ea13cd9reedSkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
7123716fd067a5621bb94a6cb08d72afec8bf3acedareed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7134a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(props)
7143716fd067a5621bb94a6cb08d72afec8bf3acedareed{
7153716fd067a5621bb94a6cb08d72afec8bf3acedareed    inc_canvas();
716b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
717704cd32e4a92d6c3eae6bfae4adcc20126bf4437Hal Canary    sk_sp<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps));
718704cd32e4a92d6c3eae6bfae4adcc20126bf4437Hal Canary    this->init(device.get(), kDefault_InitFlags);
7194a8126e7f81384526629b1e21bf89b632ea13cd9reed}
72029c857d0f3a1cb837f73406eeb6ba9771879b5e7reed
721356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedSkCanvas::SkCanvas(const SkBitmap& bitmap, std::unique_ptr<SkRasterHandleAllocator> alloc,
722356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                   SkRasterHandleAllocator::Handle hndl)
7234a8126e7f81384526629b1e21bf89b632ea13cd9reed    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
7244a8126e7f81384526629b1e21bf89b632ea13cd9reed    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
725356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    , fAllocator(std::move(alloc))
7264a8126e7f81384526629b1e21bf89b632ea13cd9reed{
7274a8126e7f81384526629b1e21bf89b632ea13cd9reed    inc_canvas();
728b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
729356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    sk_sp<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps, hndl));
730704cd32e4a92d6c3eae6bfae4adcc20126bf4437Hal Canary    this->init(device.get(), kDefault_InitFlags);
7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
733356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedSkCanvas::SkCanvas(const SkBitmap& bitmap) : SkCanvas(bitmap, nullptr, nullptr) {}
734356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
73531f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
73631f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt SarettSkCanvas::SkCanvas(const SkBitmap& bitmap, ColorBehavior)
73731f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
73831f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
73931f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    , fAllocator(nullptr)
74031f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett{
74131f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    inc_canvas();
74231f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett
74331f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    SkBitmap tmp(bitmap);
74431f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    *const_cast<SkImageInfo*>(&tmp.info()) = tmp.info().makeColorSpace(nullptr);
74531f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    sk_sp<SkBaseDevice> device(new SkBitmapDevice(tmp, fProps, nullptr));
74631f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett    this->init(device.get(), kDefault_InitFlags);
74731f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett}
74831f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett#endif
74931f99ce7d2f3c2b61742d07ab92b6dac6a928ef9Matt Sarett
7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::~SkCanvas() {
7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // free up the contents of our deque
7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->restoreToCount(1);    // restore everything but the last
7537c2029367cea5479fa3b74fb0ca2b0297b42b709reed@google.com
7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->internalRestore();    // restore the last, since we're going away
7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
756385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary    delete fMetaData;
757b70ae310bbdaa1b26786773aabce5548c1f48563vandebo@chromium.org
7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dec_canvas();
7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
76153d9f1cfbd5ddbf57c2f22b9e613ce48e5b2896cfmalita#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::getDrawFilter() const {
7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fMCRec->fFilter;
7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) {
76751985e3f5e608d369e52832b7ce489d85d402422reed    this->checkForDeferredSave();
7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fMCRec->fFilter, filter);
7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7717765000709dc64eb23be7df47d1f995d1f787115fmalita#endif
7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
77374bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.orgSkMetaData& SkCanvas::getMetaData() {
77474bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // metadata users are rare, so we lazily allocate it. If that changes we
77574bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    // can decide to just make it a field in the device (rather than a ptr)
77696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == fMetaData) {
77774bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org        fMetaData = new SkMetaData;
77874bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    }
77974bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org    return *fMetaData;
78074bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org}
78174bb77ee4c747b8c70c5c613987c9f93df71df06mike@reedtribe.org
7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
7838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
784bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.orgvoid SkCanvas::flush() {
785ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed    this->onFlush();
786ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed}
787ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed
788ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reedvoid SkCanvas::onFlush() {
7891f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkBaseDevice* device = this->getDevice();
790bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    if (device) {
791bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org        device->flush();
792bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org    }
793bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org}
794bf6c1e4aff4d233f6502157fb73459cf69d0ab37junov@chromium.org
795afc7cce5d68663934128d76963cd501f771d71desenorblancoSkISize SkCanvas::getBaseLayerSize() const {
796afc7cce5d68663934128d76963cd501f771d71desenorblanco    SkBaseDevice* d = this->getDevice();
7974ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
7984ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com}
7994ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com
800afc7cce5d68663934128d76963cd501f771d71desenorblancoSkIRect SkCanvas::getTopLayerBounds() const {
8014ebe3821888d550d8a8b89341ec251ba942f0225bsalomon@google.com    SkBaseDevice* d = this->getTopDevice();
802afc7cce5d68663934128d76963cd501f771d71desenorblanco    if (!d) {
803afc7cce5d68663934128d76963cd501f771d71desenorblanco        return SkIRect::MakeEmpty();
804afc7cce5d68663934128d76963cd501f771d71desenorblanco    }
805afc7cce5d68663934128d76963cd501f771d71desenorblanco    return SkIRect::MakeXYWH(d->getOrigin().x(), d->getOrigin().y(), d->width(), d->height());
806210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com}
807210ce003a5ec039dda80de0569fb47ca4efc4dc7reed@google.com
8081f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::getDevice() const {
8098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return root device
810c029062a0312fb747fb6c2677983aba51795c580robertphillips@google.com    MCRec* rec = (MCRec*) fMCStack.front();
8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(rec && rec->fLayer);
812713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    return rec->fLayer->fDevice.get();
8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8150ed3b640c9da71fbbd73c65a4ec1992f85596271Florin MalitaSkBaseDevice* SkCanvas::getTopDevice() const {
816713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita    return fMCRec->fTopLayer->fDevice.get();
8179266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com}
8189266fed56a46a4edc710a52c7be8d46fd7c2bc7areed@google.com
81996472deea70169396b8e1f576e470138f55fdb1freedbool SkCanvas::readPixels(const SkImageInfo& dstInfo, void* dstP, size_t rowBytes, int x, int y) {
820a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
821a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    if (!device) {
822a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org        return false;
823a713f9c6f6a06d216d53e268b9c691941053dabfcommit-bot@chromium.org    }
824db0c8753775774aa3f67114491e26ac1be32f38eskia.committer@gmail.com
82503dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    return device->readPixels(dstInfo, dstP, rowBytes, x, y);
82651df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com}
82751df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
82812e946b4bfdf598bffb276776ea6e25439e25265Mike Reedbool SkCanvas::readPixels(const SkPixmap& pm, int x, int y) {
82912e946b4bfdf598bffb276776ea6e25439e25265Mike Reed    return pm.addr() && this->readPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), x, y);
83012e946b4bfdf598bffb276776ea6e25439e25265Mike Reed}
83112e946b4bfdf598bffb276776ea6e25439e25265Mike Reed
83212e946b4bfdf598bffb276776ea6e25439e25265Mike Reedbool SkCanvas::readPixels(const SkBitmap& bm, int x, int y) {
83312e946b4bfdf598bffb276776ea6e25439e25265Mike Reed    SkPixmap pm;
83412e946b4bfdf598bffb276776ea6e25439e25265Mike Reed    return bm.peekPixels(&pm) && this->readPixels(pm, x, y);
83512e946b4bfdf598bffb276776ea6e25439e25265Mike Reed}
83612e946b4bfdf598bffb276776ea6e25439e25265Mike Reed
8374cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.orgbool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
8384edb5d219eb99aa1e8fbe5e37260d3b34314e54bMike Reed    SkPixmap pm;
8394edb5d219eb99aa1e8fbe5e37260d3b34314e54bMike Reed    if (bitmap.peekPixels(&pm)) {
840cf01e31df6bbda270dca2ee3b4967caf51e465dcreed        return this->writePixels(pm.info(), pm.addr(), pm.rowBytes(), x, y);
8414cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8424cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    return false;
8434cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
8444cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
84503dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarettbool SkCanvas::writePixels(const SkImageInfo& srcInfo, const void* pixels, size_t rowBytes,
8464cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org                           int x, int y) {
8474cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    SkBaseDevice* device = this->getDevice();
8484cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    if (!device) {
8494cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org        return false;
8504cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8514cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
85203dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // This check gives us an early out and prevents generation ID churn on the surface.
85303dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // This is purely optional: it is a subset of the checks performed by SkWritePixelsRec.
85403dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    SkIRect srcRect = SkIRect::MakeXYWH(x, y, srcInfo.width(), srcInfo.height());
85503dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    if (!srcRect.intersect(0, 0, device->width(), device->height())) {
85603dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett        return false;
8574cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org    }
8584cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
85903dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // Tell our owning surface to bump its generation ID.
86003dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    const bool completeOverwrite =
86103dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett            srcRect.size() == SkISize::Make(device->width(), device->height());
862c83a29759a5c2966da5ab973e4fd90763e4c962breed    this->predrawNotify(completeOverwrite);
8634af35f348b2e2f6c428819118eb7a2f2fff53a74reed
86403dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // This can still fail, most notably in the case of a invalid color type or alpha type
86503dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // conversion.  We could pull those checks into this function and avoid the unnecessary
86603dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // generation ID bump.  But then we would be performing those checks twice, since they
86703dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    // are also necessary at the bitmap/pixmap entry points.
86803dd6d5208a6e3d92190e7020300e4399178ae4bMatt Sarett    return device->writePixels(srcInfo, pixels, rowBytes, x, y);
8694cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org}
87051df9e3fe3c1aec370854b2718df16fc02faa1b2reed@google.com
8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8732ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::checkForDeferredSave() {
8742ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
8752ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        this->doSave();
8762ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
8772ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
8782ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
879f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::getSaveCount() const {
8802ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#ifdef SK_DEBUG
8812ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    int count = 0;
8822ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkDeque::Iter iter(fMCStack, SkDeque::Iter::kFront_IterStart);
8832ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    for (;;) {
8842ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        const MCRec* rec = (const MCRec*)iter.next();
8852ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (!rec) {
8862ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            break;
8872ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
8882ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        count += 1 + rec->fDeferredSaveCount;
8892ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
8902ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    SkASSERT(count == fSaveCount);
8912ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed#endif
8922ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return fSaveCount;
893f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
894f0090cb80ab10a49e511aa5450ae38917fa058d9reed
895f0090cb80ab10a49e511aa5450ae38917fa058d9reedint SkCanvas::save() {
8962ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fSaveCount += 1;
8972ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    fMCRec->fDeferredSaveCount += 1;
8982ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;  // return our prev value
8992ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed}
9002ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed
9012ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::doSave() {
902f0090cb80ab10a49e511aa5450ae38917fa058d9reed    this->willSave();
903a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita
904a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    SkASSERT(fMCRec->fDeferredSaveCount > 0);
905a62d32d1e3112c7e5a26c27e5e967d124ef8dd81fmalita    fMCRec->fDeferredSaveCount -= 1;
9062ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
907f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
908f0090cb80ab10a49e511aa5450ae38917fa058d9reed
909f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restore() {
9102ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    if (fMCRec->fDeferredSaveCount > 0) {
9112ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        SkASSERT(fSaveCount > 1);
9122ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fSaveCount -= 1;
9132ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        fMCRec->fDeferredSaveCount -= 1;
9142ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    } else {
9152ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        // check for underflow
9162ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        if (fMCStack.count() > 1) {
9172ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->willRestore();
9182ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            SkASSERT(fSaveCount > 1);
919a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed            fSaveCount -= 1;
9202ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->internalRestore();
9212ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            this->didRestore();
9222ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        }
923f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
924f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
925f0090cb80ab10a49e511aa5450ae38917fa058d9reed
926f0090cb80ab10a49e511aa5450ae38917fa058d9reedvoid SkCanvas::restoreToCount(int count) {
927f0090cb80ab10a49e511aa5450ae38917fa058d9reed    // sanity check
928f0090cb80ab10a49e511aa5450ae38917fa058d9reed    if (count < 1) {
929f0090cb80ab10a49e511aa5450ae38917fa058d9reed        count = 1;
930f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
931f0f14113431ace669f278fdd97b50950f2cf4c80mtklein
932f0090cb80ab10a49e511aa5450ae38917fa058d9reed    int n = this->getSaveCount() - count;
933f0090cb80ab10a49e511aa5450ae38917fa058d9reed    for (int i = 0; i < n; ++i) {
934f0090cb80ab10a49e511aa5450ae38917fa058d9reed        this->restore();
935f0090cb80ab10a49e511aa5450ae38917fa058d9reed    }
936f0090cb80ab10a49e511aa5450ae38917fa058d9reed}
937f0090cb80ab10a49e511aa5450ae38917fa058d9reed
9382ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreedvoid SkCanvas::internalSave() {
9398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    MCRec* newTop = (MCRec*)fMCStack.push_back();
940d954498c01ccf0417feacf89e45d0c62a06a813breed    new (newTop) MCRec(*fMCRec);    // balanced in restore()
9418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = newTop;
9424b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
943c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    FOR_EACH_TOP_DEVICE(device->save());
9448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9464960eeec4a1f2a772654883d7f3615d47bcd5dc3reedbool SkCanvas::BoundsAffectsClip(SaveLayerFlags saveLayerFlags) {
9474960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    return !(saveLayerFlags & SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag);
9488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9504960eeec4a1f2a772654883d7f3615d47bcd5dc3reedbool SkCanvas::clipRectBounds(const SkRect* bounds, SaveLayerFlags saveLayerFlags,
9519b3aa54bc9605257c701cf465813f5fb1d7ba39ereed                              SkIRect* intersection, const SkImageFilter* imageFilter) {
952918e144408ba218df919528f8b48c544f4767883Mike Reed    SkIRect clipBounds = this->getDeviceClipBounds();
953918e144408ba218df919528f8b48c544f4767883Mike Reed    if (clipBounds.isEmpty()) {
954a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        return false;
955f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
956c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
95796e657d0e103b8358a77ecd913f6086929f792b8reed    const SkMatrix& ctm = fMCRec->fMatrix;  // this->getTotalMatrix()
95896e657d0e103b8358a77ecd913f6086929f792b8reed
959c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (imageFilter) {
960e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco        clipBounds = imageFilter->filterBounds(clipBounds, ctm);
961db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco        if (bounds && !imageFilter->canComputeFastBounds()) {
962db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco            bounds = nullptr;
963db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco        }
964c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
965bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com    SkIRect ir;
96649f085dddff10473b6ebf832a974288300224e60bsalomon    if (bounds) {
9678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRect r;
9684b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
96996e657d0e103b8358a77ecd913f6086929f792b8reed        ctm.mapRect(&r, *bounds);
9708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r.roundOut(&ir);
9718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // early exit if the layer's bounds are clipped out
9728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!ir.intersect(clipBounds)) {
9734960eeec4a1f2a772654883d7f3615d47bcd5dc3reed            if (BoundsAffectsClip(saveLayerFlags)) {
974a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed                fMCRec->fTopLayer->fDevice->clipRegion(SkRegion(), SkClipOp::kIntersect); // empty
9751f836ee096bb988adef4b9757b2629c7afeda36dreed                fMCRec->fRasterClip.setEmpty();
976fbfa25802709139c2f14e304319c9541da65ca27msarett                fDeviceClipBounds.setEmpty();
977bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com            }
978a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org            return false;
9798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // no user bounds, so just use the clip
9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ir = clipBounds;
9828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
983180aec43451dd951fdaae81a92efc710ba093260reed    SkASSERT(!ir.isEmpty());
9848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9854960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    if (BoundsAffectsClip(saveLayerFlags)) {
986180aec43451dd951fdaae81a92efc710ba093260reed        // Simplify the current clips since they will be applied properly during restore()
987180aec43451dd951fdaae81a92efc710ba093260reed        fMCRec->fRasterClip.setRect(ir);
988fbfa25802709139c2f14e304319c9541da65ca27msarett        fDeviceClipBounds = qr_clip_bounds(ir);
989a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
990a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
991a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    if (intersection) {
992a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org        *intersection = ir;
993a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    }
994a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    return true;
995a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org}
996a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
9974960eeec4a1f2a772654883d7f3615d47bcd5dc3reed
9984960eeec4a1f2a772654883d7f3615d47bcd5dc3reedint SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
9994960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    return this->saveLayer(SaveLayerRec(bounds, paint, 0));
1000d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
1001d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
10024960eeec4a1f2a772654883d7f3615d47bcd5dc3reedint SkCanvas::saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint) {
10034960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    return this->saveLayer(SaveLayerRec(bounds, paint, kPreserveLCDText_SaveLayerFlag));
10044960eeec4a1f2a772654883d7f3615d47bcd5dc3reed}
10054960eeec4a1f2a772654883d7f3615d47bcd5dc3reed
10064960eeec4a1f2a772654883d7f3615d47bcd5dc3reedint SkCanvas::saveLayer(const SaveLayerRec& origRec) {
100753f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita    SkTCopyOnFirstWrite<SaveLayerRec> rec(origRec);
1008d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    if (gIgnoreSaveLayerBounds) {
100953f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita        rec.writable()->fBounds = nullptr;
1010d990e2f14f14c36c3d0beb303dd0953c7aa1fcfareed    }
101153f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita
101253f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita    SaveLayerStrategy strategy = this->getSaveLayerStrategy(*rec);
1013a644116c3375b12c642d1b51ee1e5cf4a22c1f5breed    fSaveCount += 1;
101453f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita    this->internalSaveLayer(*rec, strategy);
10152ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    return this->getSaveCount() - 1;
10168926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com}
10178926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com
1018a2217ef965e57fdbbf989989e7ec1f2c04f62d39reedvoid SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter,
1019c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed                                    SkBaseDevice* dst, const SkIPoint& dstOrigin,
1020a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed                                    const SkMatrix& ctm) {
1021a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    SkDraw draw;
1022a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    SkRasterClip rc;
1023a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    rc.setRect(SkIRect::MakeWH(dst->width(), dst->height()));
1024a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    if (!dst->accessPixels(&draw.fDst)) {
1025a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        draw.fDst.reset(dst->imageInfo(), nullptr, 0);
1026a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    }
1027a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    draw.fMatrix = &SkMatrix::I();
1028a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    draw.fRC = &rc;
10297354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips
10307354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips    SkPaint p;
1031c61abeed8958a757c6b49937f28b63066148dd67Mike Reed    if (filter) {
1032c61abeed8958a757c6b49937f28b63066148dd67Mike Reed        p.setImageFilter(filter->makeWithLocalMatrix(ctm));
1033c61abeed8958a757c6b49937f28b63066148dd67Mike Reed    }
1034a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed
1035c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    int x = src->getOrigin().x() - dstOrigin.x();
1036c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    int y = src->getOrigin().y() - dstOrigin.y();
1037a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    auto special = src->snapSpecial();
1038a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    if (special) {
103953f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita        dst->drawSpecial(special.get(), x, y, p, nullptr, SkMatrix::I());
1040a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    }
10417354a4b193aaaeae43fb9ede90e1158fa46c372brobertphillips}
104270ee31b2fa127eee6c0cea61cf05508e9d3ca7b1reed
1043129ed1cd6d792f3f6cf563aefa9756fc6308289dreedstatic SkImageInfo make_layer_info(const SkImageInfo& prev, int w, int h, bool isOpaque,
1044129ed1cd6d792f3f6cf563aefa9756fc6308289dreed                                   const SkPaint* paint) {
1045129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    // need to force L32 for now if we have an image filter. Once filters support other colortypes
1046129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    // e.g. sRGB or F16, we can remove this check
104752ede1d905728cdcaa98db1e4a33724f5a85c62dbrianosman    // SRGBTODO: Can we remove this check now?
1048129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    const bool hasImageFilter = paint && paint->getImageFilter();
1049129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
1050129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    SkAlphaType alphaType = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
1051129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    if ((prev.bytesPerPixel() < 4) || hasImageFilter) {
1052129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        // force to L32
1053129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        return SkImageInfo::MakeN32(w, h, alphaType);
1054129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    } else {
1055129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        // keep the same characteristics as the prev
1056693fdbd6b81a860657612e7604430dd55d6e721bMike Reed        return SkImageInfo::Make(w, h, prev.colorType(), alphaType, prev.refColorSpace());
1057129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    }
1058129ed1cd6d792f3f6cf563aefa9756fc6308289dreed}
1059129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
10604960eeec4a1f2a772654883d7f3615d47bcd5dc3reedvoid SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy strategy) {
10614960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    const SkRect* bounds = rec.fBounds;
10624960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    const SkPaint* paint = rec.fPaint;
10634960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    SaveLayerFlags saveLayerFlags = rec.fSaveLayerFlags;
10644960eeec4a1f2a772654883d7f3615d47bcd5dc3reed
10658c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkLazyPaint lazyP;
10668c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkImageFilter* imageFilter = paint ? paint->getImageFilter() : NULL;
10678c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkMatrix stashedMatrix = fMCRec->fMatrix;
10688c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkMatrix remainder;
10698c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    SkSize scale;
10708c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    /*
10718c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  ImageFilters (so far) do not correctly handle matrices (CTM) that contain rotation/skew/etc.
10728c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  but they do handle scaling. To accommodate this, we do the following:
10738c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *
10748c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  1. Stash off the current CTM
10758c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  2. Decompose the CTM into SCALE and REMAINDER
10768c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  3. Wack the CTM to be just SCALE, and wrap the imagefilter with a MatrixImageFilter that
10778c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *     contains the REMAINDER
10788c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  4. Proceed as usual, allowing the client to draw into the layer (now with a scale-only CTM)
10798c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  5. During restore, we process the MatrixImageFilter, which applies REMAINDER to the output
10808c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *     of the original imagefilter, and draw that (via drawSprite)
10818c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  6. Unwack the CTM to its original state (i.e. stashedMatrix)
10828c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *
10838c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  Perhaps in the future we could augment #5 to apply REMAINDER as part of the draw (no longer
10848c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     *  a sprite operation) to avoid the extra buffer/overhead of MatrixImageFilter.
10858c30a8196dd5903d2d23b4d0a5dc888e802bf698reed     */
108696a04f329926099f0002f97883242793ff04f61creed    if (imageFilter && !stashedMatrix.isScaleTranslate() && !imageFilter->canHandleComplexCTM() &&
10878c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        stashedMatrix.decomposeScale(&scale, &remainder))
10888c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    {
10898c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        // We will restore the matrix (which we are overwriting here) in restore via fStashedMatrix
10908c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        this->internalSetMatrix(SkMatrix::MakeScale(scale.width(), scale.height()));
10918c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        SkPaint* p = lazyP.set(*paint);
10928c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        p->setImageFilter(SkImageFilter::MakeMatrixFilter(remainder,
10938c30a8196dd5903d2d23b4d0a5dc888e802bf698reed                                                          SkFilterQuality::kLow_SkFilterQuality,
10948c30a8196dd5903d2d23b4d0a5dc888e802bf698reed                                                          sk_ref_sp(imageFilter)));
10958c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        imageFilter = p->getImageFilter();
10968c30a8196dd5903d2d23b4d0a5dc888e802bf698reed        paint = p;
10978c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    }
10988c30a8196dd5903d2d23b4d0a5dc888e802bf698reed
1099a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // do this before we create the layer. We don't call the public save() since
1100a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    // that would invoke a possibly overridden virtual
11012ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->internalSave();
1102a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org
1103a907ac3e3e3458fbb5d673c3feafb31fd7647b38junov@chromium.org    SkIRect ir;
11048c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, imageFilter)) {
11052ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
11068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1108e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
1109e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    // the clipRectBounds() call above?
1110e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    if (kNoLayer_SaveLayerStrategy == strategy) {
11112ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1112e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org    }
1113e54a23fcfa42b2fc9d320650de72bcb2d9566b2dcommit-bot@chromium.org
11144960eeec4a1f2a772654883d7f3615d47bcd5dc3reed    bool isOpaque = SkToBool(saveLayerFlags & kIsOpaque_SaveLayerFlag);
11158dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    SkPixelGeometry geo = fProps.pixelGeometry();
11168dc0ccb8d33d1af7dd13228509e61fe915bc7705reed    if (paint) {
111776033be81b82c44fd5d4fdf2672eb22e505da1f0reed        // TODO: perhaps add a query to filters so we might preserve opaqueness...
1118daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        if (paint->getImageFilter() || paint->getColorFilter()) {
111976033be81b82c44fd5d4fdf2672eb22e505da1f0reed            isOpaque = false;
11208dc0ccb8d33d1af7dd13228509e61fe915bc7705reed            geo = kUnknown_SkPixelGeometry;
1121b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com        }
1122b55deeb1c7c692023603639a9b29c0e3de124eacreed@google.com    }
11238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11245139e501c5ac3a511e35c78395c907a176113451robertphillips    SkBaseDevice* priorDevice = this->getTopDevice();
1125c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    if (nullptr == priorDevice) {   // Do we still need this check???
1126b2db898573e3cdcc8234eebf51961bfc4977ebbcreed        SkDebugf("Unable to find device for layer.");
11272ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        return;
1128b2db898573e3cdcc8234eebf51961bfc4977ebbcreed    }
1129b2db898573e3cdcc8234eebf51961bfc4977ebbcreed
11305139e501c5ac3a511e35c78395c907a176113451robertphillips    SkImageInfo info = make_layer_info(priorDevice->imageInfo(), ir.width(), ir.height(), isOpaque,
1131129ed1cd6d792f3f6cf563aefa9756fc6308289dreed                                       paint);
1132129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
1133704cd32e4a92d6c3eae6bfae4adcc20126bf4437Hal Canary    sk_sp<SkBaseDevice> newDevice;
113461f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed    {
113570ee31b2fa127eee6c0cea61cf05508e9d3ca7b1reed        const bool preserveLCDText = kOpaque_SkAlphaType == info.alphaType() ||
11364960eeec4a1f2a772654883d7f3615d47bcd5dc3reed                                     (saveLayerFlags & kPreserveLCDText_SaveLayerFlag);
1137daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed        const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
113870ee31b2fa127eee6c0cea61cf05508e9d3ca7b1reed        const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo,
1139356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                                                                             preserveLCDText,
1140356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                                                                             fAllocator.get());
11415139e501c5ac3a511e35c78395c907a176113451robertphillips        newDevice.reset(priorDevice->onCreateDevice(createInfo, paint));
11425139e501c5ac3a511e35c78395c907a176113451robertphillips        if (!newDevice) {
11437503d60847c4ad22df87458aecd917772b23d293reed            return;
114461f501f8c675da8d5915e5e7fd32dfdb113f1cfbreed        }
1145e25c68402b38ac01dc1ae196ae8a5265b773c5f2bungeman@google.com    }
114653f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita    DeviceCM* layer = new DeviceCM(newDevice, paint, stashedMatrix, rec.fClipMask, rec.fClipMatrix);
11478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1148b43a3e0160b3854a04305decd1d9e766a3889b3aMike Reed    // only have a "next" if this new layer doesn't affect the clip (rare)
1149b43a3e0160b3854a04305decd1d9e766a3889b3aMike Reed    layer->fNext = BoundsAffectsClip(saveLayerFlags) ? nullptr : fMCRec->fTopLayer;
11508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fLayer = layer;
11518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
1152a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed
1153c61abeed8958a757c6b49937f28b63066148dd67Mike Reed    if ((rec.fSaveLayerFlags & kInitWithPrevious_SaveLayerFlag) || rec.fBackdrop) {
1154c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        DrawDeviceWithFilter(priorDevice, rec.fBackdrop, newDevice.get(), { ir.fLeft, ir.fTop },
1155a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed                             fMCRec->fMatrix);
1156a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    }
1157c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
1158c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    newDevice->setOrigin(fMCRec->fMatrix, ir.fLeft, ir.fTop);
1159c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
1160c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    newDevice->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
1161c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    if (layer->fNext) {
1162c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        // need to punch a hole in the previous device, so we don't draw there, given that
1163c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        // the new top-layer will allow drawing to happen "below" it.
1164c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        SkRegion hole(ir);
1165c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        do {
1166c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed            layer = layer->fNext;
1167c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed            layer->fDevice->clipRegion(hole, SkClipOp::kDifference);
1168c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        } while (layer->fNext);
1169c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    }
11708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1172d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.orgint SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
1173bada1885da479d948f065182d6dfa85a1140bda5reed    if (0xFF == alpha) {
1174bada1885da479d948f065182d6dfa85a1140bda5reed        return this->saveLayer(bounds, nullptr);
1175bada1885da479d948f065182d6dfa85a1140bda5reed    } else {
1176bada1885da479d948f065182d6dfa85a1140bda5reed        SkPaint tmpPaint;
1177bada1885da479d948f065182d6dfa85a1140bda5reed        tmpPaint.setAlpha(alpha);
1178bada1885da479d948f065182d6dfa85a1140bda5reed        return this->saveLayer(bounds, &tmpPaint);
1179bada1885da479d948f065182d6dfa85a1140bda5reed    }
1180d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org}
1181d70fa2013adccaa52d1f3e6ca501a4d4ab1520f3commit-bot@chromium.org
11828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::internalRestore() {
11838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fMCStack.count() != 0);
11848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
118588edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    // reserve our layer (if any)
11868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DeviceCM* layer = fMCRec->fLayer;   // may be null
11878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
118896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fMCRec->fLayer = nullptr;
11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now do the normal restore()
11918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec->~MCRec();       // balanced in save()
11928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCStack.pop_back();
11938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMCRec = (MCRec*)fMCStack.back();
11948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1195c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    if (fMCRec) {
1196c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        FOR_EACH_TOP_DEVICE(device->restore(fMCRec->fMatrix));
1197c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    }
1198c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
11998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
12008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        since if we're being recorded, we don't want to record this (the
12018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        recorder will have already recorded the restore).
12028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
120349f085dddff10473b6ebf832a974288300224e60bsalomon    if (layer) {
1204b43a3e0160b3854a04305decd1d9e766a3889b3aMike Reed        if (fMCRec) {
12056f8f292aa768869a9e85c314b124875f57504f2creed@google.com            const SkIPoint& origin = layer->fDevice->getOrigin();
1206713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita            this->internalDrawDevice(layer->fDevice.get(), origin.x(), origin.y(),
120753f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita                                     layer->fPaint.get(),
120853f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita                                     layer->fClipImage.get(), layer->fClipMatrix);
12098c30a8196dd5903d2d23b4d0a5dc888e802bf698reed            // restore what we smashed in internalSaveLayer
12108c30a8196dd5903d2d23b4d0a5dc888e802bf698reed            fMCRec->fMatrix = layer->fStashedMatrix;
12118926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com            // reset this, since internalDrawDevice will have set it to true
1212385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            delete layer;
1213b679ca8926a832274b14fdb512f88f64b61d32eareed        } else {
1214b679ca8926a832274b14fdb512f88f64b61d32eareed            // we're at the root
1215a499f905e9340e4935447f2562fd92e8853382b1reed            SkASSERT(layer == (void*)fDeviceCMStorage);
1216b679ca8926a832274b14fdb512f88f64b61d32eareed            layer->~DeviceCM();
12178c30a8196dd5903d2d23b4d0a5dc888e802bf698reed            // no need to update fMCRec, 'cause we're killing the canvas
12188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
121988edf1e50794e6d8cd7cc671ffce4f5e329ef888bungeman@google.com    }
1220fbfa25802709139c2f14e304319c9541da65ca27msarett
1221fbfa25802709139c2f14e304319c9541da65ca27msarett    if (fMCRec) {
12229637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett        fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate();
1223fbfa25802709139c2f14e304319c9541da65ca27msarett        fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1224fbfa25802709139c2f14e304319c9541da65ca27msarett    }
12258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1227e8f3062a36d3682f4019309a32b5b84dc9eddf8creedsk_sp<SkSurface> SkCanvas::makeSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
122896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == props) {
12294a8126e7f81384526629b1e21bf89b632ea13cd9reed        props = &fProps;
12304a8126e7f81384526629b1e21bf89b632ea13cd9reed    }
12314a8126e7f81384526629b1e21bf89b632ea13cd9reed    return this->onNewSurface(info, *props);
123276f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
123376f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
1234e8f3062a36d3682f4019309a32b5b84dc9eddf8creedsk_sp<SkSurface> SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
123576f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com    SkBaseDevice* dev = this->getDevice();
1236e8f3062a36d3682f4019309a32b5b84dc9eddf8creed    return dev ? dev->makeSurface(info, props) : nullptr;
123776f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com}
123876f10a3bd936af7dbe2b5873d5a7eedd73cdc5dareed@google.com
1239c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.orgSkImageInfo SkCanvas::imageInfo() const {
1240ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed    return this->onImageInfo();
1241ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed}
1242ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed
1243ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reedSkImageInfo SkCanvas::onImageInfo() const {
1244c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1245c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    if (dev) {
1246c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org        return dev->imageInfo();
1247c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    } else {
1248900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        return SkImageInfo::MakeUnknown(0, 0);
1249c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    }
1250c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1251c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1252898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosmanbool SkCanvas::getProps(SkSurfaceProps* props) const {
1253ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed    return this->onGetProps(props);
1254ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed}
1255ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reed
1256ea5a6513c05e3d7261b68c3ef7d42645ee5bfe17reedbool SkCanvas::onGetProps(SkSurfaceProps* props) const {
1257898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman    SkBaseDevice* dev = this->getDevice();
1258898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman    if (dev) {
1259898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman        if (props) {
1260898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman            *props = fProps;
1261898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman        }
1262898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman        return true;
1263898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman    } else {
1264898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman        return false;
1265898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman    }
1266898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman}
1267898235c4864df66aa7f6d32bc2a8b8551040ce1ebrianosman
12686ceeebd37a43d879c120b6ba100ae1febdd67a18reedbool SkCanvas::peekPixels(SkPixmap* pmap) {
12696ceeebd37a43d879c120b6ba100ae1febdd67a18reed    return this->onPeekPixels(pmap);
1270c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1271c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
1272884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onPeekPixels(SkPixmap* pmap) {
1273c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org    SkBaseDevice* dev = this->getDevice();
1274884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->peekPixels(pmap);
1275c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org}
1276c3bd8af6d5722e854feca70c40d92f4954c5b67bcommit-bot@chromium.org
12776b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.orgvoid* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
1278884e97cb04db7ed053a866567ee9c6e4c01f993areed    SkPixmap pmap;
1279884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (!this->onAccessTopLayerPixels(&pmap)) {
128096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
1281884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1282884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (info) {
1283884e97cb04db7ed053a866567ee9c6e4c01f993areed        *info = pmap.info();
1284884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1285884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (rowBytes) {
1286884e97cb04db7ed053a866567ee9c6e4c01f993areed        *rowBytes = pmap.rowBytes();
1287884e97cb04db7ed053a866567ee9c6e4c01f993areed    }
1288884e97cb04db7ed053a866567ee9c6e4c01f993areed    if (origin) {
12890ed3b640c9da71fbbd73c65a4ec1992f85596271Florin Malita        *origin = this->getTopDevice()->getOrigin();
12906b4aaa77dcc4f17d0e22986f5f4cca70011d1ee5commit-bot@chromium.org    }
1291884e97cb04db7ed053a866567ee9c6e4c01f993areed    return pmap.writable_addr();
12929c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
12939c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1294884e97cb04db7ed053a866567ee9c6e4c01f993areedbool SkCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
12959c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
1296884e97cb04db7ed053a866567ee9c6e4c01f993areed    return dev && dev->accessPixels(pmap);
12979c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
12989c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1299520cf8b33e788268432c6314c52dfcef22e776aecommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////
13008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
130153f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malitavoid SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, const SkPaint* paint,
130253f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita                                  SkImage* clipImage, const SkMatrix& clipMatrix) {
13038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint tmp;
130496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
13058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &tmp;
13068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13074b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
13088926b169f6a0dfa4c2129a98ec2aee205f0c8527reed@google.com    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1309a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed
13108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
13111f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com        SkBaseDevice* dstDev = iter.fDevice;
131276dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        paint = &looper.paint();
131376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkImageFilter* filter = paint->getImageFilter();
131476dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
131553f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita        if (filter || clipImage) {
1316833dcf48844dd053ddf7ecea20e3e1c2b6b47e01Robert Phillips            sk_sp<SkSpecialImage> specialImage = srcDev->snapSpecial();
1317833dcf48844dd053ddf7ecea20e3e1c2b6b47e01Robert Phillips            if (specialImage) {
131853f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita                dstDev->drawSpecial(specialImage.get(), pos.x(), pos.y(), *paint,
131953f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita                                    clipImage, clipMatrix);
1320833dcf48844dd053ddf7ecea20e3e1c2b6b47e01Robert Phillips            }
132176dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        } else {
1322a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            dstDev->drawDevice(srcDev, pos.x(), pos.y(), *paint);
132376dd277b1fa021c42fc3acdd8d61e7dc05f9c267reed@google.com        }
13248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1325a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed
13264e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
13278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
132932704674f64cb6a14356dfebe060cd3484c06cc7reed/////////////////////////////////////////////////////////////////////////////
1330da420b976e61071cfe5de10556b4b23e519091d6reed
133192362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::translate(SkScalar dx, SkScalar dy) {
1332fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed    if (dx || dy) {
1333fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        this->checkForDeferredSave();
1334fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        fMCRec->fMatrix.preTranslate(dx,dy);
1335cbdf007bc2eb85056a1a5c75c088202becba2d16mtklein
1336fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        // Translate shouldn't affect the is-scale-translateness of the matrix.
1337fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
1338cbdf007bc2eb85056a1a5c75c088202becba2d16mtklein
1339c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed        FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
1340c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
1341fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed        this->didTranslate(dx,dy);
1342fe69b5037817fdf4e64e96ca8b2b50eae6ed4f2creed    }
13438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
134592362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::scale(SkScalar sx, SkScalar sy) {
1346d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1347d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setScale(sx, sy);
1348d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
13498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
135192362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::rotate(SkScalar degrees) {
1352d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1353d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setRotate(degrees);
1354d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
13558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13577438bfc0804d021aa92cdd5ea644994a4248f3dbbungemanvoid SkCanvas::rotate(SkScalar degrees, SkScalar px, SkScalar py) {
13587438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman    SkMatrix m;
13597438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman    m.setRotate(degrees, px, py);
13607438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman    this->concat(m);
13617438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman}
13627438bfc0804d021aa92cdd5ea644994a4248f3dbbungeman
136392362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::skew(SkScalar sx, SkScalar sy) {
1364d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    SkMatrix m;
1365d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    m.setSkew(sx, sy);
1366d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    this->concat(m);
136744c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
136844c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
136992362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkCanvas::concat(const SkMatrix& matrix) {
1370d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    if (matrix.isIdentity()) {
1371d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org        return;
1372d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org    }
1373d9ea09e1f29b303e6fa36079e99729d2951925b9commit-bot@chromium.org
13742ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
13751f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix.preConcat(matrix);
13769637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate();
13777627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
13787627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
13797627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
138044c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didConcat(matrix);
138144c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org}
138244c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org
13838c30a8196dd5903d2d23b4d0a5dc888e802bf698reedvoid SkCanvas::internalSetMatrix(const SkMatrix& matrix) {
13841f836ee096bb988adef4b9757b2629c7afeda36dreed    fMCRec->fMatrix = matrix;
13859da5a5a198e5dc9148f7f30a6089377590eee55bmsarett    fIsScaleTranslate = matrix.isScaleTranslate();
1386c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed
1387c42a1cdd1de7a3cf57a9a5fd7363f5fb660e97d0Mike Reed    FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
13888c30a8196dd5903d2d23b4d0a5dc888e802bf698reed}
13898c30a8196dd5903d2d23b4d0a5dc888e802bf698reed
13908c30a8196dd5903d2d23b4d0a5dc888e802bf698reedvoid SkCanvas::setMatrix(const SkMatrix& matrix) {
13918c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    this->checkForDeferredSave();
13928c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    this->internalSetMatrix(matrix);
139344c48d062f7996b5b46917e1b312a32ad101f326commit-bot@chromium.org    this->didSetMatrix(matrix);
13948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::resetMatrix() {
13978c30a8196dd5903d2d23b4d0a5dc888e802bf698reed    this->setMatrix(SkMatrix::I());
13988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
14018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1402c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::clipRect(const SkRect& rect, SkClipOp op, bool doAA) {
14032ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14048f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
14058f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRect(rect, op, edgeStyle);
14068f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
14078f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
1408c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
1409a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    const bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
14107627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
14117627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    FOR_EACH_TOP_DEVICE(device->clipRect(rect, op, isAA));
14127627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
1413c64eff55049b1192052b791549a32a03be1c43e3reed    AutoValidateClip avc(this);
1414a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    fMCRec->fRasterClip.op(rect, fMCRec->fMatrix, this->getTopLayerBounds(), (SkRegion::Op)op,
1415a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon                           isAA);
1416fbfa25802709139c2f14e304319c9541da65ca27msarett    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
14178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14195f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Ilievvoid SkCanvas::androidFramework_setDeviceClipRestriction(const SkIRect& rect) {
14205f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev    fClipRestrictionRect = rect;
1421d519d484949161df6d4b2ecadc282427cab532cfMike Reed    if (fClipRestrictionRect.isEmpty()) {
1422d519d484949161df6d4b2ecadc282427cab532cfMike Reed        // we notify the device, but we *dont* resolve deferred saves (since we're just
1423d519d484949161df6d4b2ecadc282427cab532cfMike Reed        // removing the restriction if the rect is empty. how I hate this api.
1424d519d484949161df6d4b2ecadc282427cab532cfMike Reed        FOR_EACH_TOP_DEVICE(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect));
1425d519d484949161df6d4b2ecadc282427cab532cfMike Reed    } else {
14265f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev        this->checkForDeferredSave();
1427d519d484949161df6d4b2ecadc282427cab532cfMike Reed        FOR_EACH_TOP_DEVICE(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect));
14285f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev        AutoValidateClip avc(this);
14295f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev        fMCRec->fRasterClip.op(fClipRestrictionRect, SkRegion::kIntersect_Op);
14305f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev        fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
14315f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev    }
14325f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev}
14335f1bb0a7c5186e797aa0f0d447a68fc3fbf3c2feStan Iliev
1434c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::clipRRect(const SkRRect& rrect, SkClipOp op, bool doAA) {
14352ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14368f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
14374ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
14388f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRect(rrect.getBounds(), op, edgeStyle);
14398f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    } else {
14408f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com        this->onClipRRect(rrect, op, edgeStyle);
14414ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
14428f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
144314e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
1444c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
1445a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    AutoValidateClip avc(this);
144614e50ae2a1b1cccdace599247b8c788b8db33ef4commit-bot@chromium.org
1447a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
14487627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
14497627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    FOR_EACH_TOP_DEVICE(device->clipRRect(rrect, op, isAA));
1450a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
1451a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    fMCRec->fRasterClip.op(rrect, fMCRec->fMatrix, this->getTopLayerBounds(), (SkRegion::Op)op,
1452a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon                           isAA);
1453a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
14544ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
14554ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
1456c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::clipPath(const SkPath& path, SkClipOp op, bool doAA) {
14572ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14588f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
145939f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips
146039f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips    if (!path.isInverseFillType() && fMCRec->fMatrix.rectStaysRect()) {
146139f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        SkRect r;
146239f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        if (path.isRect(&r)) {
146339f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            this->onClipRect(r, op, edgeStyle);
146439f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            return;
146539f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        }
146639f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        SkRRect rrect;
146739f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        if (path.isOval(&r)) {
146839f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            rrect.setOval(r);
146939f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            this->onClipRRect(rrect, op, edgeStyle);
147039f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            return;
147139f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        }
147239f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        if (path.isRRect(&rrect)) {
147339f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            this->onClipRRect(rrect, op, edgeStyle);
147439f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips            return;
147539f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips        }
14768f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    }
147739f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips
147839f0538178bcb182346fbbb1c746eb5a1c2925fdrobertphillips    this->onClipPath(path, op, edgeStyle);
14798f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
14808f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
1481c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
14825c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    AutoValidateClip avc(this);
14835c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1484a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
14857627fa51044e35dc21251f925b56f6dd6887df97Mike Reed
14867627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    FOR_EACH_TOP_DEVICE(device->clipPath(path, op, isAA));
14875c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1488a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    const SkPath* rasterClipPath = &path;
1489a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    const SkMatrix* matrix = &fMCRec->fMatrix;
1490a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon    fMCRec->fRasterClip.op(*rasterClipPath, *matrix, this->getTopLayerBounds(), (SkRegion::Op)op,
1491a3b45d4f7db953472df4f11ab1595964b65175f9Brian Salomon                           isAA);
1492fbfa25802709139c2f14e304319c9541da65ca27msarett    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
14938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1495c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::clipRegion(const SkRegion& rgn, SkClipOp op) {
14962ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    this->checkForDeferredSave();
14978f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com    this->onClipRegion(rgn, op);
14988f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com}
14998f90a892c5130d4d26b5588e1ff151d01a40688arobertphillips@google.com
1500c1f7774e8d327e3c98b4094c9c01d26e27013f71Mike Reedvoid SkCanvas::onClipRegion(const SkRegion& rgn, SkClipOp op) {
15017627fa51044e35dc21251f925b56f6dd6887df97Mike Reed    FOR_EACH_TOP_DEVICE(device->clipRegion(rgn, op));
150227d07f0acb85eea4062075dfbe9148ce12d92c66Mike Reed
1503a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    AutoValidateClip avc(this);
150427d07f0acb85eea4062075dfbe9148ce12d92c66Mike Reed
150573603f3c52ffd89fe9d035be827b566a0e7d3b79reed    fMCRec->fRasterClip.op(rgn, (SkRegion::Op)op);
1506fbfa25802709139c2f14e304319c9541da65ca27msarett    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
15078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1509819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#ifdef SK_DEBUG
1510819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.comvoid SkCanvas::validateClip() const {
1511819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com    // construct clipRgn from the clipstack
15121f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    const SkBaseDevice* device = this->getDevice();
1513ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    if (!device) {
15145c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org        SkASSERT(this->isClipEmpty());
1515ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com        return;
1516ccfee2a3620e32053b4bf635f0e31e31018dcd96djsollen@google.com    }
1517819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com}
1518819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com#endif
1519819c921b0445fa9f45f18d4a560603cd9fde6ba4reed@google.com
1520a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedbool SkCanvas::androidFramework_isClipAA() const {
1521a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    bool containsAA = false;
1522a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
1523a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    FOR_EACH_TOP_DEVICE(containsAA |= device->onClipIsAA());
1524a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
1525a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    return containsAA;
1526a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed}
1527a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
1528a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedclass RgnAccumulator {
1529a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    SkRegion* fRgn;
1530a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedpublic:
1531a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    RgnAccumulator(SkRegion* total) : fRgn(total) {}
1532a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    void accumulate(SkBaseDevice* device, SkRegion* rgn) {
1533a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        SkIPoint origin = device->getOrigin();
1534a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        if (origin.x() | origin.y()) {
1535a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            rgn->translate(origin.x(), origin.y());
1536a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        }
1537a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        fRgn->op(*rgn, SkRegion::kUnion_Op);
1538a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    }
1539a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed};
1540a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
1541a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedvoid SkCanvas::temporary_internal_getRgnClip(SkRegion* rgn) {
1542a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    RgnAccumulator accum(rgn);
1543a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    SkRegion tmp;
1544a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
1545a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    rgn->setEmpty();
1546a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    FOR_EACH_TOP_DEVICE(device->onAsRgnClip(&tmp); accum.accumulate(device, &tmp));
154790c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com}
154890c07ea1d0aa6b7f20252c43fe23ee5ddc1d23cbreed@google.com
15495c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com///////////////////////////////////////////////////////////////////////////////
15505c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
1551754de5f65b466f721d952a379194cc94de376f42reed@google.combool SkCanvas::isClipEmpty() const {
155202be3c1c3f53858263df82b1db466b5bb7059ab0Mike Reed    return fMCRec->fRasterClip.isEmpty();
155302be3c1c3f53858263df82b1db466b5bb7059ab0Mike Reed
155402be3c1c3f53858263df82b1db466b5bb7059ab0Mike Reed    // TODO: should we only use the conservative answer in a recording canvas?
155502be3c1c3f53858263df82b1db466b5bb7059ab0Mike Reed#if 0
1556a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    SkBaseDevice* dev = this->getTopDevice();
1557a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    // if no device we return true
1558a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    return !dev || dev->onGetClipType() == SkBaseDevice::kEmpty_ClipType;
155902be3c1c3f53858263df82b1db466b5bb7059ab0Mike Reed#endif
1560754de5f65b466f721d952a379194cc94de376f42reed@google.com}
1561754de5f65b466f721d952a379194cc94de376f42reed@google.com
15625c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.orgbool SkCanvas::isClipRect() const {
1563a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    SkBaseDevice* dev = this->getTopDevice();
1564a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    // if no device we return false
1565a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    return dev && dev->onGetClipType() == SkBaseDevice::kRect_ClipType;
15665c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org}
15675c70cdca5efe541b70d010e91607bf8626ea49cacommit-bot@chromium.org
1568fbfa25802709139c2f14e304319c9541da65ca27msarettstatic inline bool is_nan_or_clipped(const Sk4f& devRect, const Sk4f& devClip) {
1569fbfa25802709139c2f14e304319c9541da65ca27msarett#if !defined(SKNX_NO_SIMD) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
1570fbfa25802709139c2f14e304319c9541da65ca27msarett    __m128 lLtT = _mm_unpacklo_ps(devRect.fVec, devClip.fVec);
1571fbfa25802709139c2f14e304319c9541da65ca27msarett    __m128 RrBb = _mm_unpackhi_ps(devClip.fVec, devRect.fVec);
1572fbfa25802709139c2f14e304319c9541da65ca27msarett    __m128 mask = _mm_cmplt_ps(lLtT, RrBb);
1573fbfa25802709139c2f14e304319c9541da65ca27msarett    return 0xF != _mm_movemask_ps(mask);
1574fbfa25802709139c2f14e304319c9541da65ca27msarett#elif !defined(SKNX_NO_SIMD) && defined(SK_ARM_HAS_NEON)
1575fbfa25802709139c2f14e304319c9541da65ca27msarett    float32x4_t lLtT = vzipq_f32(devRect.fVec, devClip.fVec).val[0];
1576fbfa25802709139c2f14e304319c9541da65ca27msarett    float32x4_t RrBb = vzipq_f32(devClip.fVec, devRect.fVec).val[1];
1577fbfa25802709139c2f14e304319c9541da65ca27msarett    uint32x4_t mask = vcltq_f32(lLtT, RrBb);
1578fbfa25802709139c2f14e304319c9541da65ca27msarett    return 0xFFFFFFFFFFFFFFFF != (uint64_t) vmovn_u32(mask);
1579fbfa25802709139c2f14e304319c9541da65ca27msarett#else
1580fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect devRectAsRect;
1581fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect devClipAsRect;
1582fbfa25802709139c2f14e304319c9541da65ca27msarett    devRect.store(&devRectAsRect.fLeft);
1583fbfa25802709139c2f14e304319c9541da65ca27msarett    devClip.store(&devClipAsRect.fLeft);
1584fbfa25802709139c2f14e304319c9541da65ca27msarett    return !devRectAsRect.isFinite() || !devRectAsRect.intersect(devClipAsRect);
1585fbfa25802709139c2f14e304319c9541da65ca27msarett#endif
1586fbfa25802709139c2f14e304319c9541da65ca27msarett}
1587fbfa25802709139c2f14e304319c9541da65ca27msarett
1588fbfa25802709139c2f14e304319c9541da65ca27msarett// It's important for this function to not be inlined.  Otherwise the compiler will share code
1589fbfa25802709139c2f14e304319c9541da65ca27msarett// between the fast path and the slow path, resulting in two slow paths.
1590fbfa25802709139c2f14e304319c9541da65ca27msarettstatic SK_NEVER_INLINE bool quick_reject_slow_path(const SkRect& src, const SkRect& deviceClip,
1591fbfa25802709139c2f14e304319c9541da65ca27msarett                                                   const SkMatrix& matrix) {
1592fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect deviceRect;
1593fbfa25802709139c2f14e304319c9541da65ca27msarett    matrix.mapRect(&deviceRect, src);
1594fbfa25802709139c2f14e304319c9541da65ca27msarett    return !deviceRect.isFinite() || !deviceRect.intersect(deviceClip);
1595fbfa25802709139c2f14e304319c9541da65ca27msarett}
1596d22a817ff57986407facd16af36320fc86ce02damsarett
1597fbfa25802709139c2f14e304319c9541da65ca27msarettbool SkCanvas::quickReject(const SkRect& src) const {
1598fbfa25802709139c2f14e304319c9541da65ca27msarett#ifdef SK_DEBUG
1599fbfa25802709139c2f14e304319c9541da65ca27msarett    // Verify that fDeviceClipBounds are set properly.
1600fbfa25802709139c2f14e304319c9541da65ca27msarett    SkRect tmp = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
16011f836ee096bb988adef4b9757b2629c7afeda36dreed    if (fMCRec->fRasterClip.isEmpty()) {
16020c685ee188a5e500df25a34fa6edfceb4cbb795cmsarett        SkASSERT(fDeviceClipBounds.isEmpty());
1603fbfa25802709139c2f14e304319c9541da65ca27msarett    } else {
1604fbfa25802709139c2f14e304319c9541da65ca27msarett        SkASSERT(tmp == fDeviceClipBounds);
16058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16079637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    // Verify that fIsScaleTranslate is set properly.
16089637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
1609fbfa25802709139c2f14e304319c9541da65ca27msarett#endif
1610d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
16119637ea91b88ff8f8e95325bfc41417ffc4d5ee0bmsarett    if (!fIsScaleTranslate) {
1612fbfa25802709139c2f14e304319c9541da65ca27msarett        return quick_reject_slow_path(src, fDeviceClipBounds, fMCRec->fMatrix);
16138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1614fbfa25802709139c2f14e304319c9541da65ca27msarett
1615fbfa25802709139c2f14e304319c9541da65ca27msarett    // We inline the implementation of mapScaleTranslate() for the fast path.
1616fbfa25802709139c2f14e304319c9541da65ca27msarett    float sx = fMCRec->fMatrix.getScaleX();
1617fbfa25802709139c2f14e304319c9541da65ca27msarett    float sy = fMCRec->fMatrix.getScaleY();
1618fbfa25802709139c2f14e304319c9541da65ca27msarett    float tx = fMCRec->fMatrix.getTranslateX();
1619fbfa25802709139c2f14e304319c9541da65ca27msarett    float ty = fMCRec->fMatrix.getTranslateY();
1620fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f scale(sx, sy, sx, sy);
1621fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f trans(tx, ty, tx, ty);
1622fbfa25802709139c2f14e304319c9541da65ca27msarett
1623fbfa25802709139c2f14e304319c9541da65ca27msarett    // Apply matrix.
1624fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f ltrb = Sk4f::Load(&src.fLeft) * scale + trans;
1625fbfa25802709139c2f14e304319c9541da65ca27msarett
1626fbfa25802709139c2f14e304319c9541da65ca27msarett    // Make sure left < right, top < bottom.
1627fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f rblt(ltrb[2], ltrb[3], ltrb[0], ltrb[1]);
1628fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f min = Sk4f::Min(ltrb, rblt);
1629fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f max = Sk4f::Max(ltrb, rblt);
1630fbfa25802709139c2f14e304319c9541da65ca27msarett    // We can extract either pair [0,1] or [2,3] from min and max and be correct, but on
1631fbfa25802709139c2f14e304319c9541da65ca27msarett    // ARM this sequence generates the fastest (a single instruction).
1632fbfa25802709139c2f14e304319c9541da65ca27msarett    Sk4f devRect = Sk4f(min[2], min[3], max[0], max[1]);
1633fbfa25802709139c2f14e304319c9541da65ca27msarett
1634fbfa25802709139c2f14e304319c9541da65ca27msarett    // Check if the device rect is NaN or outside the clip.
1635fbfa25802709139c2f14e304319c9541da65ca27msarett    return is_nan_or_clipped(devRect, Sk4f::Load(&fDeviceClipBounds.fLeft));
16368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16383b3e895df6f8ee0f33010367c215944cd16a8334reed@google.combool SkCanvas::quickReject(const SkPath& path) const {
16393b3e895df6f8ee0f33010367c215944cd16a8334reed@google.com    return path.isEmpty() || this->quickReject(path.getBounds());
16408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
164242e8c53b3ef58f887a623b410d9783b4d4ab4921Mike ReedSkRect SkCanvas::onGetLocalClipBounds() const {
164342e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    SkIRect ibounds = this->onGetDeviceClipBounds();
1644918e144408ba218df919528f8b48c544f4767883Mike Reed    if (ibounds.isEmpty()) {
164542e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed        return SkRect::MakeEmpty();
16468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1648d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    SkMatrix inverse;
1649d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    // if we can't invert the CTM, we can't return local clip bounds
16501f836ee096bb988adef4b9757b2629c7afeda36dreed    if (!fMCRec->fMatrix.invert(&inverse)) {
165142e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed        return SkRect::MakeEmpty();
1652d9c0f0b57affec7a472879c5919acac6637d926areed@android.com    }
1653d9c0f0b57affec7a472879c5919acac6637d926areed@android.com
165442e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    SkRect bounds;
165542e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    SkRect r;
165642e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    // adjust it outwards in case we are antialiasing
165742e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    const int inset = 1;
1658fa4d5bd09f8f1a4a92b5ae0324800dd672760898reed@google.com
165942e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
166042e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed           ibounds.fRight + inset, ibounds.fBottom + inset);
166142e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    inverse.mapRect(&bounds, r);
166242e8c53b3ef58f887a623b410d9783b4d4ab4921Mike Reed    return bounds;
16638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
166542e8c53b3ef58f887a623b410d9783b4d4ab4921Mike ReedSkIRect SkCanvas::onGetDeviceClipBounds() const {
1666a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    return fMCRec->fRasterClip.getBounds();
1667bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com}
1668bcb671c82a7341253864cda3a5c46d396402d7fbtomhudson@google.com
16698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::getTotalMatrix() const {
16701f836ee096bb988adef4b9757b2629c7afeda36dreed    return fMCRec->fMatrix;
16718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16731105224f9701e57ec5ce0354d6a380b664f5c638Brian OsmanGrRenderTargetContext* SkCanvas::internal_private_accessTopLayerRenderTargetContext() {
16749c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com    SkBaseDevice* dev = this->getTopDevice();
16751105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman    return dev ? dev->accessRenderTargetContext() : nullptr;
16769c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com}
16779c135db83d198e7d8200027c7d2cf60f38517ee3reed@google.com
1678644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.orgGrContext* SkCanvas::getGrContext() {
1679644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org    SkBaseDevice* device = this->getTopDevice();
168086ae3d161412961c27a406465b0ec5749cc2e753reed    return device ? device->context() : nullptr;
1681644629c1c7913a43ced172b98d56e0f471bc348bcommit-bot@chromium.org}
1682e97f0856a8044866b12527819d14cdfbcdfd96f2bsalomon@google.com
1683ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.orgvoid SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1684ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org                          const SkPaint& paint) {
16859881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()");
1686ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (outer.isEmpty()) {
1687ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1688ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1689ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (inner.isEmpty()) {
1690ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        this->drawRRect(outer, paint);
1691ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org        return;
1692ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
1693ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1694ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // We don't have this method (yet), but technically this is what we should
1695e0b728726d3b44bf18219b8c5bc5599332be7c34Cary Clark    // be able to return ...
1696e0b728726d3b44bf18219b8c5bc5599332be7c34Cary Clark    // if (!outer.contains(inner))) {
1697ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    //
1698ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    // For now at least check for containment of bounds
1699e0b728726d3b44bf18219b8c5bc5599332be7c34Cary Clark    if (!outer.getBounds().contains(inner.getBounds())) {
1700e0b728726d3b44bf18219b8c5bc5599332be7c34Cary Clark        return;
1701e0b728726d3b44bf18219b8c5bc5599332be7c34Cary Clark    }
1702ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
1703ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    this->onDrawDRRect(outer, inner, paint);
1704ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
1705ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org
170641af966ab338e95eee81ab618ab28195075338f7reed// These need to stop being virtual -- clients need to override the onDraw... versions
170741af966ab338e95eee81ab618ab28195075338f7reed
170841af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPaint(const SkPaint& paint) {
170941af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPaint(paint);
171041af966ab338e95eee81ab618ab28195075338f7reed}
171141af966ab338e95eee81ab618ab28195075338f7reed
171241af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
171341af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawRect(r, paint);
171441af966ab338e95eee81ab618ab28195075338f7reed}
171541af966ab338e95eee81ab618ab28195075338f7reed
1716dca352e2d42cfe698573947b3d11abc1eaade160msarettvoid SkCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
1717dca352e2d42cfe698573947b3d11abc1eaade160msarett    if (region.isEmpty()) {
1718dca352e2d42cfe698573947b3d11abc1eaade160msarett        return;
1719dca352e2d42cfe698573947b3d11abc1eaade160msarett    }
1720dca352e2d42cfe698573947b3d11abc1eaade160msarett
1721dca352e2d42cfe698573947b3d11abc1eaade160msarett    if (region.isRect()) {
1722dca352e2d42cfe698573947b3d11abc1eaade160msarett        return this->drawIRect(region.getBounds(), paint);
1723dca352e2d42cfe698573947b3d11abc1eaade160msarett    }
1724dca352e2d42cfe698573947b3d11abc1eaade160msarett
1725dca352e2d42cfe698573947b3d11abc1eaade160msarett    this->onDrawRegion(region, paint);
1726dca352e2d42cfe698573947b3d11abc1eaade160msarett}
1727dca352e2d42cfe698573947b3d11abc1eaade160msarett
172841af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) {
172941af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawOval(r, paint);
173041af966ab338e95eee81ab618ab28195075338f7reed}
173141af966ab338e95eee81ab618ab28195075338f7reed
173241af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
173341af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawRRect(rrect, paint);
173441af966ab338e95eee81ab618ab28195075338f7reed}
173541af966ab338e95eee81ab618ab28195075338f7reed
173641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
173741af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPoints(mode, count, pts, paint);
173841af966ab338e95eee81ab618ab28195075338f7reed}
173941af966ab338e95eee81ab618ab28195075338f7reed
1740e88a1cb20e6b4c9f099070112225a88693a4630bMike Reedvoid SkCanvas::drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode,
1741e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed                            const SkPaint& paint) {
1742e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    RETURN_ON_NULL(vertices);
1743e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    this->onDrawVerticesObject(vertices.get(), mode, paint);
1744e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed}
1745e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed
1746e88a1cb20e6b4c9f099070112225a88693a4630bMike Reedvoid SkCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) {
1747199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    RETURN_ON_NULL(vertices);
1748e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed    this->onDrawVerticesObject(vertices, mode, paint);
174941af966ab338e95eee81ab618ab28195075338f7reed}
175041af966ab338e95eee81ab618ab28195075338f7reed
175141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
175241af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawPath(path, paint);
175341af966ab338e95eee81ab618ab28195075338f7reed}
175441af966ab338e95eee81ab618ab28195075338f7reed
1755a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
1756e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
1757a85d4d0814818e4ddabb9237da209d61d6cd5854reed    this->onDrawImage(image, x, y, paint);
175841af966ab338e95eee81ab618ab28195075338f7reed}
175941af966ab338e95eee81ab618ab28195075338f7reed
1760e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
1761e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             const SkPaint* paint, SrcRectConstraint constraint) {
1762e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
1763e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (dst.isEmpty() || src.isEmpty()) {
1764e47829b6b1eeb6b0c97ccb3df3016d197046824creed        return;
1765e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
1766e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->onDrawImageRect(image, &src, dst, paint, constraint);
1767e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
176841af966ab338e95eee81ab618ab28195075338f7reed
176984984efeb64787b88c5f8bd6929cfe2d58a3ba06reedvoid SkCanvas::drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
177084984efeb64787b88c5f8bd6929cfe2d58a3ba06reed                             const SkPaint* paint, SrcRectConstraint constraint) {
1771e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
1772e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawImageRect(image, SkRect::Make(isrc), dst, paint, constraint);
177384984efeb64787b88c5f8bd6929cfe2d58a3ba06reed}
177484984efeb64787b88c5f8bd6929cfe2d58a3ba06reed
1775e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
1776e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             SrcRectConstraint constraint) {
1777e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
1778e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), dst, paint,
1779e47829b6b1eeb6b0c97ccb3df3016d197046824creed                        constraint);
1780e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1781e47829b6b1eeb6b0c97ccb3df3016d197046824creed
17824c21dc5ddf3b482293ed34eead876d8d61a662c3reedvoid SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
17834c21dc5ddf3b482293ed34eead876d8d61a662c3reed                             const SkPaint* paint) {
1784e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(image);
17854c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (dst.isEmpty()) {
17864c21dc5ddf3b482293ed34eead876d8d61a662c3reed        return;
17874c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
1788552bca9afadd81d263041d04e2605d8d897940b6msarett    if (SkLatticeIter::Valid(image->width(), image->height(), center)) {
1789552bca9afadd81d263041d04e2605d8d897940b6msarett        this->onDrawImageNine(image, center, dst, paint);
1790552bca9afadd81d263041d04e2605d8d897940b6msarett    } else {
1791e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, dst, paint);
17924c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
17934c21dc5ddf3b482293ed34eead876d8d61a662c3reed}
17944c21dc5ddf3b482293ed34eead876d8d61a662c3reed
1795168820625c35a8c19f66c661efcbce7a5e334837msarettvoid SkCanvas::drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
1796168820625c35a8c19f66c661efcbce7a5e334837msarett                                const SkPaint* paint) {
1797168820625c35a8c19f66c661efcbce7a5e334837msarett    RETURN_ON_NULL(image);
1798168820625c35a8c19f66c661efcbce7a5e334837msarett    if (dst.isEmpty()) {
1799168820625c35a8c19f66c661efcbce7a5e334837msarett        return;
1800168820625c35a8c19f66c661efcbce7a5e334837msarett    }
180171df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett
180271df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    SkIRect bounds;
180371df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    Lattice latticePlusBounds = lattice;
180471df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    if (!latticePlusBounds.fBounds) {
180571df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        bounds = SkIRect::MakeWH(image->width(), image->height());
180671df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        latticePlusBounds.fBounds = &bounds;
180771df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    }
180871df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett
180971df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    if (SkLatticeIter::Valid(image->width(), image->height(), latticePlusBounds)) {
181071df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        this->onDrawImageLattice(image, latticePlusBounds, dst, paint);
1811168820625c35a8c19f66c661efcbce7a5e334837msarett    } else {
1812168820625c35a8c19f66c661efcbce7a5e334837msarett        this->drawImageRect(image, dst, paint);
1813168820625c35a8c19f66c661efcbce7a5e334837msarett    }
1814168820625c35a8c19f66c661efcbce7a5e334837msarett}
1815168820625c35a8c19f66c661efcbce7a5e334837msarett
181641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
18174c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing()) {
18182df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
18192df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
182041af966ab338e95eee81ab618ab28195075338f7reed    this->onDrawBitmap(bitmap, dx, dy, paint);
182141af966ab338e95eee81ab618ab28195075338f7reed}
182241af966ab338e95eee81ab618ab28195075338f7reed
1823e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
1824a5517e2b190a8083b38964972b031c13e99f1012reed                              const SkPaint* paint, SrcRectConstraint constraint) {
1825e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (bitmap.drawsNothing() || dst.isEmpty() || src.isEmpty()) {
1826a5517e2b190a8083b38964972b031c13e99f1012reed        return;
1827a5517e2b190a8083b38964972b031c13e99f1012reed    }
1828e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->onDrawBitmapRect(bitmap, &src, dst, paint, constraint);
182941af966ab338e95eee81ab618ab28195075338f7reed}
183041af966ab338e95eee81ab618ab28195075338f7reed
183184984efeb64787b88c5f8bd6929cfe2d58a3ba06reedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
183284984efeb64787b88c5f8bd6929cfe2d58a3ba06reed                              const SkPaint* paint, SrcRectConstraint constraint) {
1833e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawBitmapRect(bitmap, SkRect::Make(isrc), dst, paint, constraint);
1834e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1835e47829b6b1eeb6b0c97ccb3df3016d197046824creed
1836e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
1837e47829b6b1eeb6b0c97ccb3df3016d197046824creed                              SrcRectConstraint constraint) {
1838e47829b6b1eeb6b0c97ccb3df3016d197046824creed    this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, paint,
1839e47829b6b1eeb6b0c97ccb3df3016d197046824creed                         constraint);
184084984efeb64787b88c5f8bd6929cfe2d58a3ba06reed}
184184984efeb64787b88c5f8bd6929cfe2d58a3ba06reed
184241af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
184341af966ab338e95eee81ab618ab28195075338f7reed                              const SkPaint* paint) {
18444c21dc5ddf3b482293ed34eead876d8d61a662c3reed    if (bitmap.drawsNothing() || dst.isEmpty()) {
18452df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson        return;
18462df6fd650cb12af8eeb7884b2819d2bf8ba7a5bftomhudson    }
1847552bca9afadd81d263041d04e2605d8d897940b6msarett    if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), center)) {
1848552bca9afadd81d263041d04e2605d8d897940b6msarett        this->onDrawBitmapNine(bitmap, center, dst, paint);
1849552bca9afadd81d263041d04e2605d8d897940b6msarett    } else {
1850a5517e2b190a8083b38964972b031c13e99f1012reed        this->drawBitmapRect(bitmap, dst, paint);
18514c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
185241af966ab338e95eee81ab618ab28195075338f7reed}
185341af966ab338e95eee81ab618ab28195075338f7reed
1854c573a40ed5024b463e47088d307e3164a486dba5msarettvoid SkCanvas::drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
1855c573a40ed5024b463e47088d307e3164a486dba5msarett                                 const SkPaint* paint) {
1856168820625c35a8c19f66c661efcbce7a5e334837msarett    if (bitmap.drawsNothing() || dst.isEmpty()) {
1857c573a40ed5024b463e47088d307e3164a486dba5msarett        return;
1858c573a40ed5024b463e47088d307e3164a486dba5msarett    }
185971df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett
186071df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    SkIRect bounds;
186171df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    Lattice latticePlusBounds = lattice;
186271df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    if (!latticePlusBounds.fBounds) {
186371df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        bounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
186471df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        latticePlusBounds.fBounds = &bounds;
186571df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    }
186671df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett
186771df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett    if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), latticePlusBounds)) {
186871df2d7bc1bbc83ad4cf005f9027df4cb3b88a9bmsarett        this->onDrawBitmapLattice(bitmap, latticePlusBounds, dst, paint);
1869552bca9afadd81d263041d04e2605d8d897940b6msarett    } else {
1870168820625c35a8c19f66c661efcbce7a5e334837msarett        this->drawBitmapRect(bitmap, dst, paint);
1871c573a40ed5024b463e47088d307e3164a486dba5msarett    }
1872c573a40ed5024b463e47088d307e3164a486dba5msarett}
1873c573a40ed5024b463e47088d307e3164a486dba5msarett
187471c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
18757d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                         const SkColor colors[], int count, SkBlendMode mode,
187671c3c760a83123ee0b3127b8c65c6394ce541c50reed                         const SkRect* cull, const SkPaint* paint) {
1877e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(atlas);
187871c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (count <= 0) {
187971c3c760a83123ee0b3127b8c65c6394ce541c50reed        return;
188071c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
1881c485907f0420e5f9cf8223e9ba53812cd8dd5368Joe Gregorio    SkASSERT(atlas);
188271c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkASSERT(tex);
1883faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed    this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
188471c3c760a83123ee0b3127b8c65c6394ce541c50reed}
188571c3c760a83123ee0b3127b8c65c6394ce541c50reed
1886f70b531daaf47db1ee95c70da9843f1dd1f418d3reedvoid SkCanvas::drawAnnotation(const SkRect& rect, const char key[], SkData* value) {
1887f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    if (key) {
1888f70b531daaf47db1ee95c70da9843f1dd1f418d3reed        this->onDrawAnnotation(rect, key, value);
1889f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    }
1890f70b531daaf47db1ee95c70da9843f1dd1f418d3reed}
1891f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
1892e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1893e47829b6b1eeb6b0c97ccb3df3016d197046824creed                                    const SkPaint* paint, SrcRectConstraint constraint) {
1894e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (src) {
1895e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, *src, dst, paint, constraint);
1896e47829b6b1eeb6b0c97ccb3df3016d197046824creed    } else {
1897e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()),
1898e47829b6b1eeb6b0c97ccb3df3016d197046824creed                            dst, paint, constraint);
1899e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
1900e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1901e47829b6b1eeb6b0c97ccb3df3016d197046824creedvoid SkCanvas::legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1902e47829b6b1eeb6b0c97ccb3df3016d197046824creed                                     const SkPaint* paint, SrcRectConstraint constraint) {
1903e47829b6b1eeb6b0c97ccb3df3016d197046824creed    if (src) {
1904e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawBitmapRect(bitmap, *src, dst, paint, constraint);
1905e47829b6b1eeb6b0c97ccb3df3016d197046824creed    } else {
1906e47829b6b1eeb6b0c97ccb3df3016d197046824creed        this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()),
1907e47829b6b1eeb6b0c97ccb3df3016d197046824creed                             dst, paint, constraint);
1908e47829b6b1eeb6b0c97ccb3df3016d197046824creed    }
1909e47829b6b1eeb6b0c97ccb3df3016d197046824creed}
1910e47829b6b1eeb6b0c97ccb3df3016d197046824creed
19118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
19128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  These are the virtual drawing methods
19138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
19148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
191528361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.orgvoid SkCanvas::onDiscard() {
191649f085dddff10473b6ebf832a974288300224e60bsalomon    if (fSurfaceBase) {
191728361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
191828361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    }
191928361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org}
192028361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org
192141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPaint(const SkPaint& paint) {
19229881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()");
1923fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    this->internalDrawPaint(paint);
1924fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com}
1925fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
1926fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.comvoid SkCanvas::internalDrawPaint(const SkPaint& paint) {
192796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, nullptr, false)
19288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
1930a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawPaint(looper.paint());
19318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19334e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
19348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
193641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
193741af966ab338e95eee81ab618ab28195075338f7reed                            const SkPaint& paint) {
19389881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count));
19398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if ((long)count <= 0) {
19408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
19418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1943822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    SkRect r;
194496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
1945a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com    if (paint.canComputeFastBounds()) {
1946a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        // special-case 2 points (common for drawing a single line)
1947a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        if (2 == count) {
1948a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com            r.set(pts[0], pts[1]);
1949a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        } else {
1950a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org            r.set(pts, SkToInt(count));
1951a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com        }
1952822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
195387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) {
195487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
195587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
195687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &r;
1957fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
1958a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com
195996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkASSERT(pts != nullptr);
19608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
196178cf11980d87700be0b3fded86a6d8f0d43f24d9senorblanco@chromium.org    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
19624b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
19638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
1964a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawPoints(mode, count, pts, looper.paint());
19658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19664b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
19674e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
19688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19704a16717bc7aa471fad10ec3157774771a76e5106reedstatic bool needs_autodrawlooper(SkCanvas* canvas, const SkPaint& paint) {
19714a16717bc7aa471fad10ec3157774771a76e5106reed    return ((intptr_t)paint.getImageFilter()    |
19724a16717bc7aa471fad10ec3157774771a76e5106reed#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
19734a16717bc7aa471fad10ec3157774771a76e5106reed            (intptr_t)canvas->getDrawFilter()   |
19744a16717bc7aa471fad10ec3157774771a76e5106reed#endif
19754a16717bc7aa471fad10ec3157774771a76e5106reed            (intptr_t)paint.getLooper()         ) != 0;
19764a16717bc7aa471fad10ec3157774771a76e5106reed}
19774a16717bc7aa471fad10ec3157774771a76e5106reed
197841af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
19799881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()");
19808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (paint.canComputeFastBounds()) {
19818432808ad8898ac7137bc7ce1d9df6005e866401reed        // Skia will draw an inverted rect, because it explicitly "sorts" it downstream.
19828432808ad8898ac7137bc7ce1d9df6005e866401reed        // To prevent accidental rejecting at this stage, we have to sort it before we check.
19838432808ad8898ac7137bc7ce1d9df6005e866401reed        SkRect tmp(r);
19848432808ad8898ac7137bc7ce1d9df6005e866401reed        tmp.sort();
19858432808ad8898ac7137bc7ce1d9df6005e866401reed
1986822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
198787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(tmp, &storage))) {
198887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
198987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
19908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19914b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
19924a16717bc7aa471fad10ec3157774771a76e5106reed    if (needs_autodrawlooper(this, paint)) {
1993822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, &r, false)
19948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19954a16717bc7aa471fad10ec3157774771a76e5106reed        while (iter.next()) {
1996a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->drawRect(r, looper.paint());
19974a16717bc7aa471fad10ec3157774771a76e5106reed        }
19988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19994a16717bc7aa471fad10ec3157774771a76e5106reed        LOOPER_END
20004a16717bc7aa471fad10ec3157774771a76e5106reed    } else {
2001822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        this->predrawNotify(&r, &paint, false);
20024a16717bc7aa471fad10ec3157774771a76e5106reed        SkDrawIter iter(this);
20034a16717bc7aa471fad10ec3157774771a76e5106reed        while (iter.next()) {
2004a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->drawRect(r, paint);
20054a16717bc7aa471fad10ec3157774771a76e5106reed        }
20064a16717bc7aa471fad10ec3157774771a76e5106reed    }
20078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
200944df651ebefc284acc2f66425dff3ea0b0e14b36msarettvoid SkCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
201044df651ebefc284acc2f66425dff3ea0b0e14b36msarett    SkRect regionRect = SkRect::Make(region.getBounds());
201144df651ebefc284acc2f66425dff3ea0b0e14b36msarett    if (paint.canComputeFastBounds()) {
2012822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
201344df651ebefc284acc2f66425dff3ea0b0e14b36msarett        if (this->quickReject(paint.computeFastBounds(regionRect, &storage))) {
201444df651ebefc284acc2f66425dff3ea0b0e14b36msarett            return;
201544df651ebefc284acc2f66425dff3ea0b0e14b36msarett        }
201644df651ebefc284acc2f66425dff3ea0b0e14b36msarett    }
201744df651ebefc284acc2f66425dff3ea0b0e14b36msarett
2018822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, &regionRect)
201944df651ebefc284acc2f66425dff3ea0b0e14b36msarett
202044df651ebefc284acc2f66425dff3ea0b0e14b36msarett    while (iter.next()) {
2021a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawRegion(region, looper.paint());
202244df651ebefc284acc2f66425dff3ea0b0e14b36msarett    }
202344df651ebefc284acc2f66425dff3ea0b0e14b36msarett
202444df651ebefc284acc2f66425dff3ea0b0e14b36msarett    LOOPER_END
202544df651ebefc284acc2f66425dff3ea0b0e14b36msarett}
202644df651ebefc284acc2f66425dff3ea0b0e14b36msarett
202741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
20289881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()");
20294ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
2030822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
203187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
203287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
203387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
20344ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
2035306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
2036822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
203746d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
203846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    while (iter.next()) {
2039a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawOval(oval, looper.paint());
204046d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    }
204146d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
204246d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    LOOPER_END
20434ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
20444ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
2045ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomonvoid SkCanvas::onDrawArc(const SkRect& oval, SkScalar startAngle,
2046ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon                         SkScalar sweepAngle, bool useCenter,
2047ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon                         const SkPaint& paint) {
2048ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
2049ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    if (paint.canComputeFastBounds()) {
2050ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        SkRect storage;
2051ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        // Note we're using the entire oval as the bounds.
2052ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
2053ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon            return;
2054ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon        }
2055ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    }
2056ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
2057822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
2058ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
2059ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    while (iter.next()) {
2060a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawArc(oval, startAngle, sweepAngle, useCenter, looper.paint());
2061ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    }
2062ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
2063ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon    LOOPER_END
2064ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon}
2065ac3aa245acc7b469aa2f0d0078e53401d78ac8b9bsalomon
206641af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
20679881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()");
20684ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (paint.canComputeFastBounds()) {
2069822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
207087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) {
207187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
207287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
20734ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
20744ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
20754ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    if (rrect.isRect()) {
20764ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
20774ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->SkCanvas::drawRect(rrect.getBounds(), paint);
2078f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
2079f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    } else if (rrect.isOval()) {
20804ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        // call the non-virtual version
2081f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        this->SkCanvas::drawOval(rrect.getBounds(), paint);
2082f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        return;
20834ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    }
2084f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2085822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &rrect.getBounds())
2086f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2087f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    while (iter.next()) {
2088a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawRRect(rrect, looper.paint());
2089f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    }
2090f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
2091f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    LOOPER_END
20924ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com}
20934ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
2094822128b475c1782788f96e7a1a848d0affb878b1Mike Reedvoid SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
2095ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    if (paint.canComputeFastBounds()) {
2096822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
209787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(outer.getBounds(), &storage))) {
209887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
209987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
2100ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
210125c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2102822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &outer.getBounds())
210325c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2104ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    while (iter.next()) {
2105a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawDRRect(outer, inner, looper.paint());
2106ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    }
210725c7127c904aa6e03209220e8ecb7128d3595f11skia.committer@gmail.com
2108ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org    LOOPER_END
2109ed9806f5c972513d4141c9d1b5a04ab78b3af4cbcommit-bot@chromium.org}
21104ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com
211141af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
21129881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()");
21139364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    if (!path.isFinite()) {
21149364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com        return;
21159364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com    }
21169364511bd17d7414efc5df3ee38faa78c6f89eb1reed@google.com
2117822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    const SkRect& pathBounds = path.getBounds();
2118fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
2119822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
212087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(pathBounds, &storage))) {
212187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
212287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
21238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21240b45dc45d67144421904555ccf53782cc8d9969dcommit-bot@chromium.org
2125822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    if (pathBounds.width() <= 0 && pathBounds.height() <= 0) {
21266803c219dd3be4a73e7bb5c4bb8a5b1f803624d0commit-bot@chromium.org        if (path.isInverseFillType()) {
2127fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com            this->internalDrawPaint(paint);
21286651a3238dd6affa4276ada42ab613abf1d42d1dcaryclark            return;
2129fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com        }
2130fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
21318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2132822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, &pathBounds)
21338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
2135a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawPath(path, looper.paint());
21368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21384e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
21398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2141262a71b7f95ce98ff3dd8dba845afbd724470903reedbool SkCanvas::canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint& paint) {
2142262a71b7f95ce98ff3dd8dba845afbd724470903reed    if (!paint.getImageFilter()) {
2143262a71b7f95ce98ff3dd8dba845afbd724470903reed        return false;
2144262a71b7f95ce98ff3dd8dba845afbd724470903reed    }
2145262a71b7f95ce98ff3dd8dba845afbd724470903reed
2146262a71b7f95ce98ff3dd8dba845afbd724470903reed    const SkMatrix& ctm = this->getTotalMatrix();
2147c7e211acd0c9201688de7ff0c9a2271c67440adffmalita    if (!SkTreatAsSprite(ctm, SkISize::Make(w, h), paint)) {
2148262a71b7f95ce98ff3dd8dba845afbd724470903reed        return false;
2149262a71b7f95ce98ff3dd8dba845afbd724470903reed    }
2150262a71b7f95ce98ff3dd8dba845afbd724470903reed
2151262a71b7f95ce98ff3dd8dba845afbd724470903reed    // Currently we can only use the filterSprite code if we are clipped to the bitmap's bounds.
2152262a71b7f95ce98ff3dd8dba845afbd724470903reed    // Once we can filter and the filter will return a result larger than itself, we should be
2153262a71b7f95ce98ff3dd8dba845afbd724470903reed    // able to remove this constraint.
2154262a71b7f95ce98ff3dd8dba845afbd724470903reed    // skbug.com/4526
2155262a71b7f95ce98ff3dd8dba845afbd724470903reed    //
2156262a71b7f95ce98ff3dd8dba845afbd724470903reed    SkPoint pt;
2157262a71b7f95ce98ff3dd8dba845afbd724470903reed    ctm.mapXY(x, y, &pt);
2158262a71b7f95ce98ff3dd8dba845afbd724470903reed    SkIRect ir = SkIRect::MakeXYWH(SkScalarRoundToInt(pt.x()), SkScalarRoundToInt(pt.y()), w, h);
2159262a71b7f95ce98ff3dd8dba845afbd724470903reed    return ir.contains(fMCRec->fRasterClip.getBounds());
2160262a71b7f95ce98ff3dd8dba845afbd724470903reed}
2161262a71b7f95ce98ff3dd8dba845afbd724470903reed
2162a85d4d0814818e4ddabb9237da209d61d6cd5854reedvoid SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
21639881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()");
2164a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkRect bounds = SkRect::MakeXYWH(x, y,
2165a85d4d0814818e4ddabb9237da209d61d6cd5854reed                                     SkIntToScalar(image->width()), SkIntToScalar(image->height()));
216696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
216787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        SkRect tmp = bounds;
216887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (paint) {
216987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            paint->computeFastBounds(tmp, &tmp);
217087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
217187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(tmp)) {
217287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
217387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
2174a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
21759d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2176a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
217796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
2178a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2179a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2180262a71b7f95ce98ff3dd8dba845afbd724470903reed
2181a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    sk_sp<SkSpecialImage> special;
2182129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    bool drawAsSprite = this->canDrawBitmapAsSprite(x, y, image->width(), image->height(),
2183129ed1cd6d792f3f6cf563aefa9756fc6308289dreed                                                    *paint);
2184129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    if (drawAsSprite && paint->getImageFilter()) {
2185a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        special = this->getDevice()->makeSpecial(image);
2186a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        if (!special) {
2187129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            drawAsSprite = false;
2188129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        }
2189129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    }
2190129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
2191262a71b7f95ce98ff3dd8dba845afbd724470903reed    LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
2192262a71b7f95ce98ff3dd8dba845afbd724470903reed
2193a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2194262a71b7f95ce98ff3dd8dba845afbd724470903reed        const SkPaint& pnt = looper.paint();
2195a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        if (special) {
2196a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed            SkPoint pt;
2197a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->ctm().mapXY(x, y, &pt);
2198a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->drawSpecial(special.get(),
2199a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed                                      SkScalarRoundToInt(pt.fX),
220053f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita                                      SkScalarRoundToInt(pt.fY), pnt,
220153f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita                                      nullptr, SkMatrix::I());
2202262a71b7f95ce98ff3dd8dba845afbd724470903reed        } else {
2203a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->drawImage(image, x, y, pnt);
2204262a71b7f95ce98ff3dd8dba845afbd724470903reed        }
2205a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
22069d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2207a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2208b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2209b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
221041af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
2211562fe4767cc73e08a4e039362bc0336aea66ecfbreed                               const SkPaint* paint, SrcRectConstraint constraint) {
22129881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
221396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2214c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage = dst;
221587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (paint) {
221687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            paint->computeFastBounds(dst, &storage);
221787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
221887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(storage)) {
221987e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
222087e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
2221a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
2222a85d4d0814818e4ddabb9237da209d61d6cd5854reed    SkLazyPaint lazy;
222396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
2224a85d4d0814818e4ddabb9237da209d61d6cd5854reed        paint = lazy.init();
2225a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
22269d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2227c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2228c83a29759a5c2966da5ab973e4fd90763e4c962breed                                          image->isOpaque())
22299d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2230a85d4d0814818e4ddabb9237da209d61d6cd5854reed    while (iter.next()) {
2231a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawImageRect(image, src, dst, looper.paint(), constraint);
2232a85d4d0814818e4ddabb9237da209d61d6cd5854reed    }
22339d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2234a85d4d0814818e4ddabb9237da209d61d6cd5854reed    LOOPER_END
2235b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr}
2236b5fae93d72c7b6480f83fd8a7b534cd1fdfcd49apiotaixr
223741af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
22389881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()");
22398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(bitmap.validate();)
22408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
224133366974d43eae80e22284a2e445225c343859dareed    if (bitmap.drawsNothing()) {
224233366974d43eae80e22284a2e445225c343859dareed        return;
224333366974d43eae80e22284a2e445225c343859dareed    }
224433366974d43eae80e22284a2e445225c343859dareed
224533366974d43eae80e22284a2e445225c343859dareed    SkLazyPaint lazy;
224633366974d43eae80e22284a2e445225c343859dareed    if (nullptr == paint) {
224733366974d43eae80e22284a2e445225c343859dareed        paint = lazy.init();
224833366974d43eae80e22284a2e445225c343859dareed    }
224933366974d43eae80e22284a2e445225c343859dareed
2250822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    SkRect bounds;
2251822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    bitmap.getBounds(&bounds);
2252822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    bounds.offset(x, y);
2253822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    bool canFastBounds = paint->canComputeFastBounds();
2254822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    if (canFastBounds) {
2255822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        SkRect storage;
2256822128b475c1782788f96e7a1a848d0affb878b1Mike Reed        if (this->quickReject(paint->computeFastBounds(bounds, &storage))) {
225787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
225887e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
22598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22604b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
2261a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed    sk_sp<SkSpecialImage> special;
2262822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    bool drawAsSprite = canFastBounds && this->canDrawBitmapAsSprite(x, y, bitmap.width(),
2263822128b475c1782788f96e7a1a848d0affb878b1Mike Reed                                                                     bitmap.height(), *paint);
2264129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    if (drawAsSprite && paint->getImageFilter()) {
2265a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        special = this->getDevice()->makeSpecial(bitmap);
2266a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        if (!special) {
2267129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            drawAsSprite = false;
2268129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        }
2269129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    }
2270129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
2271822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    const SkMatrix matrix = SkMatrix::MakeTrans(x, y);
2272822128b475c1782788f96e7a1a848d0affb878b1Mike Reed
2273822128b475c1782788f96e7a1a848d0affb878b1Mike Reed    LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
227433366974d43eae80e22284a2e445225c343859dareed
227533366974d43eae80e22284a2e445225c343859dareed    while (iter.next()) {
2276262a71b7f95ce98ff3dd8dba845afbd724470903reed        const SkPaint& pnt = looper.paint();
2277a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed        if (special) {
2278262a71b7f95ce98ff3dd8dba845afbd724470903reed            SkPoint pt;
2279a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->ctm().mapXY(x, y, &pt);
2280a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->drawSpecial(special.get(),
2281a2217ef965e57fdbbf989989e7ec1f2c04f62d39reed                                      SkScalarRoundToInt(pt.fX),
228253f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita                                      SkScalarRoundToInt(pt.fY), pnt,
228353f77bd4fdd76525b66b7f26d1c5c550858120dfFlorin Malita                                      nullptr, SkMatrix::I());
2284262a71b7f95ce98ff3dd8dba845afbd724470903reed        } else {
2285a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed            iter.fDevice->drawBitmap(bitmap, matrix, looper.paint());
2286262a71b7f95ce98ff3dd8dba845afbd724470903reed        }
228733366974d43eae80e22284a2e445225c343859dareed    }
2288fbfa25802709139c2f14e304319c9541da65ca27msarett
228933366974d43eae80e22284a2e445225c343859dareed    LOOPER_END
22908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22929987ec3791336bad6af5cbe513564786b2df55aareed@google.com// this one is non-virtual, so it can be called safely by other canvas apis
22937112173c3c4cd1b1e7da8cdf971d71f01dd91299reed@google.comvoid SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2294eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                      const SkRect& dst, const SkPaint* paint,
2295a5517e2b190a8083b38964972b031c13e99f1012reed                                      SrcRectConstraint constraint) {
229650b393a768c0311b3210f723325fd27bf161136bcommit-bot@chromium.org    if (bitmap.drawsNothing() || dst.isEmpty()) {
22978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
22988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
229974b461961607fa57a150a9282c410ef0cab38764vandebo@chromium.org
230096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2301c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage;
230287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
230387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
230487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
23058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23063d60812865bb034851da777a91413ab584929887reed@google.com
230733535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    SkLazyPaint lazy;
230896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
230933535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com        paint = lazy.init();
23108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23117064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
2312c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2313c83a29759a5c2966da5ab973e4fd90763e4c962breed                                          bitmap.isOpaque())
23147064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
231533535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    while (iter.next()) {
2316a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawBitmapRect(bitmap, src, dst, looper.paint(), constraint);
2317f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
23187064e9a3fc2fe54856d66ede84eddee2cace01b9skia.committer@gmail.com
231933535f3c48bf723c46f334a93d4a06d782dad30ereed@google.com    LOOPER_END
23208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
232241af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
2323562fe4767cc73e08a4e039362bc0336aea66ecfbreed                                const SkPaint* paint, SrcRectConstraint constraint) {
23249881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()");
23259987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
2326562fe4767cc73e08a4e039362bc0336aea66ecfbreed    this->internalDrawBitmapRect(bitmap, src, dst, paint, constraint);
23279987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
23289987ec3791336bad6af5cbe513564786b2df55aareed@google.com
23294c21dc5ddf3b482293ed34eead876d8d61a662c3reedvoid SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
23304c21dc5ddf3b482293ed34eead876d8d61a662c3reed                               const SkPaint* paint) {
23314c21dc5ddf3b482293ed34eead876d8d61a662c3reed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageNine()");
23329d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
233396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2334c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage;
233587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
233687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
233787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
23383d60812865bb034851da777a91413ab584929887reed@google.com    }
23399d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
23404c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkLazyPaint lazy;
234196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
23424c21dc5ddf3b482293ed34eead876d8d61a662c3reed        paint = lazy.init();
23434c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
23449d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2345c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
23469d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
23474c21dc5ddf3b482293ed34eead876d8d61a662c3reed    while (iter.next()) {
2348a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawImageNine(image, center, dst, looper.paint());
23499987ec3791336bad6af5cbe513564786b2df55aareed@google.com    }
23509d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
23514c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_END
23529987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
23539987ec3791336bad6af5cbe513564786b2df55aareed@google.com
235441af966ab338e95eee81ab618ab28195075338f7reedvoid SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
235541af966ab338e95eee81ab618ab28195075338f7reed                                const SkPaint* paint) {
23569881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()");
23579987ec3791336bad6af5cbe513564786b2df55aareed@google.com    SkDEBUGCODE(bitmap.validate();)
23589987ec3791336bad6af5cbe513564786b2df55aareed@google.com
235996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint || paint->canComputeFastBounds()) {
2360c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco        SkRect storage;
236187e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
236287e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
236387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
23644c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
23659d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
23664c21dc5ddf3b482293ed34eead876d8d61a662c3reed    SkLazyPaint lazy;
236796fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
23684c21dc5ddf3b482293ed34eead876d8d61a662c3reed        paint = lazy.init();
23694c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
23709d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
2371c41e7e14f4a0076d277870502168ed870e558dfcsenorblanco    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
23729d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
23734c21dc5ddf3b482293ed34eead876d8d61a662c3reed    while (iter.next()) {
2374a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawBitmapNine(bitmap, center, dst, looper.paint());
23754c21dc5ddf3b482293ed34eead876d8d61a662c3reed    }
23769d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
23774c21dc5ddf3b482293ed34eead876d8d61a662c3reed    LOOPER_END
23789987ec3791336bad6af5cbe513564786b2df55aareed@google.com}
23799987ec3791336bad6af5cbe513564786b2df55aareed@google.com
2380168820625c35a8c19f66c661efcbce7a5e334837msarettvoid SkCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
2381168820625c35a8c19f66c661efcbce7a5e334837msarett                                  const SkPaint* paint) {
2382168820625c35a8c19f66c661efcbce7a5e334837msarett    if (nullptr == paint || paint->canComputeFastBounds()) {
2383168820625c35a8c19f66c661efcbce7a5e334837msarett        SkRect storage;
2384168820625c35a8c19f66c661efcbce7a5e334837msarett        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2385168820625c35a8c19f66c661efcbce7a5e334837msarett            return;
2386168820625c35a8c19f66c661efcbce7a5e334837msarett        }
2387168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2388168820625c35a8c19f66c661efcbce7a5e334837msarett
2389168820625c35a8c19f66c661efcbce7a5e334837msarett    SkLazyPaint lazy;
2390168820625c35a8c19f66c661efcbce7a5e334837msarett    if (nullptr == paint) {
2391168820625c35a8c19f66c661efcbce7a5e334837msarett        paint = lazy.init();
2392168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2393168820625c35a8c19f66c661efcbce7a5e334837msarett
2394168820625c35a8c19f66c661efcbce7a5e334837msarett    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2395168820625c35a8c19f66c661efcbce7a5e334837msarett
2396168820625c35a8c19f66c661efcbce7a5e334837msarett    while (iter.next()) {
2397a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawImageLattice(image, lattice, dst, looper.paint());
2398168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2399168820625c35a8c19f66c661efcbce7a5e334837msarett
2400168820625c35a8c19f66c661efcbce7a5e334837msarett    LOOPER_END
2401168820625c35a8c19f66c661efcbce7a5e334837msarett}
2402168820625c35a8c19f66c661efcbce7a5e334837msarett
2403168820625c35a8c19f66c661efcbce7a5e334837msarettvoid SkCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
2404168820625c35a8c19f66c661efcbce7a5e334837msarett                                   const SkRect& dst, const SkPaint* paint) {
2405168820625c35a8c19f66c661efcbce7a5e334837msarett    if (nullptr == paint || paint->canComputeFastBounds()) {
2406168820625c35a8c19f66c661efcbce7a5e334837msarett        SkRect storage;
2407168820625c35a8c19f66c661efcbce7a5e334837msarett        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2408168820625c35a8c19f66c661efcbce7a5e334837msarett            return;
2409168820625c35a8c19f66c661efcbce7a5e334837msarett        }
2410168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2411168820625c35a8c19f66c661efcbce7a5e334837msarett
2412168820625c35a8c19f66c661efcbce7a5e334837msarett    SkLazyPaint lazy;
2413168820625c35a8c19f66c661efcbce7a5e334837msarett    if (nullptr == paint) {
2414168820625c35a8c19f66c661efcbce7a5e334837msarett        paint = lazy.init();
2415168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2416168820625c35a8c19f66c661efcbce7a5e334837msarett
2417168820625c35a8c19f66c661efcbce7a5e334837msarett    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2418168820625c35a8c19f66c661efcbce7a5e334837msarett
2419168820625c35a8c19f66c661efcbce7a5e334837msarett    while (iter.next()) {
2420a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawBitmapLattice(bitmap, lattice, dst, looper.paint());
2421168820625c35a8c19f66c661efcbce7a5e334837msarett    }
2422168820625c35a8c19f66c661efcbce7a5e334837msarett
2423168820625c35a8c19f66c661efcbce7a5e334837msarett    LOOPER_END
2424168820625c35a8c19f66c661efcbce7a5e334837msarett}
2425168820625c35a8c19f66c661efcbce7a5e334837msarett
2426f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comclass SkDeviceFilteredPaint {
2427f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.compublic:
24281f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2429112e7e277702e104357f2d44742253ee1b0109acfmalita        uint32_t filteredFlags = device->filterTextFlags(paint);
2430112e7e277702e104357f2d44742253ee1b0109acfmalita        if (filteredFlags != paint.getFlags()) {
2431a076e9be17654a60310e72c4f70fcd5337f56dbfreed@google.com            SkPaint* newPaint = fLazy.set(paint);
2432112e7e277702e104357f2d44742253ee1b0109acfmalita            newPaint->setFlags(filteredFlags);
2433f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = newPaint;
2434f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        } else {
2435f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com            fPaint = &paint;
2436f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        }
2437f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    }
2438f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2439f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com    const SkPaint& paint() const { return *fPaint; }
2440f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2441f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.comprivate:
24422c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    const SkPaint*  fPaint;
24432c8fc5a7038cdfbb28a8364fd0057f3c21f90bfdmike@reedtribe.org    SkLazyPaint     fLazy;
2444f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com};
2445f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com
2446e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2447e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                          const SkPaint& paint) {
244896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
24498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24514e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2452a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawText(text, byteLength, x, y, dfp.paint());
24538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
24548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24554e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
24568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2458e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2459e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                             const SkPaint& paint) {
246005c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, 0);
246105c4a4322e7d4f3417b7df33825bab8603d52051fmalita
246296fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
246387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
24648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24654e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2466a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawPosText(text, byteLength, &pos->fX, 2, textOffset,
2467f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
24688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2469b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
24704e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
24718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2473e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2474e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              SkScalar constY, const SkPaint& paint) {
247505c4a4322e7d4f3417b7df33825bab8603d52051fmalita
247605c4a4322e7d4f3417b7df33825bab8603d52051fmalita    SkPoint textOffset = SkPoint::Make(0, constY);
247705c4a4322e7d4f3417b7df33825bab8603d52051fmalita
247896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
247987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
24808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
24814e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2482a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawPosText(text, byteLength, xpos, 1, textOffset,
2483f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com                                  dfp.paint());
24848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2485b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
24864e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com    LOOPER_END
24878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2489e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2490e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                                const SkMatrix* matrix, const SkPaint& paint) {
249196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
249287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
24938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (iter.next()) {
2494a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawTextOnPath(text, byteLength, path,
24954e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com                                     matrix, looper.paint());
24968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2497b0430d024572b1a5e5d7b80e406c668e975e3030skia.committer@gmail.com
2498945ec3a2bec668ca845071a65df8ec55e8f43819commit-bot@chromium.org    LOOPER_END
24994325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org}
25004325d114a5679e46f25ae75b0e43547fd7694998commit-bot@chromium.org
250145561a0b15fe045ba272c328684c3f7ae290785areedvoid SkCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
250245561a0b15fe045ba272c328684c3f7ae290785areed                                 const SkRect* cullRect, const SkPaint& paint) {
250345561a0b15fe045ba272c328684c3f7ae290785areed    if (cullRect && this->quickReject(*cullRect)) {
250445561a0b15fe045ba272c328684c3f7ae290785areed        return;
250545561a0b15fe045ba272c328684c3f7ae290785areed    }
250645561a0b15fe045ba272c328684c3f7ae290785areed
250745561a0b15fe045ba272c328684c3f7ae290785areed    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
250845561a0b15fe045ba272c328684c3f7ae290785areed
250945561a0b15fe045ba272c328684c3f7ae290785areed    while (iter.next()) {
2510a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawTextRSXform(text, byteLength, xform, looper.paint());
251145561a0b15fe045ba272c328684c3f7ae290785areed    }
251245561a0b15fe045ba272c328684c3f7ae290785areed
251345561a0b15fe045ba272c328684c3f7ae290785areed    LOOPER_END
251445561a0b15fe045ba272c328684c3f7ae290785areed}
251545561a0b15fe045ba272c328684c3f7ae290785areed
251600d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
251700d5c2c6523321d25b32905ff4822f083a4173eefmalita                              const SkPaint& paint) {
25187ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
251985d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    SkRect storage;
252096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    const SkRect* bounds = nullptr;
252119653d1d004610b4ba07ce563a5701164e120e45fmalita    if (paint.canComputeFastBounds()) {
252285d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita        storage = blob->bounds().makeOffset(x, y);
252387e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        SkRect tmp;
252487e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        if (this->quickReject(paint.computeFastBounds(storage, &tmp))) {
252587e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco            return;
252687e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        }
252787e066ee80e094c8f4ccda3d6c33d907b414b91bsenorblanco        bounds = &storage;
25287ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita    }
25297ba7aa7e82c749b0b794f85b546f588ccf2ca777fmalita
2530024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // We cannot filter in the looper as we normally do, because the paint is
2531024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    // incomplete at this point (text-related attributes are embedded within blob run paints).
2532024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    SkDrawFilter* drawFilter = fMCRec->fFilter;
253396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    fMCRec->fFilter = nullptr;
2534024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
253585d5eb92940868baf8f6962dffe8ed28caa62d0dfmalita    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds)
253600d5c2c6523321d25b32905ff4822f083a4173eefmalita
2537aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    while (iter.next()) {
2538aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2539a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawTextBlob(blob, x, y, dfp.paint(), drawFilter);
254000d5c2c6523321d25b32905ff4822f083a4173eefmalita    }
254100d5c2c6523321d25b32905ff4822f083a4173eefmalita
2542aa1b9120463fc69be7a5545eb83e6fbe6955a424fmalita    LOOPER_END
2543024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita
2544024f996c1daac32ecad1f9ffec15f0e54fb207f4fmalita    fMCRec->fFilter = drawFilter;
254500d5c2c6523321d25b32905ff4822f083a4173eefmalita}
254600d5c2c6523321d25b32905ff4822f083a4173eefmalita
25472a475eae622adc1e8fa29206be1eaf862c23548eCary Clarkvoid SkCanvas::drawString(const SkString& string, SkScalar x, SkScalar y, const SkPaint& paint) {
25482a475eae622adc1e8fa29206be1eaf862c23548eCary Clark    this->drawText(string.c_str(), string.size(), x, y, paint);
25492a475eae622adc1e8fa29206be1eaf862c23548eCary Clark}
25502a475eae622adc1e8fa29206be1eaf862c23548eCary Clark
2551e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com// These will become non-virtual, so they always call the (virtual) onDraw... method
2552e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2553e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                        const SkPaint& paint) {
25549881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()");
2555ac09554dce518e9d4496771f648f3ae17eca857creed    if (byteLength) {
2556ac09554dce518e9d4496771f648f3ae17eca857creed        this->onDrawText(text, byteLength, x, y, paint);
2557ac09554dce518e9d4496771f648f3ae17eca857creed    }
2558e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2559e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2560e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                           const SkPaint& paint) {
25619881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()");
2562ac09554dce518e9d4496771f648f3ae17eca857creed    if (byteLength) {
2563ac09554dce518e9d4496771f648f3ae17eca857creed        this->onDrawPosText(text, byteLength, pos, paint);
2564ac09554dce518e9d4496771f648f3ae17eca857creed    }
2565e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2566e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2567e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                            SkScalar constY, const SkPaint& paint) {
25689881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()");
2569ac09554dce518e9d4496771f648f3ae17eca857creed    if (byteLength) {
2570ac09554dce518e9d4496771f648f3ae17eca857creed        this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2571ac09554dce518e9d4496771f648f3ae17eca857creed    }
2572e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
2573e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.comvoid SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2574e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com                              const SkMatrix* matrix, const SkPaint& paint) {
25759881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()");
2576ac09554dce518e9d4496771f648f3ae17eca857creed    if (byteLength) {
2577ac09554dce518e9d4496771f648f3ae17eca857creed        this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2578ac09554dce518e9d4496771f648f3ae17eca857creed    }
2579e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com}
258045561a0b15fe045ba272c328684c3f7ae290785areedvoid SkCanvas::drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
258145561a0b15fe045ba272c328684c3f7ae290785areed                               const SkRect* cullRect, const SkPaint& paint) {
258245561a0b15fe045ba272c328684c3f7ae290785areed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextRSXform()");
258345561a0b15fe045ba272c328684c3f7ae290785areed    if (byteLength) {
258445561a0b15fe045ba272c328684c3f7ae290785areed        this->onDrawTextRSXform(text, byteLength, xform, cullRect, paint);
258545561a0b15fe045ba272c328684c3f7ae290785areed    }
258645561a0b15fe045ba272c328684c3f7ae290785areed}
258700d5c2c6523321d25b32905ff4822f083a4173eefmalitavoid SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
258800d5c2c6523321d25b32905ff4822f083a4173eefmalita                            const SkPaint& paint) {
2589e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(blob);
25909881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()");
2591e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    this->onDrawTextBlob(blob, x, y, paint);
259200d5c2c6523321d25b32905ff4822f083a4173eefmalita}
2593e0d9ce890e67d02727ac2811bb456ddb64f827d4reed@google.com
2594e88a1cb20e6b4c9f099070112225a88693a4630bMike Reedvoid SkCanvas::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode,
2595e88a1cb20e6b4c9f099070112225a88693a4630bMike Reed                                    const SkPaint& paint) {
2596199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
2597199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
2598199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon
2599199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    while (iter.next()) {
2600199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon        // In the common case of one iteration we could std::move vertices here.
26012f6b5a47a50cdd218bc3302273be3a4a71add8fbMike Reed        iter.fDevice->drawVertices(vertices, bmode, looper.paint());
2602199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    }
2603199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon
2604199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon    LOOPER_END
2605199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon}
2606199fb875c5e63c13233209e89b943c7ac7ab6665Brian Salomon
2607b3c9d1c33caf325aada244204215eb790c228c12dandovvoid SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
26087d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                         const SkPoint texCoords[4], SkBlendMode bmode,
26097d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                         const SkPaint& paint) {
26109881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()");
261196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == cubics) {
2612b3c9d1c33caf325aada244204215eb790c228c12dandov        return;
2613b3c9d1c33caf325aada244204215eb790c228c12dandov    }
26146cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2615faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed    this->onDrawPatch(cubics, colors, texCoords, bmode, paint);
26169340c2685c0bb0e1e70008acaaf3d1448f074c38msarett}
26179340c2685c0bb0e1e70008acaaf3d1448f074c38msarett
26189340c2685c0bb0e1e70008acaaf3d1448f074c38msarettvoid SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2619faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed                           const SkPoint texCoords[4], SkBlendMode bmode,
26207d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed                           const SkPaint& paint) {
2621ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // Since a patch is always within the convex hull of the control points, we discard it when its
2622ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    // bounding rectangle is completely outside the current clip.
2623ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    SkRect bounds;
2624b3c9d1c33caf325aada244204215eb790c228c12dandov    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2625ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    if (this->quickReject(bounds)) {
2626ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov        return;
2627ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
26286cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
262996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
26306cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2631ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    while (iter.next()) {
2632a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawPatch(cubics, colors, texCoords, bmode, paint);
2633ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    }
26346cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
2635ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov    LOOPER_END
2636ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov}
2637ecfff21bde1f0ca3c36533eded325066b5f2d42ddandov
2638a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) {
2639e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(dr);
2640e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (x || y) {
2641e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        SkMatrix matrix = SkMatrix::MakeTrans(x, y);
2642e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        this->onDrawDrawable(dr, &matrix);
2643e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    } else {
2644e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        this->onDrawDrawable(dr, nullptr);
2645a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    }
2646a8db72864a43ad1fbba3c2892cf5cd88060a43efreed}
2647a8db72864a43ad1fbba3c2892cf5cd88060a43efreed
2648a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2649e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(dr);
2650e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (matrix && matrix->isIdentity()) {
2651e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        matrix = nullptr;
26526a070dc06af4e9f305f9d08a69e34d18ade473cbreed    }
2653e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    this->onDrawDrawable(dr, matrix);
26546a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
26556a070dc06af4e9f305f9d08a69e34d18ade473cbreed
2656a8db72864a43ad1fbba3c2892cf5cd88060a43efreedvoid SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
26572a62e853c27cfacafd5c15ac1077cc13140589bareed    // drawable bounds are no longer reliable (e.g. android displaylist)
26582a62e853c27cfacafd5c15ac1077cc13140589bareed    // so don't use them for quick-reject
2659a8db72864a43ad1fbba3c2892cf5cd88060a43efreed    dr->draw(this, matrix);
26606a070dc06af4e9f305f9d08a69e34d18ade473cbreed}
26616a070dc06af4e9f305f9d08a69e34d18ade473cbreed
266271c3c760a83123ee0b3127b8c65c6394ce541c50reedvoid SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
2663faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed                           const SkColor colors[], int count, SkBlendMode bmode,
266471c3c760a83123ee0b3127b8c65c6394ce541c50reed                           const SkRect* cull, const SkPaint* paint) {
266571c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (cull && this->quickReject(*cull)) {
266671c3c760a83123ee0b3127b8c65c6394ce541c50reed        return;
266771c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
266871c3c760a83123ee0b3127b8c65c6394ce541c50reed
266971c3c760a83123ee0b3127b8c65c6394ce541c50reed    SkPaint pnt;
267071c3c760a83123ee0b3127b8c65c6394ce541c50reed    if (paint) {
267171c3c760a83123ee0b3127b8c65c6394ce541c50reed        pnt = *paint;
267271c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
26739d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
267496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr)
267571c3c760a83123ee0b3127b8c65c6394ce541c50reed    while (iter.next()) {
2676a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawAtlas(atlas, xform, tex, colors, count, bmode, pnt);
267771c3c760a83123ee0b3127b8c65c6394ce541c50reed    }
267871c3c760a83123ee0b3127b8c65c6394ce541c50reed    LOOPER_END
267971c3c760a83123ee0b3127b8c65c6394ce541c50reed}
268071c3c760a83123ee0b3127b8c65c6394ce541c50reed
2681f70b531daaf47db1ee95c70da9843f1dd1f418d3reedvoid SkCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
2682f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    SkASSERT(key);
2683f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
2684f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    SkPaint paint;
2685f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, nullptr)
2686f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    while (iter.next()) {
2687a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed        iter.fDevice->drawAnnotation(rect, key, value);
2688f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    }
2689f70b531daaf47db1ee95c70da9843f1dd1f418d3reed    LOOPER_END
2690f70b531daaf47db1ee95c70da9843f1dd1f418d3reed}
2691f70b531daaf47db1ee95c70da9843f1dd1f418d3reed
26928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
26938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// These methods are NOT virtual, and therefore must call back into virtual
26948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// methods, rather than actually drawing themselves.
26958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
26968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2697374772bd61951f01bf84fe17bf53d8867681c9aereedvoid SkCanvas::drawColor(SkColor c, SkBlendMode mode) {
26989881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()");
26998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint paint;
27008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    paint.setColor(c);
2702374772bd61951f01bf84fe17bf53d8867681c9aereed    paint.setBlendMode(mode);
27038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPaint(paint);
27048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
27079881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)");
27083661bc997620899695041010a750d11dbe8a972dMike Reed    const SkPoint pt = { x, y };
27098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
27108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27123661bc997620899695041010a750d11dbe8a972dMike Reedvoid SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint) {
27139881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()");
27148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint pts[2];
27154b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
27168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[0].set(x0, y0);
27178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    pts[1].set(x1, y1);
27188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawPoints(kLines_PointMode, 2, pts, paint);
27198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27213661bc997620899695041010a750d11dbe8a972dMike Reedvoid SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint) {
27229881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()");
27238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (radius < 0) {
27248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        radius = 0;
27258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
27268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRect  r;
27288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
27294ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com    this->drawOval(r, paint);
27308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
27338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const SkPaint& paint) {
27349881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()");
27358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rx > 0 && ry > 0) {
27364ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        SkRRect rrect;
27374ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        rrect.setRectXY(r, rx, ry);
27384ed0fb768409bf97b79899c3990d8c15f5e9d784reed@google.com        this->drawRRect(rrect, paint);
27398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
27408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->drawRect(r, paint);
27418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
27428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
27458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       SkScalar sweepAngle, bool useCenter,
27468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                       const SkPaint& paint) {
27479881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
274821af9ca1b1f54d9ba1de055aa8475928d5c8ecdfbsalomon    if (oval.isEmpty() || !sweepAngle) {
274921af9ca1b1f54d9ba1de055aa8475928d5c8ecdfbsalomon        return;
27508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
275121af9ca1b1f54d9ba1de055aa8475928d5c8ecdfbsalomon    this->onDrawArc(oval, startAngle, sweepAngle, useCenter, paint);
27528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
27558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const SkPath& path, SkScalar hOffset,
27568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                SkScalar vOffset, const SkPaint& paint) {
27579881d63c57002ffbdf2adf623965ece280279989danakj    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()");
27588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix    matrix;
27594b226023832011bc3bcdd1e5092ff0645ad0bdeereed@google.com
27608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setTranslate(hOffset, vOffset);
27618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
27628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
27638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2764f76bacff7f66724072c67edb185abf9e3add11a0reed@android.com///////////////////////////////////////////////////////////////////////////////
27651c2c441fede0ae9573afc098017011e3439624a9reed
27661c2c441fede0ae9573afc098017011e3439624a9reed/**
27671c2c441fede0ae9573afc098017011e3439624a9reed *  This constant is trying to balance the speed of ref'ing a subpicture into a parent picture,
27681c2c441fede0ae9573afc098017011e3439624a9reed *  against the playback cost of recursing into the subpicture to get at its actual ops.
27691c2c441fede0ae9573afc098017011e3439624a9reed *
27701c2c441fede0ae9573afc098017011e3439624a9reed *  For now we pick a conservatively small value, though measurement (and other heuristics like
27711c2c441fede0ae9573afc098017011e3439624a9reed *  the type of ops contained) may justify changing this value.
27721c2c441fede0ae9573afc098017011e3439624a9reed */
27731c2c441fede0ae9573afc098017011e3439624a9reed#define kMaxPictureOpsToUnrollInsteadOfRef  1
27749b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2775d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
2776e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    RETURN_ON_NULL(picture);
2777e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed
27781c2c441fede0ae9573afc098017011e3439624a9reed    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()");
2779e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (matrix && matrix->isIdentity()) {
2780e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        matrix = nullptr;
2781e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    }
2782e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) {
2783e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2784e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        picture->playback(this);
2785e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed    } else {
2786e3b38ce43b5c5c6711e9cde4588e2bc15333c780reed        this->onDrawPicture(picture, matrix, paint);
2787d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
2788d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
27899b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips
2790d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedvoid SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2791d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed                             const SkPaint* paint) {
2792d028180f0310cf2b23f9744256a41697b0683e67fmalita    if (!paint || paint->canComputeFastBounds()) {
2793d028180f0310cf2b23f9744256a41697b0683e67fmalita        SkRect bounds = picture->cullRect();
2794d028180f0310cf2b23f9744256a41697b0683e67fmalita        if (paint) {
2795d028180f0310cf2b23f9744256a41697b0683e67fmalita            paint->computeFastBounds(bounds, &bounds);
2796d028180f0310cf2b23f9744256a41697b0683e67fmalita        }
2797d028180f0310cf2b23f9744256a41697b0683e67fmalita        if (matrix) {
2798d028180f0310cf2b23f9744256a41697b0683e67fmalita            matrix->mapRect(&bounds);
2799d028180f0310cf2b23f9744256a41697b0683e67fmalita        }
2800d028180f0310cf2b23f9744256a41697b0683e67fmalita        if (this->quickReject(bounds)) {
2801d028180f0310cf2b23f9744256a41697b0683e67fmalita            return;
2802d028180f0310cf2b23f9744256a41697b0683e67fmalita        }
2803d028180f0310cf2b23f9744256a41697b0683e67fmalita    }
2804d028180f0310cf2b23f9744256a41697b0683e67fmalita
2805a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2806c5ba71d2e5cd426def66fa49dcf003e5b2c98dc7robertphillips    picture->playback(this);
28078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
28108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
28118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28123aafe111b6cc388400092851cc53bbbdfcb8a81creedSkCanvas::LayerIter::LayerIter(SkCanvas* canvas) {
281399fe82260633fcf5d92cca38d12ef0937ecca61cbungeman    static_assert(sizeof(fStorage) >= sizeof(SkDrawIter), "fStorage_too_small");
28148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(canvas);
28168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28173aafe111b6cc388400092851cc53bbbdfcb8a81creed    fImpl = new (fStorage) SkDrawIter(canvas);
28188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
28198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkCanvas::LayerIter::~LayerIter() {
28228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fImpl->~SkDrawIter();
28238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkCanvas::LayerIter::next() {
28268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = !fImpl->next();
28278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28291f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comSkBaseDevice* SkCanvas::LayerIter::device() const {
283099330ba6227137866a0dbd63478d36f335203ebdMike Reed    return fImpl->fDevice;
28318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix& SkCanvas::LayerIter::matrix() const {
2834a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    return fImpl->fDevice->ctm();
28358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkPaint& SkCanvas::LayerIter::paint() const {
28388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPaint* paint = fImpl->getPaint();
283996fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == paint) {
28408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        paint = &fDefaultPaint;
28418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
28428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *paint;
28438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
28448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2845a1361364e64138adda3dc5f71d50d7503838bb6dMike Reedvoid SkCanvas::LayerIter::clip(SkRegion* rgn) const {
2846a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed    return fImpl->fDevice->onAsRgnClip(rgn);
2847a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed}
2848a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed
28498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::x() const { return fImpl->getX(); }
28508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkCanvas::LayerIter::y() const { return fImpl->getY(); }
285120a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
285220a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com///////////////////////////////////////////////////////////////////////////////
285320a550c6ea947f0ab239da1d4ecba209d76a98fdjustinlin@google.com
28543107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.orgstatic bool supported_for_raster_canvas(const SkImageInfo& info) {
28553107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.alphaType()) {
28563107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kPremul_SkAlphaType:
28573107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kOpaque_SkAlphaType:
28583107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
28593107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
28603107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
28613107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
28623107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
28633107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    switch (info.colorType()) {
28643107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kAlpha_8_SkColorType:
28653107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        case kRGB_565_SkColorType:
286628fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:
28679e3dbdff53f2d9957626a17a279730cda70f17bajunov        case kRGBA_F16_SkColorType:
28683107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            break;
28693107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org        default:
28703107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org            return false;
28713107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    }
28723107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
28733107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    return true;
28743107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org}
28753107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org
28765df4934b3e40cdc378e225d1dda39f015cae9baeMike Reedstd::unique_ptr<SkCanvas> SkCanvas::MakeRasterDirect(const SkImageInfo& info, void* pixels,
28775df4934b3e40cdc378e225d1dda39f015cae9baeMike Reed                                                     size_t rowBytes) {
287842b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!supported_for_raster_canvas(info)) {
287996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
288042b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
2881eb849e5fd10cbe00cbc31307ba97fd9efca0b41bskia.committer@gmail.com
288242b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    SkBitmap bitmap;
288342b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    if (!bitmap.installPixels(info, pixels, rowBytes)) {
288496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
288542b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org    }
28865df4934b3e40cdc378e225d1dda39f015cae9baeMike Reed    return skstd::make_unique<SkCanvas>(bitmap);
288742b08932e81abd8ebf296bede1994d297811511dcommit-bot@chromium.org}
2888d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2889d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed///////////////////////////////////////////////////////////////////////////////
2890d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2891d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
2892a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips                                                 const SkPaint* paint, const SkRect& bounds)
2893d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    : fCanvas(canvas)
2894d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    , fSaveCount(canvas->getSaveCount())
2895d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed{
289649f085dddff10473b6ebf832a974288300224e60bsalomon    if (paint) {
2897a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        SkRect newBounds = bounds;
2898d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        if (matrix) {
2899a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips            matrix->mapRect(&newBounds);
2900d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        }
2901a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        canvas->saveLayer(&newBounds, paint);
290249f085dddff10473b6ebf832a974288300224e60bsalomon    } else if (matrix) {
2903d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->save();
2904d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
29056cfa73a29a26edf1d03bca224ad6860396308ffcmtklein
290649f085dddff10473b6ebf832a974288300224e60bsalomon    if (matrix) {
2907d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed        canvas->concat(*matrix);
2908d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    }
2909d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
2910d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed
2911d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reedSkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
2912d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed    fCanvas->restoreToCount(fSaveCount);
2913d5fa1a455aad61f3e99081fe7a9b065cb3b115c6reed}
2914e8f3062a36d3682f4019309a32b5b84dc9eddf8creed
2915ee424acbb87bf999be132a437527e656e37541d7Florin Malita///////////////////////////////////////////////////////////////////////////////
2916ee424acbb87bf999be132a437527e656e37541d7Florin Malita
2917ee424acbb87bf999be132a437527e656e37541d7Florin MalitaSkNoDrawCanvas::SkNoDrawCanvas(int width, int height)
2918ee424acbb87bf999be132a437527e656e37541d7Florin Malita    : INHERITED(SkIRect::MakeWH(width, height), kConservativeRasterClip_InitFlag) {}
2919ee424acbb87bf999be132a437527e656e37541d7Florin Malita
2920439ace939b6aaa58408ece0e9e89b633353571aeFlorin MalitaSkNoDrawCanvas::SkNoDrawCanvas(const SkIRect& bounds)
2921439ace939b6aaa58408ece0e9e89b633353571aeFlorin Malita    : INHERITED(bounds, kConservativeRasterClip_InitFlag) {}
2922439ace939b6aaa58408ece0e9e89b633353571aeFlorin Malita
2923ee424acbb87bf999be132a437527e656e37541d7Florin MalitaSkCanvas::SaveLayerStrategy SkNoDrawCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
2924ee424acbb87bf999be132a437527e656e37541d7Florin Malita    (void)this->INHERITED::getSaveLayerStrategy(rec);
2925ee424acbb87bf999be132a437527e656e37541d7Florin Malita    return kNoLayer_SaveLayerStrategy;
2926ee424acbb87bf999be132a437527e656e37541d7Florin Malita}
2927ee424acbb87bf999be132a437527e656e37541d7Florin Malita
2928ee424acbb87bf999be132a437527e656e37541d7Florin Malita///////////////////////////////////////////////////////////////////////////////
292973603f3c52ffd89fe9d035be827b566a0e7d3b79reed
293073603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kDifference_Op         == (int)kDifference_SkClipOp, "");
293173603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kIntersect_Op          == (int)kIntersect_SkClipOp, "");
293273603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kUnion_Op              == (int)kUnion_SkClipOp, "");
293373603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kXOR_Op                == (int)kXOR_SkClipOp, "");
293473603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kReverseDifference_Op  == (int)kReverseDifference_SkClipOp, "");
293573603f3c52ffd89fe9d035be827b566a0e7d3b79reedstatic_assert((int)SkRegion::kReplace_Op            == (int)kReplace_SkClipOp, "");
2936356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
2937356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed///////////////////////////////////////////////////////////////////////////////////////////////////
2938356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
2939356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedSkRasterHandleAllocator::Handle SkCanvas::accessTopRasterHandle() const {
2940356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    if (fAllocator && fMCRec->fTopLayer->fDevice) {
2941713b8ef3748609ee20f6005a66d6aafd02aab4b6Florin Malita        const auto& dev = fMCRec->fTopLayer->fDevice;
2942356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        SkRasterHandleAllocator::Handle handle = dev->getRasterHandle();
2943356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        SkIPoint origin = dev->getOrigin();
2944356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        SkMatrix ctm = this->getTotalMatrix();
2945356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        ctm.preTranslate(SkIntToScalar(-origin.x()), SkIntToScalar(-origin.y()));
2946356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
2947356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        SkIRect clip = fMCRec->fRasterClip.getBounds();
2948356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        clip.offset(-origin.x(), -origin.y());
2949108f55ed5d0b63baf653e4e443cc469df887c811Mike Reed        if (!clip.intersect(0, 0, dev->width(), dev->height())) {
2950356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed            clip.setEmpty();
2951356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        }
2952356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
2953356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        fAllocator->updateHandle(handle, ctm, clip);
2954356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        return handle;
2955356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    }
2956356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    return nullptr;
2957356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed}
2958356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
2959356f7c2600ef54237fb8678cf63d5953f065b7daMike Reedstatic bool install(SkBitmap* bm, const SkImageInfo& info,
2960356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                    const SkRasterHandleAllocator::Rec& rec) {
2961356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    return bm->installPixels(info, rec.fPixels, rec.fRowBytes, nullptr,
2962356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                             rec.fReleaseProc, rec.fReleaseCtx);
2963356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed}
2964356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
2965356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedSkRasterHandleAllocator::Handle SkRasterHandleAllocator::allocBitmap(const SkImageInfo& info,
2966356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                                                                     SkBitmap* bm) {
2967356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    SkRasterHandleAllocator::Rec rec;
2968356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    if (!this->allocHandle(info, &rec) || !install(bm, info, rec)) {
2969356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        return nullptr;
2970356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    }
2971356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    return rec.fHandle;
2972356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed}
2973356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
2974356f7c2600ef54237fb8678cf63d5953f065b7daMike Reedstd::unique_ptr<SkCanvas>
2975356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedSkRasterHandleAllocator::MakeCanvas(std::unique_ptr<SkRasterHandleAllocator> alloc,
2976356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                                    const SkImageInfo& info, const Rec* rec) {
2977356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    if (!alloc || !supported_for_raster_canvas(info)) {
2978356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        return nullptr;
2979356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    }
2980356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
2981356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    SkBitmap bm;
2982356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    Handle hndl;
2983356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
2984356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    if (rec) {
2985356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        hndl = install(&bm, info, *rec) ? rec->fHandle : nullptr;
2986356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    } else {
2987356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        hndl = alloc->allocBitmap(info, &bm);
2988356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    }
2989356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    return hndl ? std::unique_ptr<SkCanvas>(new SkCanvas(bm, std::move(alloc), hndl)) : nullptr;
2990356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed}
2991