ClipArea.cpp revision 04d46eb69fb4f4c4c332c36c6ae845da3b2ae848
1487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 2487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * Copyright (C) 2015 The Android Open Source Project 3487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * 4487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * Licensed under the Apache License, Version 2.0 (the "License"); 5487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * you may not use this file except in compliance with the License. 6487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * You may obtain a copy of the License at 7487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * 8487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * http://www.apache.org/licenses/LICENSE-2.0 9487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * 10487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * Unless required by applicable law or agreed to in writing, software 11487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * distributed under the License is distributed on an "AS IS" BASIS, 12487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * See the License for the specific language governing permissions and 14487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * limitations under the License. 15487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 16487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk#include "ClipArea.h" 17487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 18e4db79de127cfe961195f52907af8451026eaa20Chris Craik#include "utils/LinearAllocator.h" 19e4db79de127cfe961195f52907af8451026eaa20Chris Craik 20487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk#include <SkPath.h> 21487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk#include <limits> 22e4db79de127cfe961195f52907af8451026eaa20Chris Craik#include <type_traits> 23487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 24487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuknamespace android { 25487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuknamespace uirenderer { 26487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 27487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukstatic void handlePoint(Rect& transformedBounds, const Matrix4& transform, float x, float y) { 284d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik Vertex v = {x, y}; 29487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk transform.mapPoint(v.x, v.y); 3015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik transformedBounds.expandToCover(v.x, v.y); 31487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 32487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 33487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukRect transformAndCalculateBounds(const Rect& r, const Matrix4& transform) { 34487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const float kMinFloat = std::numeric_limits<float>::lowest(); 35487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const float kMaxFloat = std::numeric_limits<float>::max(); 36487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk Rect transformedBounds = { kMaxFloat, kMaxFloat, kMinFloat, kMinFloat }; 37487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk handlePoint(transformedBounds, transform, r.left, r.top); 38487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk handlePoint(transformedBounds, transform, r.right, r.top); 39487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk handlePoint(transformedBounds, transform, r.left, r.bottom); 40487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk handlePoint(transformedBounds, transform, r.right, r.bottom); 41487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return transformedBounds; 42487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 43487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 4402806288d1c56475413888a934c796e6e4eb11c5Chris Craikvoid ClipBase::dump() const { 4502806288d1c56475413888a934c796e6e4eb11c5Chris Craik ALOGD("mode %d" RECT_STRING, mode, RECT_ARGS(rect)); 4602806288d1c56475413888a934c796e6e4eb11c5Chris Craik} 4702806288d1c56475413888a934c796e6e4eb11c5Chris Craik 48487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 49487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * TransformedRectangle 50487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 51487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 52487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukTransformedRectangle::TransformedRectangle() { 53487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 54487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 55487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukTransformedRectangle::TransformedRectangle(const Rect& bounds, 56487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const Matrix4& transform) 57487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk : mBounds(bounds) 58487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk , mTransform(transform) { 59487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 60487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 61487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool TransformedRectangle::canSimplyIntersectWith( 62487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const TransformedRectangle& other) const { 63487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 64487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return mTransform == other.mTransform; 65487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 66487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 67ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craikvoid TransformedRectangle::intersectWith(const TransformedRectangle& other) { 68ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik mBounds.doIntersect(other.mBounds); 69487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 70487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 71487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool TransformedRectangle::isEmpty() const { 72487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return mBounds.isEmpty(); 73487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 74487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 75487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 76487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * RectangleList 77487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 78487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 79487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukRectangleList::RectangleList() 80487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk : mTransformedRectanglesCount(0) { 81487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 82487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 83487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool RectangleList::isEmpty() const { 84487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (mTransformedRectanglesCount < 1) { 85487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return true; 86487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 87487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 88487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk for (int i = 0; i < mTransformedRectanglesCount; i++) { 89487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (mTransformedRectangles[i].isEmpty()) { 90487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return true; 91487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 92487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 93487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return false; 94487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 95487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 96487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukint RectangleList::getTransformedRectanglesCount() const { 97487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return mTransformedRectanglesCount; 98487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 99487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 100487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukconst TransformedRectangle& RectangleList::getTransformedRectangle(int i) const { 101487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return mTransformedRectangles[i]; 102487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 103487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 104487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid RectangleList::setEmpty() { 105487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mTransformedRectanglesCount = 0; 106487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 107487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 108487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid RectangleList::set(const Rect& bounds, const Matrix4& transform) { 109487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mTransformedRectanglesCount = 1; 110487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mTransformedRectangles[0] = TransformedRectangle(bounds, transform); 111487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 112487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 113487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool RectangleList::intersectWith(const Rect& bounds, 114487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const Matrix4& transform) { 115487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk TransformedRectangle newRectangle(bounds, transform); 116487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 117487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // Try to find a rectangle with a compatible transformation 118487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk int index = 0; 119487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk for (; index < mTransformedRectanglesCount; index++) { 120487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk TransformedRectangle& tr(mTransformedRectangles[index]); 121487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (tr.canSimplyIntersectWith(newRectangle)) { 122487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk tr.intersectWith(newRectangle); 123487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return true; 124487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 125487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 126487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 127487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // Add it to the list if there is room 128487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (index < kMaxTransformedRectangles) { 129487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mTransformedRectangles[index] = newRectangle; 130487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mTransformedRectanglesCount += 1; 131487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return true; 132487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 133487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 134487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // This rectangle list is full 135487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return false; 136487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 137487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 138487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukRect RectangleList::calculateBounds() const { 139487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk Rect bounds; 140487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk for (int index = 0; index < mTransformedRectanglesCount; index++) { 141487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const TransformedRectangle& tr(mTransformedRectangles[index]); 142487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (index == 0) { 143487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk bounds = tr.transformedBounds(); 144487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } else { 145ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik bounds.doIntersect(tr.transformedBounds()); 146487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 147487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 148487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return bounds; 149487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 150487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 151487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukstatic SkPath pathFromTransformedRectangle(const Rect& bounds, 152487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const Matrix4& transform) { 153487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkPath rectPath; 154487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkPath rectPathTransformed; 155487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk rectPath.addRect(bounds.left, bounds.top, bounds.right, bounds.bottom); 156487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkMatrix skTransform; 157487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk transform.copyTo(skTransform); 158487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk rectPath.transform(skTransform, &rectPathTransformed); 159487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return rectPathTransformed; 160487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 161487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 162487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukSkRegion RectangleList::convertToRegion(const SkRegion& clip) const { 163487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion rectangleListAsRegion; 164487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk for (int index = 0; index < mTransformedRectanglesCount; index++) { 165487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const TransformedRectangle& tr(mTransformedRectangles[index]); 166487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkPath rectPathTransformed = pathFromTransformedRectangle( 167487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk tr.getBounds(), tr.getTransform()); 168487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (index == 0) { 169487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk rectangleListAsRegion.setPath(rectPathTransformed, clip); 170487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } else { 171487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion rectRegion; 172487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk rectRegion.setPath(rectPathTransformed, clip); 173487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk rectangleListAsRegion.op(rectRegion, SkRegion::kIntersect_Op); 174487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 175487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 176487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return rectangleListAsRegion; 177487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 178487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 179e4db79de127cfe961195f52907af8451026eaa20Chris Craikvoid RectangleList::transform(const Matrix4& transform) { 180e4db79de127cfe961195f52907af8451026eaa20Chris Craik for (int index = 0; index < mTransformedRectanglesCount; index++) { 181e4db79de127cfe961195f52907af8451026eaa20Chris Craik mTransformedRectangles[index].transform(transform); 182e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 183e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 184e4db79de127cfe961195f52907af8451026eaa20Chris Craik 185487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 186487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * ClipArea 187487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 188487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 189487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukClipArea::ClipArea() 190e4db79de127cfe961195f52907af8451026eaa20Chris Craik : mMode(ClipMode::Rectangle) { 191487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 192487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 193487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 194487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * Interface 195487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 196487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 197487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::setViewportDimensions(int width, int height) { 198e4db79de127cfe961195f52907af8451026eaa20Chris Craik mPostViewportClipObserved = false; 199487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mViewportBounds.set(0, 0, width, height); 200487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect = mViewportBounds; 201487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 202487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 203487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::setEmpty() { 204e4db79de127cfe961195f52907af8451026eaa20Chris Craik onClipUpdated(); 205e4db79de127cfe961195f52907af8451026eaa20Chris Craik mMode = ClipMode::Rectangle; 206487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect.setEmpty(); 207487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.setEmpty(); 208487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mRectangleList.setEmpty(); 209487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 210487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 211487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::setClip(float left, float top, float right, float bottom) { 212e4db79de127cfe961195f52907af8451026eaa20Chris Craik onClipUpdated(); 213e4db79de127cfe961195f52907af8451026eaa20Chris Craik mMode = ClipMode::Rectangle; 214487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect.set(left, top, right, bottom); 215487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.setEmpty(); 216487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 217487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 2184d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid ClipArea::clipRectWithTransform(const Rect& r, const mat4* transform, 219487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion::Op op) { 22004d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik if (op == SkRegion::kReplace_Op) mReplaceOpObserved = true; 2217fc1b0349bc2ac8c880120dc5611f703faa7f06fChris Craik if (!mPostViewportClipObserved && op == SkRegion::kIntersect_Op) op = SkRegion::kReplace_Op; 222e4db79de127cfe961195f52907af8451026eaa20Chris Craik onClipUpdated(); 223487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk switch (mMode) { 224e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::Rectangle: 2254d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik rectangleModeClipRectWithTransform(r, transform, op); 2264d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik break; 227e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::RectangleList: 2284d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik rectangleListModeClipRectWithTransform(r, transform, op); 2294d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik break; 230e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::Region: 2314d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik regionModeClipRectWithTransform(r, transform, op); 2324d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik break; 233487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 234487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 235487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 2364d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid ClipArea::clipRegion(const SkRegion& region, SkRegion::Op op) { 23704d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik if (op == SkRegion::kReplace_Op) mReplaceOpObserved = true; 2387fc1b0349bc2ac8c880120dc5611f703faa7f06fChris Craik if (!mPostViewportClipObserved && op == SkRegion::kIntersect_Op) op = SkRegion::kReplace_Op; 239e4db79de127cfe961195f52907af8451026eaa20Chris Craik onClipUpdated(); 240487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk enterRegionMode(); 241487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.op(region, op); 242e30b53cec5eb6eaa5d24231feb3207b917c1baabTom Hudson onClipRegionUpdated(); 243487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 244487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 2454d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid ClipArea::clipPathWithTransform(const SkPath& path, const mat4* transform, 246487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion::Op op) { 24704d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik if (op == SkRegion::kReplace_Op) mReplaceOpObserved = true; 2487fc1b0349bc2ac8c880120dc5611f703faa7f06fChris Craik if (!mPostViewportClipObserved && op == SkRegion::kIntersect_Op) op = SkRegion::kReplace_Op; 249e4db79de127cfe961195f52907af8451026eaa20Chris Craik onClipUpdated(); 250487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkMatrix skTransform; 251487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk transform->copyTo(skTransform); 252487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkPath transformed; 253487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk path.transform(skTransform, &transformed); 254487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion region; 255487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk regionFromPath(transformed, region); 2564d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik clipRegion(region, op); 257487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 258487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 259487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 260487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * Rectangle mode 261487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 262487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 263487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::enterRectangleMode() { 264487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // Entering rectangle mode discards any 265487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // existing clipping information from the other modes. 266487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // The only way this occurs is by a clip setting operation. 267e4db79de127cfe961195f52907af8451026eaa20Chris Craik mMode = ClipMode::Rectangle; 268487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 269487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 2704d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid ClipArea::rectangleModeClipRectWithTransform(const Rect& r, 271487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const mat4* transform, SkRegion::Op op) { 272487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 2738ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris Craik if (op == SkRegion::kReplace_Op && transform->rectToRect()) { 2748ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris Craik mClipRect = r; 2758ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris Craik transform->mapRect(mClipRect); 2764d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik return; 2778ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris Craik } else if (op != SkRegion::kIntersect_Op) { 278487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk enterRegionMode(); 2794d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik regionModeClipRectWithTransform(r, transform, op); 2804d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik return; 281487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 282487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 283487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (transform->rectToRect()) { 284487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk Rect transformed(r); 285487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk transform->mapRect(transformed); 286ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik mClipRect.doIntersect(transformed); 2874d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik return; 288487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 289487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 290487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk enterRectangleListMode(); 2914d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik rectangleListModeClipRectWithTransform(r, transform, op); 292487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 293487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 294487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 295487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * RectangleList mode implementation 296487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 297487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 298487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::enterRectangleListMode() { 299487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // Is is only legal to enter rectangle list mode from 300487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // rectangle mode, since rectangle list mode cannot represent 301487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // all clip areas that can be represented by a region. 302e4db79de127cfe961195f52907af8451026eaa20Chris Craik ALOG_ASSERT(mMode == ClipMode::Rectangle); 303e4db79de127cfe961195f52907af8451026eaa20Chris Craik mMode = ClipMode::RectangleList; 304487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mRectangleList.set(mClipRect, Matrix4::identity()); 305487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 306487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 3074d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid ClipArea::rectangleListModeClipRectWithTransform(const Rect& r, 308487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const mat4* transform, SkRegion::Op op) { 309487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (op != SkRegion::kIntersect_Op 310487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk || !mRectangleList.intersectWith(r, *transform)) { 311487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk enterRegionMode(); 3124d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik regionModeClipRectWithTransform(r, transform, op); 313487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 314487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 315487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 316487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 317487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * Region mode implementation 318487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 319487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 320487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::enterRegionMode() { 321e4db79de127cfe961195f52907af8451026eaa20Chris Craik ClipMode oldMode = mMode; 322e4db79de127cfe961195f52907af8451026eaa20Chris Craik mMode = ClipMode::Region; 323e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (oldMode != ClipMode::Region) { 324e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (oldMode == ClipMode::Rectangle) { 325e4db79de127cfe961195f52907af8451026eaa20Chris Craik mClipRegion.setRect(mClipRect.toSkIRect()); 326487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } else { 327487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion = mRectangleList.convertToRegion(createViewportRegion()); 328e30b53cec5eb6eaa5d24231feb3207b917c1baabTom Hudson onClipRegionUpdated(); 329487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 330487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 331487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 332487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 3334d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid ClipArea::regionModeClipRectWithTransform(const Rect& r, 334487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const mat4* transform, SkRegion::Op op) { 335487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkPath transformedRect = pathFromTransformedRectangle(r, *transform); 336487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion transformedRectRegion; 337487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk regionFromPath(transformedRect, transformedRectRegion); 338487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.op(transformedRectRegion, op); 339e30b53cec5eb6eaa5d24231feb3207b917c1baabTom Hudson onClipRegionUpdated(); 340487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 341487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 342e30b53cec5eb6eaa5d24231feb3207b917c1baabTom Hudsonvoid ClipArea::onClipRegionUpdated() { 343487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (!mClipRegion.isEmpty()) { 344487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect.set(mClipRegion.getBounds()); 345487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 346487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (mClipRegion.isRect()) { 347487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.setEmpty(); 348e30b53cec5eb6eaa5d24231feb3207b917c1baabTom Hudson enterRectangleMode(); 349487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 350487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } else { 351487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect.setEmpty(); 352487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 353487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 354487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 355e4db79de127cfe961195f52907af8451026eaa20Chris Craik/** 356e4db79de127cfe961195f52907af8451026eaa20Chris Craik * Clip serialization 357e4db79de127cfe961195f52907af8451026eaa20Chris Craik */ 358e4db79de127cfe961195f52907af8451026eaa20Chris Craik 359e4db79de127cfe961195f52907af8451026eaa20Chris Craikconst ClipBase* ClipArea::serializeClip(LinearAllocator& allocator) { 360e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (!mPostViewportClipObserved) { 361e4db79de127cfe961195f52907af8451026eaa20Chris Craik // Only initial clip-to-viewport observed, so no serialization of clip necessary 362e4db79de127cfe961195f52907af8451026eaa20Chris Craik return nullptr; 363e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 364e4db79de127cfe961195f52907af8451026eaa20Chris Craik 365e4db79de127cfe961195f52907af8451026eaa20Chris Craik static_assert(std::is_trivially_destructible<Rect>::value, 366e4db79de127cfe961195f52907af8451026eaa20Chris Craik "expect Rect to be trivially destructible"); 367e4db79de127cfe961195f52907af8451026eaa20Chris Craik static_assert(std::is_trivially_destructible<RectangleList>::value, 368e4db79de127cfe961195f52907af8451026eaa20Chris Craik "expect RectangleList to be trivially destructible"); 369e4db79de127cfe961195f52907af8451026eaa20Chris Craik 370e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (mLastSerialization == nullptr) { 3714f4c60820995bad73d87c2fff4b5c5b1c6b5e027Chris Craik ClipBase* serialization = nullptr; 372e4db79de127cfe961195f52907af8451026eaa20Chris Craik switch (mMode) { 373e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::Rectangle: 374b4f4f3e16d8fbb2905dfc168383213161e988f83Chris Craik serialization = allocator.create<ClipRect>(mClipRect); 375e4db79de127cfe961195f52907af8451026eaa20Chris Craik break; 376e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::RectangleList: 377b4f4f3e16d8fbb2905dfc168383213161e988f83Chris Craik serialization = allocator.create<ClipRectList>(mRectangleList); 378b4f4f3e16d8fbb2905dfc168383213161e988f83Chris Craik serialization->rect = mRectangleList.calculateBounds(); 379e4db79de127cfe961195f52907af8451026eaa20Chris Craik break; 380e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::Region: 381b4f4f3e16d8fbb2905dfc168383213161e988f83Chris Craik serialization = allocator.create<ClipRegion>(mClipRegion); 382b4f4f3e16d8fbb2905dfc168383213161e988f83Chris Craik serialization->rect.set(mClipRegion.getBounds()); 383e4db79de127cfe961195f52907af8451026eaa20Chris Craik break; 384e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 38504d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik serialization->intersectWithRoot = mReplaceOpObserved; 38669aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik // TODO: this is only done for draw time, should eventually avoid for record time 38769aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik serialization->rect.snapToPixelBoundaries(); 388b4f4f3e16d8fbb2905dfc168383213161e988f83Chris Craik mLastSerialization = serialization; 389e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 390e4db79de127cfe961195f52907af8451026eaa20Chris Craik return mLastSerialization; 391e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 392e4db79de127cfe961195f52907af8451026eaa20Chris Craik 393e4db79de127cfe961195f52907af8451026eaa20Chris Craikinline static const RectangleList& getRectList(const ClipBase* scb) { 394e4db79de127cfe961195f52907af8451026eaa20Chris Craik return reinterpret_cast<const ClipRectList*>(scb)->rectList; 395e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 396e4db79de127cfe961195f52907af8451026eaa20Chris Craik 397e4db79de127cfe961195f52907af8451026eaa20Chris Craikinline static const SkRegion& getRegion(const ClipBase* scb) { 398e4db79de127cfe961195f52907af8451026eaa20Chris Craik return reinterpret_cast<const ClipRegion*>(scb)->region; 399e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 400e4db79de127cfe961195f52907af8451026eaa20Chris Craik 401e4db79de127cfe961195f52907af8451026eaa20Chris Craik// Conservative check for too many rectangles to fit in rectangle list. 402e4db79de127cfe961195f52907af8451026eaa20Chris Craik// For simplicity, doesn't account for rect merging 403e4db79de127cfe961195f52907af8451026eaa20Chris Craikstatic bool cannotFitInRectangleList(const ClipArea& clipArea, const ClipBase* scb) { 404e4db79de127cfe961195f52907af8451026eaa20Chris Craik int currentRectCount = clipArea.isRectangleList() 405e4db79de127cfe961195f52907af8451026eaa20Chris Craik ? clipArea.getRectangleList().getTransformedRectanglesCount() 406e4db79de127cfe961195f52907af8451026eaa20Chris Craik : 1; 407e4db79de127cfe961195f52907af8451026eaa20Chris Craik int recordedRectCount = (scb->mode == ClipMode::RectangleList) 408e4db79de127cfe961195f52907af8451026eaa20Chris Craik ? getRectList(scb).getTransformedRectanglesCount() 409e4db79de127cfe961195f52907af8451026eaa20Chris Craik : 1; 410e4db79de127cfe961195f52907af8451026eaa20Chris Craik return currentRectCount + recordedRectCount > RectangleList::kMaxTransformedRectangles; 411e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 412e4db79de127cfe961195f52907af8451026eaa20Chris Craik 413261725fdb2962271c222a049fcdf57bbdc8363c7Chris Craikstatic const ClipRect sEmptyClipRect(Rect(0, 0)); 414261725fdb2962271c222a049fcdf57bbdc8363c7Chris Craik 415e4db79de127cfe961195f52907af8451026eaa20Chris Craikconst ClipBase* ClipArea::serializeIntersectedClip(LinearAllocator& allocator, 416e4db79de127cfe961195f52907af8451026eaa20Chris Craik const ClipBase* recordedClip, const Matrix4& recordedClipTransform) { 417261725fdb2962271c222a049fcdf57bbdc8363c7Chris Craik 418e4db79de127cfe961195f52907af8451026eaa20Chris Craik // if no recordedClip passed, just serialize current state 419e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (!recordedClip) return serializeClip(allocator); 420e4db79de127cfe961195f52907af8451026eaa20Chris Craik 421261725fdb2962271c222a049fcdf57bbdc8363c7Chris Craik // if either is empty, clip is empty 422261725fdb2962271c222a049fcdf57bbdc8363c7Chris Craik if (CC_UNLIKELY(recordedClip->rect.isEmpty())|| mClipRect.isEmpty()) return &sEmptyClipRect; 423261725fdb2962271c222a049fcdf57bbdc8363c7Chris Craik 424e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (!mLastResolutionResult 425e4db79de127cfe961195f52907af8451026eaa20Chris Craik || recordedClip != mLastResolutionClip 426e4db79de127cfe961195f52907af8451026eaa20Chris Craik || recordedClipTransform != mLastResolutionTransform) { 427e4db79de127cfe961195f52907af8451026eaa20Chris Craik mLastResolutionClip = recordedClip; 428e4db79de127cfe961195f52907af8451026eaa20Chris Craik mLastResolutionTransform = recordedClipTransform; 429e4db79de127cfe961195f52907af8451026eaa20Chris Craik 430e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (CC_LIKELY(mMode == ClipMode::Rectangle 431e4db79de127cfe961195f52907af8451026eaa20Chris Craik && recordedClip->mode == ClipMode::Rectangle 432e4db79de127cfe961195f52907af8451026eaa20Chris Craik && recordedClipTransform.rectToRect())) { 433e4db79de127cfe961195f52907af8451026eaa20Chris Craik // common case - result is a single rectangle 43469aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik auto rectClip = allocator.create<ClipRect>(recordedClip->rect); 435e4db79de127cfe961195f52907af8451026eaa20Chris Craik recordedClipTransform.mapRect(rectClip->rect); 436e4db79de127cfe961195f52907af8451026eaa20Chris Craik rectClip->rect.doIntersect(mClipRect); 43769aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik rectClip->rect.snapToPixelBoundaries(); 438e4db79de127cfe961195f52907af8451026eaa20Chris Craik mLastResolutionResult = rectClip; 439e4db79de127cfe961195f52907af8451026eaa20Chris Craik } else if (CC_UNLIKELY(mMode == ClipMode::Region 440e4db79de127cfe961195f52907af8451026eaa20Chris Craik || recordedClip->mode == ClipMode::Region 441e4db79de127cfe961195f52907af8451026eaa20Chris Craik || cannotFitInRectangleList(*this, recordedClip))) { 442e4db79de127cfe961195f52907af8451026eaa20Chris Craik // region case 443e4db79de127cfe961195f52907af8451026eaa20Chris Craik SkRegion other; 444e4db79de127cfe961195f52907af8451026eaa20Chris Craik switch (recordedClip->mode) { 445e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::Rectangle: 446e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (CC_LIKELY(recordedClipTransform.rectToRect())) { 447e4db79de127cfe961195f52907af8451026eaa20Chris Craik // simple transform, skip creating SkPath 44869aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik Rect resultClip(recordedClip->rect); 449e4db79de127cfe961195f52907af8451026eaa20Chris Craik recordedClipTransform.mapRect(resultClip); 450e4db79de127cfe961195f52907af8451026eaa20Chris Craik other.setRect(resultClip.toSkIRect()); 451e4db79de127cfe961195f52907af8451026eaa20Chris Craik } else { 45269aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik SkPath transformedRect = pathFromTransformedRectangle(recordedClip->rect, 453e4db79de127cfe961195f52907af8451026eaa20Chris Craik recordedClipTransform); 454e4db79de127cfe961195f52907af8451026eaa20Chris Craik other.setPath(transformedRect, createViewportRegion()); 455e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 456e4db79de127cfe961195f52907af8451026eaa20Chris Craik break; 457e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::RectangleList: { 458e4db79de127cfe961195f52907af8451026eaa20Chris Craik RectangleList transformedList(getRectList(recordedClip)); 459e4db79de127cfe961195f52907af8451026eaa20Chris Craik transformedList.transform(recordedClipTransform); 460e4db79de127cfe961195f52907af8451026eaa20Chris Craik other = transformedList.convertToRegion(createViewportRegion()); 461e4db79de127cfe961195f52907af8451026eaa20Chris Craik break; 462e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 463e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::Region: 464e4db79de127cfe961195f52907af8451026eaa20Chris Craik other = getRegion(recordedClip); 465e4db79de127cfe961195f52907af8451026eaa20Chris Craik 466e4db79de127cfe961195f52907af8451026eaa20Chris Craik // TODO: handle non-translate transforms properly! 467e4db79de127cfe961195f52907af8451026eaa20Chris Craik other.translate(recordedClipTransform.getTranslateX(), 468e4db79de127cfe961195f52907af8451026eaa20Chris Craik recordedClipTransform.getTranslateY()); 469e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 470e4db79de127cfe961195f52907af8451026eaa20Chris Craik 471e4db79de127cfe961195f52907af8451026eaa20Chris Craik ClipRegion* regionClip = allocator.create<ClipRegion>(); 472e4db79de127cfe961195f52907af8451026eaa20Chris Craik switch (mMode) { 473e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::Rectangle: 474e4db79de127cfe961195f52907af8451026eaa20Chris Craik regionClip->region.op(mClipRect.toSkIRect(), other, SkRegion::kIntersect_Op); 475e4db79de127cfe961195f52907af8451026eaa20Chris Craik break; 476e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::RectangleList: 477e4db79de127cfe961195f52907af8451026eaa20Chris Craik regionClip->region.op(mRectangleList.convertToRegion(createViewportRegion()), 478e4db79de127cfe961195f52907af8451026eaa20Chris Craik other, SkRegion::kIntersect_Op); 479e4db79de127cfe961195f52907af8451026eaa20Chris Craik break; 480e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::Region: 481e4db79de127cfe961195f52907af8451026eaa20Chris Craik regionClip->region.op(mClipRegion, other, SkRegion::kIntersect_Op); 482e4db79de127cfe961195f52907af8451026eaa20Chris Craik break; 483e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 48469aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik // Don't need to snap, since region's in int bounds 485e4db79de127cfe961195f52907af8451026eaa20Chris Craik regionClip->rect.set(regionClip->region.getBounds()); 486e4db79de127cfe961195f52907af8451026eaa20Chris Craik mLastResolutionResult = regionClip; 487e4db79de127cfe961195f52907af8451026eaa20Chris Craik } else { 488e4db79de127cfe961195f52907af8451026eaa20Chris Craik auto rectListClip = allocator.create<ClipRectList>(mRectangleList); 489e4db79de127cfe961195f52907af8451026eaa20Chris Craik auto&& rectList = rectListClip->rectList; 490e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (mMode == ClipMode::Rectangle) { 491e4db79de127cfe961195f52907af8451026eaa20Chris Craik rectList.set(mClipRect, Matrix4::identity()); 492e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 493e4db79de127cfe961195f52907af8451026eaa20Chris Craik 494e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (recordedClip->mode == ClipMode::Rectangle) { 49569aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik rectList.intersectWith(recordedClip->rect, recordedClipTransform); 496e4db79de127cfe961195f52907af8451026eaa20Chris Craik } else { 497e4db79de127cfe961195f52907af8451026eaa20Chris Craik const RectangleList& other = getRectList(recordedClip); 498e4db79de127cfe961195f52907af8451026eaa20Chris Craik for (int i = 0; i < other.getTransformedRectanglesCount(); i++) { 499e4db79de127cfe961195f52907af8451026eaa20Chris Craik auto&& tr = other.getTransformedRectangle(i); 500e4db79de127cfe961195f52907af8451026eaa20Chris Craik Matrix4 totalTransform(recordedClipTransform); 501e4db79de127cfe961195f52907af8451026eaa20Chris Craik totalTransform.multiply(tr.getTransform()); 502e4db79de127cfe961195f52907af8451026eaa20Chris Craik rectList.intersectWith(tr.getBounds(), totalTransform); 503e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 504e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 505e4db79de127cfe961195f52907af8451026eaa20Chris Craik rectListClip->rect = rectList.calculateBounds(); 50669aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik rectListClip->rect.snapToPixelBoundaries(); 507e4db79de127cfe961195f52907af8451026eaa20Chris Craik mLastResolutionResult = rectListClip; 508e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 509e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 510e4db79de127cfe961195f52907af8451026eaa20Chris Craik return mLastResolutionResult; 511e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 512e4db79de127cfe961195f52907af8451026eaa20Chris Craik 513e4db79de127cfe961195f52907af8451026eaa20Chris Craikvoid ClipArea::applyClip(const ClipBase* clip, const Matrix4& transform) { 514e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (!clip) return; // nothing to do 515e4db79de127cfe961195f52907af8451026eaa20Chris Craik 516e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (CC_LIKELY(clip->mode == ClipMode::Rectangle)) { 51769aeabe6184bbbe6e731656205ffbef78b7b0f3fChris Craik clipRectWithTransform(clip->rect, &transform, SkRegion::kIntersect_Op); 518e4db79de127cfe961195f52907af8451026eaa20Chris Craik } else if (CC_LIKELY(clip->mode == ClipMode::RectangleList)) { 519e4db79de127cfe961195f52907af8451026eaa20Chris Craik auto&& rectList = getRectList(clip); 520e4db79de127cfe961195f52907af8451026eaa20Chris Craik for (int i = 0; i < rectList.getTransformedRectanglesCount(); i++) { 521e4db79de127cfe961195f52907af8451026eaa20Chris Craik auto&& tr = rectList.getTransformedRectangle(i); 522e4db79de127cfe961195f52907af8451026eaa20Chris Craik Matrix4 totalTransform(transform); 523e4db79de127cfe961195f52907af8451026eaa20Chris Craik totalTransform.multiply(tr.getTransform()); 524e4db79de127cfe961195f52907af8451026eaa20Chris Craik clipRectWithTransform(tr.getBounds(), &totalTransform, SkRegion::kIntersect_Op); 525e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 526e4db79de127cfe961195f52907af8451026eaa20Chris Craik } else { 527e4db79de127cfe961195f52907af8451026eaa20Chris Craik SkRegion region(getRegion(clip)); 528e4db79de127cfe961195f52907af8451026eaa20Chris Craik // TODO: handle non-translate transforms properly! 529e4db79de127cfe961195f52907af8451026eaa20Chris Craik region.translate(transform.getTranslateX(), transform.getTranslateY()); 530e4db79de127cfe961195f52907af8451026eaa20Chris Craik clipRegion(region, SkRegion::kIntersect_Op); 531e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 532e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 533e4db79de127cfe961195f52907af8451026eaa20Chris Craik 534487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} /* namespace uirenderer */ 535487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} /* namespace android */ 536