ClipArea.cpp revision ac02eb9035a13a3d09c2def9ed63d04225eb2509
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 18487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk#include <SkPath.h> 19487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk#include <limits> 20487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 21487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk#include "Rect.h" 22487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 23487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuknamespace android { 24487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuknamespace uirenderer { 25487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 26487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukstatic void handlePoint(Rect& transformedBounds, const Matrix4& transform, float x, float y) { 274d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik Vertex v = {x, y}; 28487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk transform.mapPoint(v.x, v.y); 29487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk transformedBounds.expandToCoverVertex(v.x, v.y); 30487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 31487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 32487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukRect transformAndCalculateBounds(const Rect& r, const Matrix4& transform) { 33487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const float kMinFloat = std::numeric_limits<float>::lowest(); 34487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const float kMaxFloat = std::numeric_limits<float>::max(); 35487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk Rect transformedBounds = { kMaxFloat, kMaxFloat, kMinFloat, kMinFloat }; 36487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk handlePoint(transformedBounds, transform, r.left, r.top); 37487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk handlePoint(transformedBounds, transform, r.right, r.top); 38487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk handlePoint(transformedBounds, transform, r.left, r.bottom); 39487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk handlePoint(transformedBounds, transform, r.right, r.bottom); 40487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return transformedBounds; 41487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 42487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 43487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 44487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * TransformedRectangle 45487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 46487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 47487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukTransformedRectangle::TransformedRectangle() { 48487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 49487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 50487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukTransformedRectangle::TransformedRectangle(const Rect& bounds, 51487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const Matrix4& transform) 52487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk : mBounds(bounds) 53487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk , mTransform(transform) { 54487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 55487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 56487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool TransformedRectangle::canSimplyIntersectWith( 57487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const TransformedRectangle& other) const { 58487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 59487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return mTransform == other.mTransform; 60487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 61487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 62ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craikvoid TransformedRectangle::intersectWith(const TransformedRectangle& other) { 63ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik mBounds.doIntersect(other.mBounds); 64487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 65487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 66487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool TransformedRectangle::isEmpty() const { 67487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return mBounds.isEmpty(); 68487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 69487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 70487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 71487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * RectangleList 72487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 73487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 74487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukRectangleList::RectangleList() 75487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk : mTransformedRectanglesCount(0) { 76487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 77487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 78487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool RectangleList::isEmpty() const { 79487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (mTransformedRectanglesCount < 1) { 80487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return true; 81487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 82487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 83487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk for (int i = 0; i < mTransformedRectanglesCount; i++) { 84487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (mTransformedRectangles[i].isEmpty()) { 85487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return true; 86487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 87487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 88487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return false; 89487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 90487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 91487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukint RectangleList::getTransformedRectanglesCount() const { 92487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return mTransformedRectanglesCount; 93487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 94487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 95487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukconst TransformedRectangle& RectangleList::getTransformedRectangle(int i) const { 96487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return mTransformedRectangles[i]; 97487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 98487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 99487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid RectangleList::setEmpty() { 100487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mTransformedRectanglesCount = 0; 101487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 102487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 103487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid RectangleList::set(const Rect& bounds, const Matrix4& transform) { 104487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mTransformedRectanglesCount = 1; 105487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mTransformedRectangles[0] = TransformedRectangle(bounds, transform); 106487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 107487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 108487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool RectangleList::intersectWith(const Rect& bounds, 109487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const Matrix4& transform) { 110487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk TransformedRectangle newRectangle(bounds, transform); 111487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 112487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // Try to find a rectangle with a compatible transformation 113487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk int index = 0; 114487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk for (; index < mTransformedRectanglesCount; index++) { 115487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk TransformedRectangle& tr(mTransformedRectangles[index]); 116487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (tr.canSimplyIntersectWith(newRectangle)) { 117487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk tr.intersectWith(newRectangle); 118487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return true; 119487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 120487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 121487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 122487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // Add it to the list if there is room 123487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (index < kMaxTransformedRectangles) { 124487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mTransformedRectangles[index] = newRectangle; 125487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mTransformedRectanglesCount += 1; 126487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return true; 127487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 128487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 129487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // This rectangle list is full 130487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return false; 131487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 132487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 133487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukRect RectangleList::calculateBounds() const { 134487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk Rect bounds; 135487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk for (int index = 0; index < mTransformedRectanglesCount; index++) { 136487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const TransformedRectangle& tr(mTransformedRectangles[index]); 137487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (index == 0) { 138487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk bounds = tr.transformedBounds(); 139487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } else { 140ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik bounds.doIntersect(tr.transformedBounds()); 141487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 142487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 143487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return bounds; 144487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 145487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 146487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukstatic SkPath pathFromTransformedRectangle(const Rect& bounds, 147487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const Matrix4& transform) { 148487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkPath rectPath; 149487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkPath rectPathTransformed; 150487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk rectPath.addRect(bounds.left, bounds.top, bounds.right, bounds.bottom); 151487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkMatrix skTransform; 152487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk transform.copyTo(skTransform); 153487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk rectPath.transform(skTransform, &rectPathTransformed); 154487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return rectPathTransformed; 155487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 156487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 157487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukSkRegion RectangleList::convertToRegion(const SkRegion& clip) const { 158487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion rectangleListAsRegion; 159487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk for (int index = 0; index < mTransformedRectanglesCount; index++) { 160487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const TransformedRectangle& tr(mTransformedRectangles[index]); 161487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkPath rectPathTransformed = pathFromTransformedRectangle( 162487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk tr.getBounds(), tr.getTransform()); 163487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (index == 0) { 164487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk rectangleListAsRegion.setPath(rectPathTransformed, clip); 165487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } else { 166487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion rectRegion; 167487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk rectRegion.setPath(rectPathTransformed, clip); 168487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk rectangleListAsRegion.op(rectRegion, SkRegion::kIntersect_Op); 169487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 170487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 171487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return rectangleListAsRegion; 172487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 173487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 174487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 175487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * ClipArea 176487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 177487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 178487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukClipArea::ClipArea() 1794d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik : mMode(Mode::Rectangle) { 180487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 181487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 182487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 183487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * Interface 184487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 185487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 186487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::setViewportDimensions(int width, int height) { 187487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mViewportBounds.set(0, 0, width, height); 188487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect = mViewportBounds; 189487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 190487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 191487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::setEmpty() { 1924d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik mMode = Mode::Rectangle; 193487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect.setEmpty(); 194487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.setEmpty(); 195487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mRectangleList.setEmpty(); 196487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 197487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 198487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::setClip(float left, float top, float right, float bottom) { 1994d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik mMode = Mode::Rectangle; 200487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect.set(left, top, right, bottom); 201487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.setEmpty(); 202487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 203487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 2044d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid ClipArea::clipRectWithTransform(float left, float top, float right, 205487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk float bottom, const mat4* transform, SkRegion::Op op) { 206487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk Rect r(left, top, right, bottom); 2074d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik clipRectWithTransform(r, transform, op); 208487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 209487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 2104d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid ClipArea::clipRectWithTransform(const Rect& r, const mat4* transform, 211487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion::Op op) { 212487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk switch (mMode) { 2134d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik case Mode::Rectangle: 2144d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik rectangleModeClipRectWithTransform(r, transform, op); 2154d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik break; 2164d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik case Mode::RectangleList: 2174d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik rectangleListModeClipRectWithTransform(r, transform, op); 2184d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik break; 2194d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik case Mode::Region: 2204d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik regionModeClipRectWithTransform(r, transform, op); 2214d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik break; 222487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 223487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 224487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 2254d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid ClipArea::clipRegion(const SkRegion& region, SkRegion::Op op) { 226487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk enterRegionMode(); 227487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.op(region, op); 228e30b53cec5eb6eaa5d24231feb3207b917c1baabTom Hudson onClipRegionUpdated(); 229487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 230487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 2314d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid ClipArea::clipPathWithTransform(const SkPath& path, const mat4* transform, 232487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion::Op op) { 233487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkMatrix skTransform; 234487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk transform->copyTo(skTransform); 235487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkPath transformed; 236487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk path.transform(skTransform, &transformed); 237487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion region; 238487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk regionFromPath(transformed, region); 2394d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik clipRegion(region, op); 240487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 241487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 242487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 243487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * Rectangle mode 244487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 245487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 246487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::enterRectangleMode() { 247487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // Entering rectangle mode discards any 248487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // existing clipping information from the other modes. 249487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // The only way this occurs is by a clip setting operation. 2504d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik mMode = Mode::Rectangle; 251487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 252487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 2534d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid ClipArea::rectangleModeClipRectWithTransform(const Rect& r, 254487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const mat4* transform, SkRegion::Op op) { 255487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 2568ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris Craik if (op == SkRegion::kReplace_Op && transform->rectToRect()) { 2578ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris Craik mClipRect = r; 2588ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris Craik transform->mapRect(mClipRect); 2594d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik return; 2608ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris Craik } else if (op != SkRegion::kIntersect_Op) { 261487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk enterRegionMode(); 2624d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik regionModeClipRectWithTransform(r, transform, op); 2634d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik return; 264487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 265487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 266487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (transform->rectToRect()) { 267487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk Rect transformed(r); 268487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk transform->mapRect(transformed); 269ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik mClipRect.doIntersect(transformed); 2704d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik return; 271487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 272487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 273487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk enterRectangleListMode(); 2744d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik rectangleListModeClipRectWithTransform(r, transform, op); 275487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 276487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 2774d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid ClipArea::rectangleModeClipRectWithTransform(float left, float top, 278487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk float right, float bottom, const mat4* transform, SkRegion::Op op) { 279487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk Rect r(left, top, right, bottom); 2804d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik rectangleModeClipRectWithTransform(r, transform, op); 281487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect = mRectangleList.calculateBounds(); 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. 2924d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik ALOG_ASSERT(mMode == Mode::Rectangle); 2934d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik mMode = Mode::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 3064d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid ClipArea::rectangleListModeClipRectWithTransform(float left, float top, 307487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk float right, float bottom, const mat4* transform, SkRegion::Op op) { 308487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk Rect r(left, top, right, bottom); 3094d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik rectangleListModeClipRectWithTransform(r, transform, op); 310487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 311487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 312487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 313487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * Region mode implementation 314487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 315487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 316487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::enterRegionMode() { 317e30b53cec5eb6eaa5d24231feb3207b917c1baabTom Hudson Mode oldMode = mMode; 3184d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik mMode = Mode::Region; 3194d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik if (oldMode != Mode::Region) { 3204d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik if (oldMode == Mode::Rectangle) { 321487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.setRect(mClipRect.left, mClipRect.top, 322487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect.right, mClipRect.bottom); 323487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } else { 324487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion = mRectangleList.convertToRegion(createViewportRegion()); 325e30b53cec5eb6eaa5d24231feb3207b917c1baabTom Hudson onClipRegionUpdated(); 326487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 327487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 328487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 329487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 3304d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid ClipArea::regionModeClipRectWithTransform(const Rect& r, 331487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const mat4* transform, SkRegion::Op op) { 332487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkPath transformedRect = pathFromTransformedRectangle(r, *transform); 333487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion transformedRectRegion; 334487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk regionFromPath(transformedRect, transformedRectRegion); 335487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.op(transformedRectRegion, op); 336e30b53cec5eb6eaa5d24231feb3207b917c1baabTom Hudson onClipRegionUpdated(); 337487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 338487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 3394d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikvoid ClipArea::regionModeClipRectWithTransform(float left, float top, 340487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk float right, float bottom, const mat4* transform, SkRegion::Op op) { 3414d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik regionModeClipRectWithTransform(Rect(left, top, right, bottom), transform, op); 342487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 343487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 344e30b53cec5eb6eaa5d24231feb3207b917c1baabTom Hudsonvoid ClipArea::onClipRegionUpdated() { 345487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (!mClipRegion.isEmpty()) { 346487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect.set(mClipRegion.getBounds()); 347487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 348487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (mClipRegion.isRect()) { 349487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.setEmpty(); 350e30b53cec5eb6eaa5d24231feb3207b917c1baabTom Hudson enterRectangleMode(); 351487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 352487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } else { 353487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect.setEmpty(); 354487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 355487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 356487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 357487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} /* namespace uirenderer */ 358487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} /* namespace android */ 359