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