ClipArea.cpp revision e4db79de127cfe961195f52907af8451026eaa20
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 44487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 45487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * TransformedRectangle 46487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 47487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 48487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukTransformedRectangle::TransformedRectangle() { 49487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 50487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 51487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukTransformedRectangle::TransformedRectangle(const Rect& bounds, 52487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const Matrix4& transform) 53487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk : mBounds(bounds) 54487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk , mTransform(transform) { 55487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 56487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 57487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool TransformedRectangle::canSimplyIntersectWith( 58487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const TransformedRectangle& other) const { 59487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 60487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return mTransform == other.mTransform; 61487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 62487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 63ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craikvoid TransformedRectangle::intersectWith(const TransformedRectangle& other) { 64ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik mBounds.doIntersect(other.mBounds); 65487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 66487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 67487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool TransformedRectangle::isEmpty() const { 68487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return mBounds.isEmpty(); 69487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 70487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 71487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 72487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * RectangleList 73487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 74487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 75487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukRectangleList::RectangleList() 76487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk : mTransformedRectanglesCount(0) { 77487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 78487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 79487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool RectangleList::isEmpty() const { 80487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (mTransformedRectanglesCount < 1) { 81487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return true; 82487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 83487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 84487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk for (int i = 0; i < mTransformedRectanglesCount; i++) { 85487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (mTransformedRectangles[i].isEmpty()) { 86487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return true; 87487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 88487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 89487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return false; 90487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 91487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 92487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukint RectangleList::getTransformedRectanglesCount() const { 93487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return mTransformedRectanglesCount; 94487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 95487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 96487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukconst TransformedRectangle& RectangleList::getTransformedRectangle(int i) const { 97487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return mTransformedRectangles[i]; 98487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 99487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 100487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid RectangleList::setEmpty() { 101487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mTransformedRectanglesCount = 0; 102487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 103487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 104487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid RectangleList::set(const Rect& bounds, const Matrix4& transform) { 105487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mTransformedRectanglesCount = 1; 106487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mTransformedRectangles[0] = TransformedRectangle(bounds, transform); 107487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 108487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 109487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool RectangleList::intersectWith(const Rect& bounds, 110487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const Matrix4& transform) { 111487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk TransformedRectangle newRectangle(bounds, transform); 112487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 113487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // Try to find a rectangle with a compatible transformation 114487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk int index = 0; 115487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk for (; index < mTransformedRectanglesCount; index++) { 116487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk TransformedRectangle& tr(mTransformedRectangles[index]); 117487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (tr.canSimplyIntersectWith(newRectangle)) { 118487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk tr.intersectWith(newRectangle); 119487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return true; 120487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 121487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 122487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 123487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // Add it to the list if there is room 124487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (index < kMaxTransformedRectangles) { 125487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mTransformedRectangles[index] = newRectangle; 126487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mTransformedRectanglesCount += 1; 127487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return true; 128487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 129487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 130487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // This rectangle list is full 131487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return false; 132487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 133487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 134487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukRect RectangleList::calculateBounds() const { 135487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk Rect bounds; 136487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk for (int index = 0; index < mTransformedRectanglesCount; index++) { 137487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const TransformedRectangle& tr(mTransformedRectangles[index]); 138487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (index == 0) { 139487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk bounds = tr.transformedBounds(); 140487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } else { 141ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik bounds.doIntersect(tr.transformedBounds()); 142487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 143487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 144487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return bounds; 145487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 146487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 147487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukstatic SkPath pathFromTransformedRectangle(const Rect& bounds, 148487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const Matrix4& transform) { 149487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkPath rectPath; 150487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkPath rectPathTransformed; 151487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk rectPath.addRect(bounds.left, bounds.top, bounds.right, bounds.bottom); 152487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkMatrix skTransform; 153487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk transform.copyTo(skTransform); 154487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk rectPath.transform(skTransform, &rectPathTransformed); 155487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return rectPathTransformed; 156487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 157487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 158487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukSkRegion RectangleList::convertToRegion(const SkRegion& clip) const { 159487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion rectangleListAsRegion; 160487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk for (int index = 0; index < mTransformedRectanglesCount; index++) { 161487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const TransformedRectangle& tr(mTransformedRectangles[index]); 162487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkPath rectPathTransformed = pathFromTransformedRectangle( 163487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk tr.getBounds(), tr.getTransform()); 164487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (index == 0) { 165487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk rectangleListAsRegion.setPath(rectPathTransformed, clip); 166487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } else { 167487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion rectRegion; 168487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk rectRegion.setPath(rectPathTransformed, clip); 169487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk rectangleListAsRegion.op(rectRegion, SkRegion::kIntersect_Op); 170487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 171487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 172487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return rectangleListAsRegion; 173487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 174487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 175e4db79de127cfe961195f52907af8451026eaa20Chris Craikvoid RectangleList::transform(const Matrix4& transform) { 176e4db79de127cfe961195f52907af8451026eaa20Chris Craik for (int index = 0; index < mTransformedRectanglesCount; index++) { 177e4db79de127cfe961195f52907af8451026eaa20Chris Craik mTransformedRectangles[index].transform(transform); 178e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 179e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 180e4db79de127cfe961195f52907af8451026eaa20Chris Craik 181487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 182487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * ClipArea 183487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 184487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 185487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukClipArea::ClipArea() 186e4db79de127cfe961195f52907af8451026eaa20Chris Craik : mMode(ClipMode::Rectangle) { 187487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 188487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 189487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 190487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * Interface 191487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 192487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 193487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::setViewportDimensions(int width, int height) { 194e4db79de127cfe961195f52907af8451026eaa20Chris Craik mPostViewportClipObserved = false; 195487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mViewportBounds.set(0, 0, width, height); 196487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect = mViewportBounds; 197487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 198487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 199487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::setEmpty() { 200e4db79de127cfe961195f52907af8451026eaa20Chris Craik onClipUpdated(); 201e4db79de127cfe961195f52907af8451026eaa20Chris Craik mMode = ClipMode::Rectangle; 202487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect.setEmpty(); 203487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.setEmpty(); 204487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mRectangleList.setEmpty(); 205487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 206487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 207487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::setClip(float left, float top, float right, float bottom) { 208e4db79de127cfe961195f52907af8451026eaa20Chris Craik onClipUpdated(); 209e4db79de127cfe961195f52907af8451026eaa20Chris Craik mMode = ClipMode::Rectangle; 210487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect.set(left, top, right, bottom); 211487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.setEmpty(); 212487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 213487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 2144d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid ClipArea::clipRectWithTransform(const Rect& r, const mat4* transform, 215487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion::Op op) { 216e4db79de127cfe961195f52907af8451026eaa20Chris Craik onClipUpdated(); 217487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk switch (mMode) { 218e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::Rectangle: 2194d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik rectangleModeClipRectWithTransform(r, transform, op); 2204d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik break; 221e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::RectangleList: 2224d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik rectangleListModeClipRectWithTransform(r, transform, op); 2234d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik break; 224e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::Region: 2254d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik regionModeClipRectWithTransform(r, transform, op); 2264d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik break; 227487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 228487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 229487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 2304d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid ClipArea::clipRegion(const SkRegion& region, SkRegion::Op op) { 231e4db79de127cfe961195f52907af8451026eaa20Chris Craik onClipUpdated(); 232487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk enterRegionMode(); 233487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.op(region, op); 234e30b53cec5eb6eaa5d24231feb3207b917c1baabTom Hudson onClipRegionUpdated(); 235487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 236487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 2374d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid ClipArea::clipPathWithTransform(const SkPath& path, const mat4* transform, 238487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion::Op op) { 239e4db79de127cfe961195f52907af8451026eaa20Chris Craik onClipUpdated(); 240487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkMatrix skTransform; 241487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk transform->copyTo(skTransform); 242487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkPath transformed; 243487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk path.transform(skTransform, &transformed); 244487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion region; 245487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk regionFromPath(transformed, region); 2464d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik clipRegion(region, op); 247487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 248487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 249487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 250487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * Rectangle mode 251487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 252487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 253487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::enterRectangleMode() { 254487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // Entering rectangle mode discards any 255487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // existing clipping information from the other modes. 256487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // The only way this occurs is by a clip setting operation. 257e4db79de127cfe961195f52907af8451026eaa20Chris Craik mMode = ClipMode::Rectangle; 258487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 259487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 2604d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid ClipArea::rectangleModeClipRectWithTransform(const Rect& r, 261487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const mat4* transform, SkRegion::Op op) { 262487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 2638ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris Craik if (op == SkRegion::kReplace_Op && transform->rectToRect()) { 2648ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris Craik mClipRect = r; 2658ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris Craik transform->mapRect(mClipRect); 2664d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik return; 2678ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris Craik } else if (op != SkRegion::kIntersect_Op) { 268487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk enterRegionMode(); 2694d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik regionModeClipRectWithTransform(r, transform, op); 2704d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik return; 271487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 272487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 273487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (transform->rectToRect()) { 274487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk Rect transformed(r); 275487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk transform->mapRect(transformed); 276ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik mClipRect.doIntersect(transformed); 2774d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik return; 278487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 279487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 280487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk enterRectangleListMode(); 2814d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik rectangleListModeClipRectWithTransform(r, transform, op); 282487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 283487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 284487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 285487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * RectangleList mode implementation 286487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 287487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 288487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::enterRectangleListMode() { 289487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // Is is only legal to enter rectangle list mode from 290487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // rectangle mode, since rectangle list mode cannot represent 291487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // all clip areas that can be represented by a region. 292e4db79de127cfe961195f52907af8451026eaa20Chris Craik ALOG_ASSERT(mMode == ClipMode::Rectangle); 293e4db79de127cfe961195f52907af8451026eaa20Chris Craik mMode = ClipMode::RectangleList; 294487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mRectangleList.set(mClipRect, Matrix4::identity()); 295487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 296487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 2974d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid ClipArea::rectangleListModeClipRectWithTransform(const Rect& r, 298487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const mat4* transform, SkRegion::Op op) { 299487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (op != SkRegion::kIntersect_Op 300487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk || !mRectangleList.intersectWith(r, *transform)) { 301487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk enterRegionMode(); 3024d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik regionModeClipRectWithTransform(r, transform, op); 303487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 304487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 305487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 306487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 307487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * Region mode implementation 308487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 309487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 310487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::enterRegionMode() { 311e4db79de127cfe961195f52907af8451026eaa20Chris Craik ClipMode oldMode = mMode; 312e4db79de127cfe961195f52907af8451026eaa20Chris Craik mMode = ClipMode::Region; 313e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (oldMode != ClipMode::Region) { 314e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (oldMode == ClipMode::Rectangle) { 315e4db79de127cfe961195f52907af8451026eaa20Chris Craik mClipRegion.setRect(mClipRect.toSkIRect()); 316487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } else { 317487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion = mRectangleList.convertToRegion(createViewportRegion()); 318e30b53cec5eb6eaa5d24231feb3207b917c1baabTom Hudson onClipRegionUpdated(); 319487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 320487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 321487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 322487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 3234d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid ClipArea::regionModeClipRectWithTransform(const Rect& r, 324487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const mat4* transform, SkRegion::Op op) { 325487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkPath transformedRect = pathFromTransformedRectangle(r, *transform); 326487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion transformedRectRegion; 327487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk regionFromPath(transformedRect, transformedRectRegion); 328487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.op(transformedRectRegion, op); 329e30b53cec5eb6eaa5d24231feb3207b917c1baabTom Hudson onClipRegionUpdated(); 330487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 331487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 332e30b53cec5eb6eaa5d24231feb3207b917c1baabTom Hudsonvoid ClipArea::onClipRegionUpdated() { 333487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (!mClipRegion.isEmpty()) { 334487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect.set(mClipRegion.getBounds()); 335487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 336487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (mClipRegion.isRect()) { 337487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.setEmpty(); 338e30b53cec5eb6eaa5d24231feb3207b917c1baabTom Hudson enterRectangleMode(); 339487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 340487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } else { 341487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect.setEmpty(); 342487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 343487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 344487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 345e4db79de127cfe961195f52907af8451026eaa20Chris Craik/** 346e4db79de127cfe961195f52907af8451026eaa20Chris Craik * Clip serialization 347e4db79de127cfe961195f52907af8451026eaa20Chris Craik */ 348e4db79de127cfe961195f52907af8451026eaa20Chris Craik 349e4db79de127cfe961195f52907af8451026eaa20Chris Craikconst ClipBase* ClipArea::serializeClip(LinearAllocator& allocator) { 350e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (!mPostViewportClipObserved) { 351e4db79de127cfe961195f52907af8451026eaa20Chris Craik // Only initial clip-to-viewport observed, so no serialization of clip necessary 352e4db79de127cfe961195f52907af8451026eaa20Chris Craik return nullptr; 353e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 354e4db79de127cfe961195f52907af8451026eaa20Chris Craik 355e4db79de127cfe961195f52907af8451026eaa20Chris Craik static_assert(std::is_trivially_destructible<Rect>::value, 356e4db79de127cfe961195f52907af8451026eaa20Chris Craik "expect Rect to be trivially destructible"); 357e4db79de127cfe961195f52907af8451026eaa20Chris Craik static_assert(std::is_trivially_destructible<RectangleList>::value, 358e4db79de127cfe961195f52907af8451026eaa20Chris Craik "expect RectangleList to be trivially destructible"); 359e4db79de127cfe961195f52907af8451026eaa20Chris Craik 360e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (mLastSerialization == nullptr) { 361e4db79de127cfe961195f52907af8451026eaa20Chris Craik switch (mMode) { 362e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::Rectangle: 363e4db79de127cfe961195f52907af8451026eaa20Chris Craik mLastSerialization = allocator.create<ClipRect>(mClipRect); 364e4db79de127cfe961195f52907af8451026eaa20Chris Craik break; 365e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::RectangleList: 366e4db79de127cfe961195f52907af8451026eaa20Chris Craik mLastSerialization = allocator.create<ClipRectList>(mRectangleList); 367e4db79de127cfe961195f52907af8451026eaa20Chris Craik break; 368e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::Region: 369e4db79de127cfe961195f52907af8451026eaa20Chris Craik mLastSerialization = allocator.create<ClipRegion>(mClipRegion); 370e4db79de127cfe961195f52907af8451026eaa20Chris Craik break; 371e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 372e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 373e4db79de127cfe961195f52907af8451026eaa20Chris Craik return mLastSerialization; 374e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 375e4db79de127cfe961195f52907af8451026eaa20Chris Craik 376e4db79de127cfe961195f52907af8451026eaa20Chris Craikinline static const Rect& getRect(const ClipBase* scb) { 377e4db79de127cfe961195f52907af8451026eaa20Chris Craik return reinterpret_cast<const ClipRect*>(scb)->rect; 378e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 379e4db79de127cfe961195f52907af8451026eaa20Chris Craik 380e4db79de127cfe961195f52907af8451026eaa20Chris Craikinline static const RectangleList& getRectList(const ClipBase* scb) { 381e4db79de127cfe961195f52907af8451026eaa20Chris Craik return reinterpret_cast<const ClipRectList*>(scb)->rectList; 382e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 383e4db79de127cfe961195f52907af8451026eaa20Chris Craik 384e4db79de127cfe961195f52907af8451026eaa20Chris Craikinline static const SkRegion& getRegion(const ClipBase* scb) { 385e4db79de127cfe961195f52907af8451026eaa20Chris Craik return reinterpret_cast<const ClipRegion*>(scb)->region; 386e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 387e4db79de127cfe961195f52907af8451026eaa20Chris Craik 388e4db79de127cfe961195f52907af8451026eaa20Chris Craik// Conservative check for too many rectangles to fit in rectangle list. 389e4db79de127cfe961195f52907af8451026eaa20Chris Craik// For simplicity, doesn't account for rect merging 390e4db79de127cfe961195f52907af8451026eaa20Chris Craikstatic bool cannotFitInRectangleList(const ClipArea& clipArea, const ClipBase* scb) { 391e4db79de127cfe961195f52907af8451026eaa20Chris Craik int currentRectCount = clipArea.isRectangleList() 392e4db79de127cfe961195f52907af8451026eaa20Chris Craik ? clipArea.getRectangleList().getTransformedRectanglesCount() 393e4db79de127cfe961195f52907af8451026eaa20Chris Craik : 1; 394e4db79de127cfe961195f52907af8451026eaa20Chris Craik int recordedRectCount = (scb->mode == ClipMode::RectangleList) 395e4db79de127cfe961195f52907af8451026eaa20Chris Craik ? getRectList(scb).getTransformedRectanglesCount() 396e4db79de127cfe961195f52907af8451026eaa20Chris Craik : 1; 397e4db79de127cfe961195f52907af8451026eaa20Chris Craik return currentRectCount + recordedRectCount > RectangleList::kMaxTransformedRectangles; 398e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 399e4db79de127cfe961195f52907af8451026eaa20Chris Craik 400e4db79de127cfe961195f52907af8451026eaa20Chris Craikconst ClipBase* ClipArea::serializeIntersectedClip(LinearAllocator& allocator, 401e4db79de127cfe961195f52907af8451026eaa20Chris Craik const ClipBase* recordedClip, const Matrix4& recordedClipTransform) { 402e4db79de127cfe961195f52907af8451026eaa20Chris Craik // if no recordedClip passed, just serialize current state 403e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (!recordedClip) return serializeClip(allocator); 404e4db79de127cfe961195f52907af8451026eaa20Chris Craik 405e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (!mLastResolutionResult 406e4db79de127cfe961195f52907af8451026eaa20Chris Craik || recordedClip != mLastResolutionClip 407e4db79de127cfe961195f52907af8451026eaa20Chris Craik || recordedClipTransform != mLastResolutionTransform) { 408e4db79de127cfe961195f52907af8451026eaa20Chris Craik mLastResolutionClip = recordedClip; 409e4db79de127cfe961195f52907af8451026eaa20Chris Craik mLastResolutionTransform = recordedClipTransform; 410e4db79de127cfe961195f52907af8451026eaa20Chris Craik 411e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (CC_LIKELY(mMode == ClipMode::Rectangle 412e4db79de127cfe961195f52907af8451026eaa20Chris Craik && recordedClip->mode == ClipMode::Rectangle 413e4db79de127cfe961195f52907af8451026eaa20Chris Craik && recordedClipTransform.rectToRect())) { 414e4db79de127cfe961195f52907af8451026eaa20Chris Craik // common case - result is a single rectangle 415e4db79de127cfe961195f52907af8451026eaa20Chris Craik auto rectClip = allocator.create<ClipRect>(getRect(recordedClip)); 416e4db79de127cfe961195f52907af8451026eaa20Chris Craik recordedClipTransform.mapRect(rectClip->rect); 417e4db79de127cfe961195f52907af8451026eaa20Chris Craik rectClip->rect.doIntersect(mClipRect); 418e4db79de127cfe961195f52907af8451026eaa20Chris Craik mLastResolutionResult = rectClip; 419e4db79de127cfe961195f52907af8451026eaa20Chris Craik } else if (CC_UNLIKELY(mMode == ClipMode::Region 420e4db79de127cfe961195f52907af8451026eaa20Chris Craik || recordedClip->mode == ClipMode::Region 421e4db79de127cfe961195f52907af8451026eaa20Chris Craik || cannotFitInRectangleList(*this, recordedClip))) { 422e4db79de127cfe961195f52907af8451026eaa20Chris Craik // region case 423e4db79de127cfe961195f52907af8451026eaa20Chris Craik SkRegion other; 424e4db79de127cfe961195f52907af8451026eaa20Chris Craik switch (recordedClip->mode) { 425e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::Rectangle: 426e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (CC_LIKELY(recordedClipTransform.rectToRect())) { 427e4db79de127cfe961195f52907af8451026eaa20Chris Craik // simple transform, skip creating SkPath 428e4db79de127cfe961195f52907af8451026eaa20Chris Craik Rect resultClip(getRect(recordedClip)); 429e4db79de127cfe961195f52907af8451026eaa20Chris Craik recordedClipTransform.mapRect(resultClip); 430e4db79de127cfe961195f52907af8451026eaa20Chris Craik other.setRect(resultClip.toSkIRect()); 431e4db79de127cfe961195f52907af8451026eaa20Chris Craik } else { 432e4db79de127cfe961195f52907af8451026eaa20Chris Craik SkPath transformedRect = pathFromTransformedRectangle(getRect(recordedClip), 433e4db79de127cfe961195f52907af8451026eaa20Chris Craik recordedClipTransform); 434e4db79de127cfe961195f52907af8451026eaa20Chris Craik other.setPath(transformedRect, createViewportRegion()); 435e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 436e4db79de127cfe961195f52907af8451026eaa20Chris Craik break; 437e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::RectangleList: { 438e4db79de127cfe961195f52907af8451026eaa20Chris Craik RectangleList transformedList(getRectList(recordedClip)); 439e4db79de127cfe961195f52907af8451026eaa20Chris Craik transformedList.transform(recordedClipTransform); 440e4db79de127cfe961195f52907af8451026eaa20Chris Craik other = transformedList.convertToRegion(createViewportRegion()); 441e4db79de127cfe961195f52907af8451026eaa20Chris Craik break; 442e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 443e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::Region: 444e4db79de127cfe961195f52907af8451026eaa20Chris Craik other = getRegion(recordedClip); 445e4db79de127cfe961195f52907af8451026eaa20Chris Craik 446e4db79de127cfe961195f52907af8451026eaa20Chris Craik // TODO: handle non-translate transforms properly! 447e4db79de127cfe961195f52907af8451026eaa20Chris Craik other.translate(recordedClipTransform.getTranslateX(), 448e4db79de127cfe961195f52907af8451026eaa20Chris Craik recordedClipTransform.getTranslateY()); 449e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 450e4db79de127cfe961195f52907af8451026eaa20Chris Craik 451e4db79de127cfe961195f52907af8451026eaa20Chris Craik ClipRegion* regionClip = allocator.create<ClipRegion>(); 452e4db79de127cfe961195f52907af8451026eaa20Chris Craik switch (mMode) { 453e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::Rectangle: 454e4db79de127cfe961195f52907af8451026eaa20Chris Craik regionClip->region.op(mClipRect.toSkIRect(), other, SkRegion::kIntersect_Op); 455e4db79de127cfe961195f52907af8451026eaa20Chris Craik break; 456e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::RectangleList: 457e4db79de127cfe961195f52907af8451026eaa20Chris Craik regionClip->region.op(mRectangleList.convertToRegion(createViewportRegion()), 458e4db79de127cfe961195f52907af8451026eaa20Chris Craik other, SkRegion::kIntersect_Op); 459e4db79de127cfe961195f52907af8451026eaa20Chris Craik break; 460e4db79de127cfe961195f52907af8451026eaa20Chris Craik case ClipMode::Region: 461e4db79de127cfe961195f52907af8451026eaa20Chris Craik regionClip->region.op(mClipRegion, other, SkRegion::kIntersect_Op); 462e4db79de127cfe961195f52907af8451026eaa20Chris Craik break; 463e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 464e4db79de127cfe961195f52907af8451026eaa20Chris Craik regionClip->rect.set(regionClip->region.getBounds()); 465e4db79de127cfe961195f52907af8451026eaa20Chris Craik mLastResolutionResult = regionClip; 466e4db79de127cfe961195f52907af8451026eaa20Chris Craik } else { 467e4db79de127cfe961195f52907af8451026eaa20Chris Craik auto rectListClip = allocator.create<ClipRectList>(mRectangleList); 468e4db79de127cfe961195f52907af8451026eaa20Chris Craik auto&& rectList = rectListClip->rectList; 469e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (mMode == ClipMode::Rectangle) { 470e4db79de127cfe961195f52907af8451026eaa20Chris Craik rectList.set(mClipRect, Matrix4::identity()); 471e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 472e4db79de127cfe961195f52907af8451026eaa20Chris Craik 473e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (recordedClip->mode == ClipMode::Rectangle) { 474e4db79de127cfe961195f52907af8451026eaa20Chris Craik rectList.intersectWith(getRect(recordedClip), recordedClipTransform); 475e4db79de127cfe961195f52907af8451026eaa20Chris Craik } else { 476e4db79de127cfe961195f52907af8451026eaa20Chris Craik const RectangleList& other = getRectList(recordedClip); 477e4db79de127cfe961195f52907af8451026eaa20Chris Craik for (int i = 0; i < other.getTransformedRectanglesCount(); i++) { 478e4db79de127cfe961195f52907af8451026eaa20Chris Craik auto&& tr = other.getTransformedRectangle(i); 479e4db79de127cfe961195f52907af8451026eaa20Chris Craik Matrix4 totalTransform(recordedClipTransform); 480e4db79de127cfe961195f52907af8451026eaa20Chris Craik totalTransform.multiply(tr.getTransform()); 481e4db79de127cfe961195f52907af8451026eaa20Chris Craik rectList.intersectWith(tr.getBounds(), totalTransform); 482e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 483e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 484e4db79de127cfe961195f52907af8451026eaa20Chris Craik rectListClip->rect = rectList.calculateBounds(); 485e4db79de127cfe961195f52907af8451026eaa20Chris Craik mLastResolutionResult = rectListClip; 486e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 487e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 488e4db79de127cfe961195f52907af8451026eaa20Chris Craik return mLastResolutionResult; 489e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 490e4db79de127cfe961195f52907af8451026eaa20Chris Craik 491e4db79de127cfe961195f52907af8451026eaa20Chris Craikvoid ClipArea::applyClip(const ClipBase* clip, const Matrix4& transform) { 492e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (!clip) return; // nothing to do 493e4db79de127cfe961195f52907af8451026eaa20Chris Craik 494e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (CC_LIKELY(clip->mode == ClipMode::Rectangle)) { 495e4db79de127cfe961195f52907af8451026eaa20Chris Craik clipRectWithTransform(getRect(clip), &transform, SkRegion::kIntersect_Op); 496e4db79de127cfe961195f52907af8451026eaa20Chris Craik } else if (CC_LIKELY(clip->mode == ClipMode::RectangleList)) { 497e4db79de127cfe961195f52907af8451026eaa20Chris Craik auto&& rectList = getRectList(clip); 498e4db79de127cfe961195f52907af8451026eaa20Chris Craik for (int i = 0; i < rectList.getTransformedRectanglesCount(); i++) { 499e4db79de127cfe961195f52907af8451026eaa20Chris Craik auto&& tr = rectList.getTransformedRectangle(i); 500e4db79de127cfe961195f52907af8451026eaa20Chris Craik Matrix4 totalTransform(transform); 501e4db79de127cfe961195f52907af8451026eaa20Chris Craik totalTransform.multiply(tr.getTransform()); 502e4db79de127cfe961195f52907af8451026eaa20Chris Craik clipRectWithTransform(tr.getBounds(), &totalTransform, SkRegion::kIntersect_Op); 503e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 504e4db79de127cfe961195f52907af8451026eaa20Chris Craik } else { 505e4db79de127cfe961195f52907af8451026eaa20Chris Craik SkRegion region(getRegion(clip)); 506e4db79de127cfe961195f52907af8451026eaa20Chris Craik // TODO: handle non-translate transforms properly! 507e4db79de127cfe961195f52907af8451026eaa20Chris Craik region.translate(transform.getTranslateX(), transform.getTranslateY()); 508e4db79de127cfe961195f52907af8451026eaa20Chris Craik clipRegion(region, SkRegion::kIntersect_Op); 509e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 510e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 511e4db79de127cfe961195f52907af8451026eaa20Chris Craik 512487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} /* namespace uirenderer */ 513487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} /* namespace android */ 514