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
17984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson#include "CanvasState.h"
18dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include "hwui/Canvas.h"
19af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik#include "utils/MathUtils.h"
20af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik
2114e513058ed4168c94e015638d16f5f87fd8063aChris Craiknamespace android {
2214e513058ed4168c94e015638d16f5f87fd8063aChris Craiknamespace uirenderer {
2314e513058ed4168c94e015638d16f5f87fd8063aChris Craik
24984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
25984162fb7e4010b6e2908352dbff17ed47eecf06Tom HudsonCanvasState::CanvasState(CanvasStateClient& renderer)
265e00c7ce063116c11315639f0035aca8ad73e8ccChris Craik        : mWidth(-1)
27058fc640017c90120c599d378a4cbc55668b05b7Chris Craik        , mHeight(-1)
28058fc640017c90120c599d378a4cbc55668b05b7Chris Craik        , mSaveCount(1)
29984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson        , mCanvas(renderer)
30d9ee550888011a64fa3f35e666360ec8278597d8John Reck        , mSnapshot(&mFirstSnapshot) {
31d9ee550888011a64fa3f35e666360ec8278597d8John Reck}
32d9ee550888011a64fa3f35e666360ec8278597d8John Reck
33d9ee550888011a64fa3f35e666360ec8278597d8John ReckCanvasState::~CanvasState() {
34d9ee550888011a64fa3f35e666360ec8278597d8John Reck    // First call freeSnapshot on all but mFirstSnapshot
35d9ee550888011a64fa3f35e666360ec8278597d8John Reck    // to invoke all the dtors
36d9ee550888011a64fa3f35e666360ec8278597d8John Reck    freeAllSnapshots();
37984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson
38d9ee550888011a64fa3f35e666360ec8278597d8John Reck    // Now actually release the memory
39d9ee550888011a64fa3f35e666360ec8278597d8John Reck    while (mSnapshotPool) {
40d9ee550888011a64fa3f35e666360ec8278597d8John Reck        void* temp = mSnapshotPool;
41d9ee550888011a64fa3f35e666360ec8278597d8John Reck        mSnapshotPool = mSnapshotPool->previous;
42d9ee550888011a64fa3f35e666360ec8278597d8John Reck        free(temp);
43d9ee550888011a64fa3f35e666360ec8278597d8John Reck    }
4414e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
4514e513058ed4168c94e015638d16f5f87fd8063aChris Craik
46e4db79de127cfe961195f52907af8451026eaa20Chris Craikvoid CanvasState::initializeRecordingSaveStack(int viewportWidth, int viewportHeight) {
47e4db79de127cfe961195f52907af8451026eaa20Chris Craik    if (mWidth != viewportWidth || mHeight != viewportHeight) {
48e4db79de127cfe961195f52907af8451026eaa20Chris Craik        mWidth = viewportWidth;
49e4db79de127cfe961195f52907af8451026eaa20Chris Craik        mHeight = viewportHeight;
50e4db79de127cfe961195f52907af8451026eaa20Chris Craik        mFirstSnapshot.initializeViewport(viewportWidth, viewportHeight);
51e4db79de127cfe961195f52907af8451026eaa20Chris Craik        mCanvas.onViewportInitialized();
52e4db79de127cfe961195f52907af8451026eaa20Chris Craik    }
53e4db79de127cfe961195f52907af8451026eaa20Chris Craik
54e4db79de127cfe961195f52907af8451026eaa20Chris Craik    freeAllSnapshots();
55eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    mSnapshot = allocSnapshot(&mFirstSnapshot, SaveFlags::MatrixClip);
56e4db79de127cfe961195f52907af8451026eaa20Chris Craik    mSnapshot->setRelativeLightCenter(Vector3());
57e4db79de127cfe961195f52907af8451026eaa20Chris Craik    mSaveCount = 1;
58e4db79de127cfe961195f52907af8451026eaa20Chris Craik}
59e4db79de127cfe961195f52907af8451026eaa20Chris Craik
6064e445bf74bee2098781d608cedfd723d8cc88d3Chris Craikvoid CanvasState::initializeSaveStack(
6164e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik        int viewportWidth, int viewportHeight,
6264e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik        float clipLeft, float clipTop,
6369e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik        float clipRight, float clipBottom, const Vector3& lightCenter) {
6464e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik    if (mWidth != viewportWidth || mHeight != viewportHeight) {
6564e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik        mWidth = viewportWidth;
6664e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik        mHeight = viewportHeight;
67d9ee550888011a64fa3f35e666360ec8278597d8John Reck        mFirstSnapshot.initializeViewport(viewportWidth, viewportHeight);
6864e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik        mCanvas.onViewportInitialized();
6964e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik    }
7064e445bf74bee2098781d608cedfd723d8cc88d3Chris Craik
71d9ee550888011a64fa3f35e666360ec8278597d8John Reck    freeAllSnapshots();
72eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita    mSnapshot = allocSnapshot(&mFirstSnapshot, SaveFlags::MatrixClip);
7314e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSnapshot->setClip(clipLeft, clipTop, clipRight, clipBottom);
746b109c74982033d4a220cd10a0eab8b024b351c9Chris Craik    mSnapshot->fbo = mCanvas.getTargetFbo();
7569e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik    mSnapshot->setRelativeLightCenter(lightCenter);
7614e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSaveCount = 1;
7714e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
7814e513058ed4168c94e015638d16f5f87fd8063aChris Craik
79d9ee550888011a64fa3f35e666360ec8278597d8John ReckSnapshot* CanvasState::allocSnapshot(Snapshot* previous, int savecount) {
80d9ee550888011a64fa3f35e666360ec8278597d8John Reck    void* memory;
81d9ee550888011a64fa3f35e666360ec8278597d8John Reck    if (mSnapshotPool) {
82d9ee550888011a64fa3f35e666360ec8278597d8John Reck        memory = mSnapshotPool;
83d9ee550888011a64fa3f35e666360ec8278597d8John Reck        mSnapshotPool = mSnapshotPool->previous;
84d9ee550888011a64fa3f35e666360ec8278597d8John Reck        mSnapshotPoolCount--;
85d9ee550888011a64fa3f35e666360ec8278597d8John Reck    } else {
86d9ee550888011a64fa3f35e666360ec8278597d8John Reck        memory = malloc(sizeof(Snapshot));
87d9ee550888011a64fa3f35e666360ec8278597d8John Reck    }
88d9ee550888011a64fa3f35e666360ec8278597d8John Reck    return new (memory) Snapshot(previous, savecount);
89d9ee550888011a64fa3f35e666360ec8278597d8John Reck}
90d9ee550888011a64fa3f35e666360ec8278597d8John Reck
91d9ee550888011a64fa3f35e666360ec8278597d8John Reckvoid CanvasState::freeSnapshot(Snapshot* snapshot) {
92d9ee550888011a64fa3f35e666360ec8278597d8John Reck    snapshot->~Snapshot();
93d9ee550888011a64fa3f35e666360ec8278597d8John Reck    // Arbitrary number, just don't let this grown unbounded
94d9ee550888011a64fa3f35e666360ec8278597d8John Reck    if (mSnapshotPoolCount > 10) {
95d9ee550888011a64fa3f35e666360ec8278597d8John Reck        free((void*) snapshot);
96d9ee550888011a64fa3f35e666360ec8278597d8John Reck    } else {
97d9ee550888011a64fa3f35e666360ec8278597d8John Reck        snapshot->previous = mSnapshotPool;
98d9ee550888011a64fa3f35e666360ec8278597d8John Reck        mSnapshotPool = snapshot;
99d9ee550888011a64fa3f35e666360ec8278597d8John Reck        mSnapshotPoolCount++;
100d9ee550888011a64fa3f35e666360ec8278597d8John Reck    }
101d9ee550888011a64fa3f35e666360ec8278597d8John Reck}
102d9ee550888011a64fa3f35e666360ec8278597d8John Reck
103d9ee550888011a64fa3f35e666360ec8278597d8John Reckvoid CanvasState::freeAllSnapshots() {
104d9ee550888011a64fa3f35e666360ec8278597d8John Reck    while (mSnapshot != &mFirstSnapshot) {
105d9ee550888011a64fa3f35e666360ec8278597d8John Reck        Snapshot* temp = mSnapshot;
106d9ee550888011a64fa3f35e666360ec8278597d8John Reck        mSnapshot = mSnapshot->previous;
107d9ee550888011a64fa3f35e666360ec8278597d8John Reck        freeSnapshot(temp);
108d9ee550888011a64fa3f35e666360ec8278597d8John Reck    }
109d9ee550888011a64fa3f35e666360ec8278597d8John Reck}
110d9ee550888011a64fa3f35e666360ec8278597d8John Reck
11114e513058ed4168c94e015638d16f5f87fd8063aChris Craik///////////////////////////////////////////////////////////////////////////////
11214e513058ed4168c94e015638d16f5f87fd8063aChris Craik// Save (layer)
11314e513058ed4168c94e015638d16f5f87fd8063aChris Craik///////////////////////////////////////////////////////////////////////////////
11414e513058ed4168c94e015638d16f5f87fd8063aChris Craik
11514e513058ed4168c94e015638d16f5f87fd8063aChris Craik/**
116984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson * Guaranteed to save without side-effects
11714e513058ed4168c94e015638d16f5f87fd8063aChris Craik *
118984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson * This approach, here and in restoreSnapshot(), allows subclasses to directly manipulate the save
11914e513058ed4168c94e015638d16f5f87fd8063aChris Craik * stack, and ensures restoreToCount() doesn't call back into subclass overrides.
12014e513058ed4168c94e015638d16f5f87fd8063aChris Craik */
121984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonint CanvasState::saveSnapshot(int flags) {
122d9ee550888011a64fa3f35e666360ec8278597d8John Reck    mSnapshot = allocSnapshot(mSnapshot, flags);
12314e513058ed4168c94e015638d16f5f87fd8063aChris Craik    return mSaveCount++;
12414e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
12514e513058ed4168c94e015638d16f5f87fd8063aChris Craik
126984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonint CanvasState::save(int flags) {
12714e513058ed4168c94e015638d16f5f87fd8063aChris Craik    return saveSnapshot(flags);
12814e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
12914e513058ed4168c94e015638d16f5f87fd8063aChris Craik
13014e513058ed4168c94e015638d16f5f87fd8063aChris Craik/**
131984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson * Guaranteed to restore without side-effects.
13214e513058ed4168c94e015638d16f5f87fd8063aChris Craik */
133984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::restoreSnapshot() {
134d9ee550888011a64fa3f35e666360ec8278597d8John Reck    Snapshot* toRemove = mSnapshot;
135d9ee550888011a64fa3f35e666360ec8278597d8John Reck    Snapshot* toRestore = mSnapshot->previous;
13614e513058ed4168c94e015638d16f5f87fd8063aChris Craik
13714e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSaveCount--;
13814e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSnapshot = toRestore;
13914e513058ed4168c94e015638d16f5f87fd8063aChris Craik
14014e513058ed4168c94e015638d16f5f87fd8063aChris Craik    // subclass handles restore implementation
141984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson    mCanvas.onSnapshotRestored(*toRemove, *toRestore);
142d9ee550888011a64fa3f35e666360ec8278597d8John Reck
143d9ee550888011a64fa3f35e666360ec8278597d8John Reck    freeSnapshot(toRemove);
14414e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
14514e513058ed4168c94e015638d16f5f87fd8063aChris Craik
146984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::restore() {
14714e513058ed4168c94e015638d16f5f87fd8063aChris Craik    if (mSaveCount > 1) {
14814e513058ed4168c94e015638d16f5f87fd8063aChris Craik        restoreSnapshot();
14914e513058ed4168c94e015638d16f5f87fd8063aChris Craik    }
15014e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
15114e513058ed4168c94e015638d16f5f87fd8063aChris Craik
152984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::restoreToCount(int saveCount) {
15314e513058ed4168c94e015638d16f5f87fd8063aChris Craik    if (saveCount < 1) saveCount = 1;
15414e513058ed4168c94e015638d16f5f87fd8063aChris Craik
15514e513058ed4168c94e015638d16f5f87fd8063aChris Craik    while (mSaveCount > saveCount) {
15614e513058ed4168c94e015638d16f5f87fd8063aChris Craik        restoreSnapshot();
15714e513058ed4168c94e015638d16f5f87fd8063aChris Craik    }
15814e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
15914e513058ed4168c94e015638d16f5f87fd8063aChris Craik
16014e513058ed4168c94e015638d16f5f87fd8063aChris Craik///////////////////////////////////////////////////////////////////////////////
16114e513058ed4168c94e015638d16f5f87fd8063aChris Craik// Matrix
16214e513058ed4168c94e015638d16f5f87fd8063aChris Craik///////////////////////////////////////////////////////////////////////////////
16314e513058ed4168c94e015638d16f5f87fd8063aChris Craik
164984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::getMatrix(SkMatrix* matrix) const {
16514e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSnapshot->transform->copyTo(*matrix);
16614e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
16714e513058ed4168c94e015638d16f5f87fd8063aChris Craik
168984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::translate(float dx, float dy, float dz) {
16914e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSnapshot->transform->translate(dx, dy, dz);
17014e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
17114e513058ed4168c94e015638d16f5f87fd8063aChris Craik
172984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::rotate(float degrees) {
17314e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSnapshot->transform->rotate(degrees, 0.0f, 0.0f, 1.0f);
17414e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
17514e513058ed4168c94e015638d16f5f87fd8063aChris Craik
176984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::scale(float sx, float sy) {
17714e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSnapshot->transform->scale(sx, sy, 1.0f);
17814e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
17914e513058ed4168c94e015638d16f5f87fd8063aChris Craik
180984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::skew(float sx, float sy) {
18114e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSnapshot->transform->skew(sx, sy);
18214e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
18314e513058ed4168c94e015638d16f5f87fd8063aChris Craik
184984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::setMatrix(const SkMatrix& matrix) {
185139088228faa7f3c446af7387e017933998a5570Derek Sollenberger    mSnapshot->transform->load(matrix);
18614e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
18714e513058ed4168c94e015638d16f5f87fd8063aChris Craik
188984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::setMatrix(const Matrix4& matrix) {
1897c85c54499994c687a833644f7f213e747fadb98Chris Craik    *(mSnapshot->transform) = matrix;
19014e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
19114e513058ed4168c94e015638d16f5f87fd8063aChris Craik
192984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::concatMatrix(const SkMatrix& matrix) {
193139088228faa7f3c446af7387e017933998a5570Derek Sollenberger    mat4 transform(matrix);
19414e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSnapshot->transform->multiply(transform);
19514e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
19614e513058ed4168c94e015638d16f5f87fd8063aChris Craik
197984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::concatMatrix(const Matrix4& matrix) {
19814e513058ed4168c94e015638d16f5f87fd8063aChris Craik    mSnapshot->transform->multiply(matrix);
19914e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
20014e513058ed4168c94e015638d16f5f87fd8063aChris Craik
20114e513058ed4168c94e015638d16f5f87fd8063aChris Craik///////////////////////////////////////////////////////////////////////////////
20214e513058ed4168c94e015638d16f5f87fd8063aChris Craik// Clip
20314e513058ed4168c94e015638d16f5f87fd8063aChris Craik///////////////////////////////////////////////////////////////////////////////
20414e513058ed4168c94e015638d16f5f87fd8063aChris Craik
2056e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reedbool CanvasState::clipRect(float left, float top, float right, float bottom, SkClipOp op) {
206a2a70723b8cbda4354d23f901f995623e819012cChris Craik    mSnapshot->clip(Rect(left, top, right, bottom), op);
207487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    return !mSnapshot->clipIsEmpty();
208d6b65f67717025b1162f86f04e2caa5723566cacChris Craik}
209d6b65f67717025b1162f86f04e2caa5723566cacChris Craik
2106e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reedbool CanvasState::clipPath(const SkPath* path, SkClipOp op) {
2114d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik    mSnapshot->clipPath(*path, op);
212487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    return !mSnapshot->clipIsEmpty();
213d6b65f67717025b1162f86f04e2caa5723566cacChris Craik}
214d6b65f67717025b1162f86f04e2caa5723566cacChris Craik
215984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonvoid CanvasState::setClippingOutline(LinearAllocator& allocator, const Outline* outline) {
216af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik    Rect bounds;
217af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik    float radius;
218af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik    if (!outline->getAsRoundRect(&bounds, &radius)) return; // only RR supported
219af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik
22079d26c72aa6f898125df2386054f6a293da4122aChris Craik    bool outlineIsRounded = MathUtils::isPositive(radius);
22179d26c72aa6f898125df2386054f6a293da4122aChris Craik    if (!outlineIsRounded || currentTransform()->isSimple()) {
222af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik        // TODO: consider storing this rect separately, so that this can't be replaced with clip ops
2236c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed        clipRect(bounds.left, bounds.top, bounds.right, bounds.bottom, SkClipOp::kIntersect);
224af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik    }
22579d26c72aa6f898125df2386054f6a293da4122aChris Craik    if (outlineIsRounded) {
226e83cbd451868a734bfac07ccd680d5617080b579Chris Craik        setClippingRoundRect(allocator, bounds, radius, false);
22779d26c72aa6f898125df2386054f6a293da4122aChris Craik    }
228deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik}
229deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik
23014e513058ed4168c94e015638d16f5f87fd8063aChris Craik///////////////////////////////////////////////////////////////////////////////
23114e513058ed4168c94e015638d16f5f87fd8063aChris Craik// Quick Rejection
23214e513058ed4168c94e015638d16f5f87fd8063aChris Craik///////////////////////////////////////////////////////////////////////////////
23314e513058ed4168c94e015638d16f5f87fd8063aChris Craik
23414e513058ed4168c94e015638d16f5f87fd8063aChris Craik/**
23514e513058ed4168c94e015638d16f5f87fd8063aChris Craik * Calculates whether content drawn within the passed bounds would be outside of, or intersect with
23614e513058ed4168c94e015638d16f5f87fd8063aChris Craik * the clipRect. Does not modify the scissor.
23714e513058ed4168c94e015638d16f5f87fd8063aChris Craik *
23814e513058ed4168c94e015638d16f5f87fd8063aChris Craik * @param clipRequired if not null, will be set to true if element intersects clip
23914e513058ed4168c94e015638d16f5f87fd8063aChris Craik *         (and wasn't rejected)
24014e513058ed4168c94e015638d16f5f87fd8063aChris Craik *
24114e513058ed4168c94e015638d16f5f87fd8063aChris Craik * @param snapOut if set, the geometry will be treated as having an AA ramp.
24214e513058ed4168c94e015638d16f5f87fd8063aChris Craik *         See Rect::snapGeometryToPixelBoundaries()
24314e513058ed4168c94e015638d16f5f87fd8063aChris Craik */
244984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonbool CanvasState::calculateQuickRejectForScissor(float left, float top,
245deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik        float right, float bottom,
246deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik        bool* clipRequired, bool* roundRectClipRequired,
247deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik        bool snapOut) const {
2485e00c7ce063116c11315639f0035aca8ad73e8ccChris Craik    if (bottom <= top || right <= left) {
24914e513058ed4168c94e015638d16f5f87fd8063aChris Craik        return true;
25014e513058ed4168c94e015638d16f5f87fd8063aChris Craik    }
25114e513058ed4168c94e015638d16f5f87fd8063aChris Craik
25214e513058ed4168c94e015638d16f5f87fd8063aChris Craik    Rect r(left, top, right, bottom);
253d6b65f67717025b1162f86f04e2caa5723566cacChris Craik    currentTransform()->mapRect(r);
25414e513058ed4168c94e015638d16f5f87fd8063aChris Craik    r.snapGeometryToPixelBoundaries(snapOut);
25514e513058ed4168c94e015638d16f5f87fd8063aChris Craik
2566fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    Rect clipRect(currentRenderTargetClip());
25714e513058ed4168c94e015638d16f5f87fd8063aChris Craik    clipRect.snapToPixelBoundaries();
25814e513058ed4168c94e015638d16f5f87fd8063aChris Craik
25914e513058ed4168c94e015638d16f5f87fd8063aChris Craik    if (!clipRect.intersects(r)) return true;
26014e513058ed4168c94e015638d16f5f87fd8063aChris Craik
26114e513058ed4168c94e015638d16f5f87fd8063aChris Craik    // clip is required if geometry intersects clip rect
262deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    if (clipRequired) {
263deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik        *clipRequired = !clipRect.contains(r);
264deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    }
265deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik
266deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    // round rect clip is required if RR clip exists, and geometry intersects its corners
267deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    if (roundRectClipRequired) {
268d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik        *roundRectClipRequired = mSnapshot->roundRectClipState != nullptr
269deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik                && mSnapshot->roundRectClipState->areaRequiresRoundRectClip(r);
270deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    }
27114e513058ed4168c94e015638d16f5f87fd8063aChris Craik    return false;
27214e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
27314e513058ed4168c94e015638d16f5f87fd8063aChris Craik
274984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudsonbool CanvasState::quickRejectConservative(float left, float top,
27514e513058ed4168c94e015638d16f5f87fd8063aChris Craik        float right, float bottom) const {
2765e00c7ce063116c11315639f0035aca8ad73e8ccChris Craik    if (bottom <= top || right <= left) {
27714e513058ed4168c94e015638d16f5f87fd8063aChris Craik        return true;
27814e513058ed4168c94e015638d16f5f87fd8063aChris Craik    }
27914e513058ed4168c94e015638d16f5f87fd8063aChris Craik
28014e513058ed4168c94e015638d16f5f87fd8063aChris Craik    Rect r(left, top, right, bottom);
281d6b65f67717025b1162f86f04e2caa5723566cacChris Craik    currentTransform()->mapRect(r);
28214e513058ed4168c94e015638d16f5f87fd8063aChris Craik    r.roundOut(); // rounded out to be conservative
28314e513058ed4168c94e015638d16f5f87fd8063aChris Craik
2846fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    Rect clipRect(currentRenderTargetClip());
28514e513058ed4168c94e015638d16f5f87fd8063aChris Craik    clipRect.snapToPixelBoundaries();
28614e513058ed4168c94e015638d16f5f87fd8063aChris Craik
28714e513058ed4168c94e015638d16f5f87fd8063aChris Craik    if (!clipRect.intersects(r)) return true;
28814e513058ed4168c94e015638d16f5f87fd8063aChris Craik
28914e513058ed4168c94e015638d16f5f87fd8063aChris Craik    return false;
29014e513058ed4168c94e015638d16f5f87fd8063aChris Craik}
29114e513058ed4168c94e015638d16f5f87fd8063aChris Craik
292984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson} // namespace uirenderer
293984162fb7e4010b6e2908352dbff17ed47eecf06Tom Hudson} // namespace android
294