CanvasState.cpp revision eecff56fed5dd5206acfbc5007b4912081b36d3b
114e513058ed4168c94e015638d16f5f87fd8063aChris Craik/*
214e513058ed4168c94e015638d16f5f87fd8063aChris Craik * Copyright (C) 2014 The Android Open Source Project
314e513058ed4168c94e015638d16f5f87fd8063aChris Craik *
414e513058ed4168c94e015638d16f5f87fd8063aChris Craik * Licensed under the Apache License, Version 2.0 (the "License");
514e513058ed4168c94e015638d16f5f87fd8063aChris Craik * you may not use this file except in compliance with the License.
614e513058ed4168c94e015638d16f5f87fd8063aChris Craik * You may obtain a copy of the License at
714e513058ed4168c94e015638d16f5f87fd8063aChris Craik *
814e513058ed4168c94e015638d16f5f87fd8063aChris Craik *      http://www.apache.org/licenses/LICENSE-2.0
914e513058ed4168c94e015638d16f5f87fd8063aChris Craik *
1014e513058ed4168c94e015638d16f5f87fd8063aChris Craik * Unless required by applicable law or agreed to in writing, software
1114e513058ed4168c94e015638d16f5f87fd8063aChris Craik * distributed under the License is distributed on an "AS IS" BASIS,
1214e513058ed4168c94e015638d16f5f87fd8063aChris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1314e513058ed4168c94e015638d16f5f87fd8063aChris Craik * See the License for the specific language governing permissions and
1414e513058ed4168c94e015638d16f5f87fd8063aChris Craik * limitations under the License.
1514e513058ed4168c94e015638d16f5f87fd8063aChris Craik */
1614e513058ed4168c94e015638d16f5f87fd8063aChris Craik
17eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita#include "Canvas.h"
18984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson#include "CanvasState.h"
19af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik#include "utils/MathUtils.h"
20af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik
2114e513058ed4168c94e015638d16f5f87fd8063aChris Craiknamespace android {
2214e513058ed4168c94e015638d16f5f87fd8063aChris Craiknamespace uirenderer {
2314e513058ed4168c94e015638d16f5f87fd8063aChris Craik
24984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
25984162fb7e4010b6e2908352dbff17ed47eecf06Tom HudsonCanvasState::CanvasState(CanvasStateClient& renderer)
26058fc640017c90120c599d378a4cbc55668b05b7Chris Craik        : mDirtyClip(false)
27058fc640017c90120c599d378a4cbc55668b05b7Chris Craik        , mWidth(-1)
28058fc640017c90120c599d378a4cbc55668b05b7Chris Craik        , mHeight(-1)
29058fc640017c90120c599d378a4cbc55668b05b7Chris Craik        , mSaveCount(1)
30984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson        , mCanvas(renderer)
31d9ee550888011a64fa3f35e666360ec8278597d8John Reck        , mSnapshot(&mFirstSnapshot) {
32d9ee550888011a64fa3f35e666360ec8278597d8John Reck}
33d9ee550888011a64fa3f35e666360ec8278597d8John Reck
34d9ee550888011a64fa3f35e666360ec8278597d8John ReckCanvasState::~CanvasState() {
35d9ee550888011a64fa3f35e666360ec8278597d8John Reck    // First call freeSnapshot on all but mFirstSnapshot
36d9ee550888011a64fa3f35e666360ec8278597d8John Reck    // to invoke all the dtors
37d9ee550888011a64fa3f35e666360ec8278597d8John Reck    freeAllSnapshots();
38984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
39d9ee550888011a64fa3f35e666360ec8278597d8John Reck    // Now actually release the memory
40d9ee550888011a64fa3f35e666360ec8278597d8John Reck    while (mSnapshotPool) {
41d9ee550888011a64fa3f35e666360ec8278597d8John Reck        void* temp = mSnapshotPool;
42d9ee550888011a64fa3f35e666360ec8278597d8John Reck        mSnapshotPool = mSnapshotPool->previous;
43d9ee550888011a64fa3f35e666360ec8278597d8John Reck        free(temp);
44d9ee550888011a64fa3f35e666360ec8278597d8John Reck    }
4514e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
4614e513058ed4168c94e015638d16f5f87fd8063aChris Craik
47e4db79de127cfe961195f52907af8451026eaa20Chris Craikvoid CanvasState::initializeRecordingSaveStack(int viewportWidth, int viewportHeight) {
48e4db79de127cfe961195f52907af8451026eaa20Chris Craik    if (mWidth != viewportWidth || mHeight != viewportHeight) {
49e4db79de127cfe961195f52907af8451026eaa20Chris Craik        mWidth = viewportWidth;
50e4db79de127cfe961195f52907af8451026eaa20Chris Craik        mHeight = viewportHeight;
51e4db79de127cfe961195f52907af8451026eaa20Chris Craik        mFirstSnapshot.initializeViewport(viewportWidth, viewportHeight);
52e4db79de127cfe961195f52907af8451026eaa20Chris Craik        mCanvas.onViewportInitialized();
53e4db79de127cfe961195f52907af8451026eaa20Chris Craik    }
54e4db79de127cfe961195f52907af8451026eaa20Chris Craik
55e4db79de127cfe961195f52907af8451026eaa20Chris Craik    freeAllSnapshots();
56eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    mSnapshot = allocSnapshot(&mFirstSnapshot, SaveFlags::MatrixClip);
57e4db79de127cfe961195f52907af8451026eaa20Chris Craik    mSnapshot->setRelativeLightCenter(Vector3());
58e4db79de127cfe961195f52907af8451026eaa20Chris Craik    mSaveCount = 1;
59e4db79de127cfe961195f52907af8451026eaa20Chris Craik}
60e4db79de127cfe961195f52907af8451026eaa20Chris Craik
6164e445bf74bee2098781d608cedfd723d8cc88d3Chris Craikvoid CanvasState::initializeSaveStack(
6264e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik        int viewportWidth, int viewportHeight,
6364e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik        float clipLeft, float clipTop,
6469e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik        float clipRight, float clipBottom, const Vector3& lightCenter) {
6564e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik    if (mWidth != viewportWidth || mHeight != viewportHeight) {
6664e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik        mWidth = viewportWidth;
6764e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik        mHeight = viewportHeight;
68d9ee550888011a64fa3f35e666360ec8278597d8John Reck        mFirstSnapshot.initializeViewport(viewportWidth, viewportHeight);
6964e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik        mCanvas.onViewportInitialized();
7064e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik    }
7164e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik
72d9ee550888011a64fa3f35e666360ec8278597d8John Reck    freeAllSnapshots();
73eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    mSnapshot = allocSnapshot(&mFirstSnapshot, SaveFlags::MatrixClip);
7414e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSnapshot->setClip(clipLeft, clipTop, clipRight, clipBottom);
756b109c74982033d4a220cd10a0eab8b024b351c9Chris Craik    mSnapshot->fbo = mCanvas.getTargetFbo();
7669e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik    mSnapshot->setRelativeLightCenter(lightCenter);
7714e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSaveCount = 1;
7814e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
7914e513058ed4168c94e015638d16f5f87fd8063aChris Craik
80d9ee550888011a64fa3f35e666360ec8278597d8John ReckSnapshot* CanvasState::allocSnapshot(Snapshot* previous, int savecount) {
81d9ee550888011a64fa3f35e666360ec8278597d8John Reck    void* memory;
82d9ee550888011a64fa3f35e666360ec8278597d8John Reck    if (mSnapshotPool) {
83d9ee550888011a64fa3f35e666360ec8278597d8John Reck        memory = mSnapshotPool;
84d9ee550888011a64fa3f35e666360ec8278597d8John Reck        mSnapshotPool = mSnapshotPool->previous;
85d9ee550888011a64fa3f35e666360ec8278597d8John Reck        mSnapshotPoolCount--;
86d9ee550888011a64fa3f35e666360ec8278597d8John Reck    } else {
87d9ee550888011a64fa3f35e666360ec8278597d8John Reck        memory = malloc(sizeof(Snapshot));
88d9ee550888011a64fa3f35e666360ec8278597d8John Reck    }
89d9ee550888011a64fa3f35e666360ec8278597d8John Reck    return new (memory) Snapshot(previous, savecount);
90d9ee550888011a64fa3f35e666360ec8278597d8John Reck}
91d9ee550888011a64fa3f35e666360ec8278597d8John Reck
92d9ee550888011a64fa3f35e666360ec8278597d8John Reckvoid CanvasState::freeSnapshot(Snapshot* snapshot) {
93d9ee550888011a64fa3f35e666360ec8278597d8John Reck    snapshot->~Snapshot();
94d9ee550888011a64fa3f35e666360ec8278597d8John Reck    // Arbitrary number, just don't let this grown unbounded
95d9ee550888011a64fa3f35e666360ec8278597d8John Reck    if (mSnapshotPoolCount > 10) {
96d9ee550888011a64fa3f35e666360ec8278597d8John Reck        free((void*) snapshot);
97d9ee550888011a64fa3f35e666360ec8278597d8John Reck    } else {
98d9ee550888011a64fa3f35e666360ec8278597d8John Reck        snapshot->previous = mSnapshotPool;
99d9ee550888011a64fa3f35e666360ec8278597d8John Reck        mSnapshotPool = snapshot;
100d9ee550888011a64fa3f35e666360ec8278597d8John Reck        mSnapshotPoolCount++;
101d9ee550888011a64fa3f35e666360ec8278597d8John Reck    }
102d9ee550888011a64fa3f35e666360ec8278597d8John Reck}
103d9ee550888011a64fa3f35e666360ec8278597d8John Reck
104d9ee550888011a64fa3f35e666360ec8278597d8John Reckvoid CanvasState::freeAllSnapshots() {
105d9ee550888011a64fa3f35e666360ec8278597d8John Reck    while (mSnapshot != &mFirstSnapshot) {
106d9ee550888011a64fa3f35e666360ec8278597d8John Reck        Snapshot* temp = mSnapshot;
107d9ee550888011a64fa3f35e666360ec8278597d8John Reck        mSnapshot = mSnapshot->previous;
108d9ee550888011a64fa3f35e666360ec8278597d8John Reck        freeSnapshot(temp);
109d9ee550888011a64fa3f35e666360ec8278597d8John Reck    }
110d9ee550888011a64fa3f35e666360ec8278597d8John Reck}
111d9ee550888011a64fa3f35e666360ec8278597d8John Reck
11214e513058ed4168c94e015638d16f5f87fd8063aChris Craik///////////////////////////////////////////////////////////////////////////////
11314e513058ed4168c94e015638d16f5f87fd8063aChris Craik// Save (layer)
11414e513058ed4168c94e015638d16f5f87fd8063aChris Craik///////////////////////////////////////////////////////////////////////////////
11514e513058ed4168c94e015638d16f5f87fd8063aChris Craik
11614e513058ed4168c94e015638d16f5f87fd8063aChris Craik/**
117984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson * Guaranteed to save without side-effects
11814e513058ed4168c94e015638d16f5f87fd8063aChris Craik *
119984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson * This approach, here and in restoreSnapshot(), allows subclasses to directly manipulate the save
12014e513058ed4168c94e015638d16f5f87fd8063aChris Craik * stack, and ensures restoreToCount() doesn't call back into subclass overrides.
12114e513058ed4168c94e015638d16f5f87fd8063aChris Craik */
122984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonint CanvasState::saveSnapshot(int flags) {
123d9ee550888011a64fa3f35e666360ec8278597d8John Reck    mSnapshot = allocSnapshot(mSnapshot, flags);
12414e513058ed4168c94e015638d16f5f87fd8063aChris Craik    return mSaveCount++;
12514e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
12614e513058ed4168c94e015638d16f5f87fd8063aChris Craik
127984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonint CanvasState::save(int flags) {
12814e513058ed4168c94e015638d16f5f87fd8063aChris Craik    return saveSnapshot(flags);
12914e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
13014e513058ed4168c94e015638d16f5f87fd8063aChris Craik
13114e513058ed4168c94e015638d16f5f87fd8063aChris Craik/**
132984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson * Guaranteed to restore without side-effects.
13314e513058ed4168c94e015638d16f5f87fd8063aChris Craik */
134984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::restoreSnapshot() {
135d9ee550888011a64fa3f35e666360ec8278597d8John Reck    Snapshot* toRemove = mSnapshot;
136d9ee550888011a64fa3f35e666360ec8278597d8John Reck    Snapshot* toRestore = mSnapshot->previous;
13714e513058ed4168c94e015638d16f5f87fd8063aChris Craik
13814e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSaveCount--;
13914e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSnapshot = toRestore;
14014e513058ed4168c94e015638d16f5f87fd8063aChris Craik
14114e513058ed4168c94e015638d16f5f87fd8063aChris Craik    // subclass handles restore implementation
142984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    mCanvas.onSnapshotRestored(*toRemove, *toRestore);
143d9ee550888011a64fa3f35e666360ec8278597d8John Reck
144d9ee550888011a64fa3f35e666360ec8278597d8John Reck    freeSnapshot(toRemove);
14514e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
14614e513058ed4168c94e015638d16f5f87fd8063aChris Craik
147984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::restore() {
14814e513058ed4168c94e015638d16f5f87fd8063aChris Craik    if (mSaveCount > 1) {
14914e513058ed4168c94e015638d16f5f87fd8063aChris Craik        restoreSnapshot();
15014e513058ed4168c94e015638d16f5f87fd8063aChris Craik    }
15114e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
15214e513058ed4168c94e015638d16f5f87fd8063aChris Craik
153984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::restoreToCount(int saveCount) {
15414e513058ed4168c94e015638d16f5f87fd8063aChris Craik    if (saveCount < 1) saveCount = 1;
15514e513058ed4168c94e015638d16f5f87fd8063aChris Craik
15614e513058ed4168c94e015638d16f5f87fd8063aChris Craik    while (mSaveCount > saveCount) {
15714e513058ed4168c94e015638d16f5f87fd8063aChris Craik        restoreSnapshot();
15814e513058ed4168c94e015638d16f5f87fd8063aChris Craik    }
15914e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
16014e513058ed4168c94e015638d16f5f87fd8063aChris Craik
16114e513058ed4168c94e015638d16f5f87fd8063aChris Craik///////////////////////////////////////////////////////////////////////////////
16214e513058ed4168c94e015638d16f5f87fd8063aChris Craik// Matrix
16314e513058ed4168c94e015638d16f5f87fd8063aChris Craik///////////////////////////////////////////////////////////////////////////////
16414e513058ed4168c94e015638d16f5f87fd8063aChris Craik
165984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::getMatrix(SkMatrix* matrix) const {
16614e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSnapshot->transform->copyTo(*matrix);
16714e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
16814e513058ed4168c94e015638d16f5f87fd8063aChris Craik
169984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::translate(float dx, float dy, float dz) {
17014e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSnapshot->transform->translate(dx, dy, dz);
17114e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
17214e513058ed4168c94e015638d16f5f87fd8063aChris Craik
173984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::rotate(float degrees) {
17414e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSnapshot->transform->rotate(degrees, 0.0f, 0.0f, 1.0f);
17514e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
17614e513058ed4168c94e015638d16f5f87fd8063aChris Craik
177984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::scale(float sx, float sy) {
17814e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSnapshot->transform->scale(sx, sy, 1.0f);
17914e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
18014e513058ed4168c94e015638d16f5f87fd8063aChris Craik
181984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::skew(float sx, float sy) {
18214e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSnapshot->transform->skew(sx, sy);
18314e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
18414e513058ed4168c94e015638d16f5f87fd8063aChris Craik
185984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::setMatrix(const SkMatrix& matrix) {
186139088228faa7f3c446af7387e017933998a5570Derek Sollenberger    mSnapshot->transform->load(matrix);
18714e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
18814e513058ed4168c94e015638d16f5f87fd8063aChris Craik
189984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::setMatrix(const Matrix4& matrix) {
1907c85c54499994c687a833644f7f213e747fadb98Chris Craik    *(mSnapshot->transform) = matrix;
19114e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
19214e513058ed4168c94e015638d16f5f87fd8063aChris Craik
193984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::concatMatrix(const SkMatrix& matrix) {
194139088228faa7f3c446af7387e017933998a5570Derek Sollenberger    mat4 transform(matrix);
19514e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSnapshot->transform->multiply(transform);
19614e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
19714e513058ed4168c94e015638d16f5f87fd8063aChris Craik
198984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::concatMatrix(const Matrix4& matrix) {
19914e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSnapshot->transform->multiply(matrix);
20014e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
20114e513058ed4168c94e015638d16f5f87fd8063aChris Craik
20214e513058ed4168c94e015638d16f5f87fd8063aChris Craik///////////////////////////////////////////////////////////////////////////////
20314e513058ed4168c94e015638d16f5f87fd8063aChris Craik// Clip
20414e513058ed4168c94e015638d16f5f87fd8063aChris Craik///////////////////////////////////////////////////////////////////////////////
20514e513058ed4168c94e015638d16f5f87fd8063aChris Craik
206984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonbool CanvasState::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
207a2a70723b8cbda4354d23f901f995623e819012cChris Craik    mSnapshot->clip(Rect(left, top, right, bottom), op);
2084d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik    mDirtyClip = true;
209487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    return !mSnapshot->clipIsEmpty();
210d6b65f67717025b1162f86f04e2caa5723566cacChris Craik}
211d6b65f67717025b1162f86f04e2caa5723566cacChris Craik
212984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonbool CanvasState::clipPath(const SkPath* path, SkRegion::Op op) {
2134d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik    mSnapshot->clipPath(*path, op);
2144d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik    mDirtyClip = true;
215487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    return !mSnapshot->clipIsEmpty();
216d6b65f67717025b1162f86f04e2caa5723566cacChris Craik}
217d6b65f67717025b1162f86f04e2caa5723566cacChris Craik
218984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonbool CanvasState::clipRegion(const SkRegion* region, SkRegion::Op op) {
2194d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik    mSnapshot->clipRegionTransformed(*region, op);
2204d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik    mDirtyClip = true;
221487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    return !mSnapshot->clipIsEmpty();
222d6b65f67717025b1162f86f04e2caa5723566cacChris Craik}
22314e513058ed4168c94e015638d16f5f87fd8063aChris Craik
224984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::setClippingOutline(LinearAllocator& allocator, const Outline* outline) {
225af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik    Rect bounds;
226af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik    float radius;
227af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik    if (!outline->getAsRoundRect(&bounds, &radius)) return; // only RR supported
228af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik
22979d26c72aa6f898125df2386054f6a293da4122aChris Craik    bool outlineIsRounded = MathUtils::isPositive(radius);
23079d26c72aa6f898125df2386054f6a293da4122aChris Craik    if (!outlineIsRounded || currentTransform()->isSimple()) {
231af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik        // TODO: consider storing this rect separately, so that this can't be replaced with clip ops
232af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik        clipRect(bounds.left, bounds.top, bounds.right, bounds.bottom, SkRegion::kIntersect_Op);
233af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik    }
23479d26c72aa6f898125df2386054f6a293da4122aChris Craik    if (outlineIsRounded) {
235e83cbd451868a734bfac07ccd680d5617080b579Chris Craik        setClippingRoundRect(allocator, bounds, radius, false);
23679d26c72aa6f898125df2386054f6a293da4122aChris Craik    }
237deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik}
238deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik
239984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::setClippingRoundRect(LinearAllocator& allocator,
240e83cbd451868a734bfac07ccd680d5617080b579Chris Craik        const Rect& rect, float radius, bool highPriority) {
241e83cbd451868a734bfac07ccd680d5617080b579Chris Craik    mSnapshot->setClippingRoundRect(allocator, rect, radius, highPriority);
242af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik}
243af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik
244fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craikvoid CanvasState::setProjectionPathMask(LinearAllocator& allocator, const SkPath* path) {
245fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik    mSnapshot->setProjectionPathMask(allocator, path);
246fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik}
247af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik
24814e513058ed4168c94e015638d16f5f87fd8063aChris Craik///////////////////////////////////////////////////////////////////////////////
24914e513058ed4168c94e015638d16f5f87fd8063aChris Craik// Quick Rejection
25014e513058ed4168c94e015638d16f5f87fd8063aChris Craik///////////////////////////////////////////////////////////////////////////////
25114e513058ed4168c94e015638d16f5f87fd8063aChris Craik
25214e513058ed4168c94e015638d16f5f87fd8063aChris Craik/**
25314e513058ed4168c94e015638d16f5f87fd8063aChris Craik * Calculates whether content drawn within the passed bounds would be outside of, or intersect with
25414e513058ed4168c94e015638d16f5f87fd8063aChris Craik * the clipRect. Does not modify the scissor.
25514e513058ed4168c94e015638d16f5f87fd8063aChris Craik *
25614e513058ed4168c94e015638d16f5f87fd8063aChris Craik * @param clipRequired if not null, will be set to true if element intersects clip
25714e513058ed4168c94e015638d16f5f87fd8063aChris Craik *         (and wasn't rejected)
25814e513058ed4168c94e015638d16f5f87fd8063aChris Craik *
25914e513058ed4168c94e015638d16f5f87fd8063aChris Craik * @param snapOut if set, the geometry will be treated as having an AA ramp.
26014e513058ed4168c94e015638d16f5f87fd8063aChris Craik *         See Rect::snapGeometryToPixelBoundaries()
26114e513058ed4168c94e015638d16f5f87fd8063aChris Craik */
262984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonbool CanvasState::calculateQuickRejectForScissor(float left, float top,
263deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik        float right, float bottom,
264deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik        bool* clipRequired, bool* roundRectClipRequired,
265deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik        bool snapOut) const {
26614e513058ed4168c94e015638d16f5f87fd8063aChris Craik    if (mSnapshot->isIgnored() || bottom <= top || right <= left) {
26714e513058ed4168c94e015638d16f5f87fd8063aChris Craik        return true;
26814e513058ed4168c94e015638d16f5f87fd8063aChris Craik    }
26914e513058ed4168c94e015638d16f5f87fd8063aChris Craik
27014e513058ed4168c94e015638d16f5f87fd8063aChris Craik    Rect r(left, top, right, bottom);
271d6b65f67717025b1162f86f04e2caa5723566cacChris Craik    currentTransform()->mapRect(r);
27214e513058ed4168c94e015638d16f5f87fd8063aChris Craik    r.snapGeometryToPixelBoundaries(snapOut);
27314e513058ed4168c94e015638d16f5f87fd8063aChris Craik
2746fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    Rect clipRect(currentRenderTargetClip());
27514e513058ed4168c94e015638d16f5f87fd8063aChris Craik    clipRect.snapToPixelBoundaries();
27614e513058ed4168c94e015638d16f5f87fd8063aChris Craik
27714e513058ed4168c94e015638d16f5f87fd8063aChris Craik    if (!clipRect.intersects(r)) return true;
27814e513058ed4168c94e015638d16f5f87fd8063aChris Craik
27914e513058ed4168c94e015638d16f5f87fd8063aChris Craik    // clip is required if geometry intersects clip rect
280deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    if (clipRequired) {
281deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik        *clipRequired = !clipRect.contains(r);
282deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    }
283deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik
284deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    // round rect clip is required if RR clip exists, and geometry intersects its corners
285deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    if (roundRectClipRequired) {
286d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik        *roundRectClipRequired = mSnapshot->roundRectClipState != nullptr
287deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik                && mSnapshot->roundRectClipState->areaRequiresRoundRectClip(r);
288deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    }
28914e513058ed4168c94e015638d16f5f87fd8063aChris Craik    return false;
29014e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
29114e513058ed4168c94e015638d16f5f87fd8063aChris Craik
292984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonbool CanvasState::quickRejectConservative(float left, float top,
29314e513058ed4168c94e015638d16f5f87fd8063aChris Craik        float right, float bottom) const {
29414e513058ed4168c94e015638d16f5f87fd8063aChris Craik    if (mSnapshot->isIgnored() || bottom <= top || right <= left) {
29514e513058ed4168c94e015638d16f5f87fd8063aChris Craik        return true;
29614e513058ed4168c94e015638d16f5f87fd8063aChris Craik    }
29714e513058ed4168c94e015638d16f5f87fd8063aChris Craik
29814e513058ed4168c94e015638d16f5f87fd8063aChris Craik    Rect r(left, top, right, bottom);
299d6b65f67717025b1162f86f04e2caa5723566cacChris Craik    currentTransform()->mapRect(r);
30014e513058ed4168c94e015638d16f5f87fd8063aChris Craik    r.roundOut(); // rounded out to be conservative
30114e513058ed4168c94e015638d16f5f87fd8063aChris Craik
3026fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    Rect clipRect(currentRenderTargetClip());
30314e513058ed4168c94e015638d16f5f87fd8063aChris Craik    clipRect.snapToPixelBoundaries();
30414e513058ed4168c94e015638d16f5f87fd8063aChris Craik
30514e513058ed4168c94e015638d16f5f87fd8063aChris Craik    if (!clipRect.intersects(r)) return true;
30614e513058ed4168c94e015638d16f5f87fd8063aChris Craik
30714e513058ed4168c94e015638d16f5f87fd8063aChris Craik    return false;
30814e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
30914e513058ed4168c94e015638d16f5f87fd8063aChris Craik
310984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson} // namespace uirenderer
311984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson} // namespace android
312