ClipArea.cpp revision 487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8
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 bool intersect(Rect& r, const Rect& r2) { 27487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk bool hasIntersection = r.intersect(r2); 28487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (!hasIntersection) { 29487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk r.setEmpty(); 30487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 31487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return hasIntersection; 32487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 33487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 34487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukstatic void handlePoint(Rect& transformedBounds, const Matrix4& transform, float x, float y) { 35487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk Vertex v; 36487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk v.x = x; 37487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk v.y = y; 38487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk transform.mapPoint(v.x, v.y); 39487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk transformedBounds.expandToCoverVertex(v.x, v.y); 40487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 41487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 42487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukRect transformAndCalculateBounds(const Rect& r, const Matrix4& transform) { 43487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const float kMinFloat = std::numeric_limits<float>::lowest(); 44487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const float kMaxFloat = std::numeric_limits<float>::max(); 45487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk Rect transformedBounds = { kMaxFloat, kMaxFloat, kMinFloat, kMinFloat }; 46487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk handlePoint(transformedBounds, transform, r.left, r.top); 47487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk handlePoint(transformedBounds, transform, r.right, r.top); 48487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk handlePoint(transformedBounds, transform, r.left, r.bottom); 49487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk handlePoint(transformedBounds, transform, r.right, r.bottom); 50487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return transformedBounds; 51487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 52487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 53487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 54487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * TransformedRectangle 55487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 56487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 57487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukTransformedRectangle::TransformedRectangle() { 58487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 59487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 60487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukTransformedRectangle::TransformedRectangle(const Rect& bounds, 61487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const Matrix4& transform) 62487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk : mBounds(bounds) 63487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk , mTransform(transform) { 64487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 65487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 66487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool TransformedRectangle::canSimplyIntersectWith( 67487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const TransformedRectangle& other) const { 68487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 69487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return mTransform == other.mTransform; 70487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 71487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 72487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool TransformedRectangle::intersectWith(const TransformedRectangle& other) { 73487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk Rect translatedBounds(other.mBounds); 74487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return intersect(mBounds, translatedBounds); 75487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 76487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 77487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool TransformedRectangle::isEmpty() const { 78487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return mBounds.isEmpty(); 79487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 80487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 81487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 82487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * RectangleList 83487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 84487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 85487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukRectangleList::RectangleList() 86487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk : mTransformedRectanglesCount(0) { 87487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 88487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 89487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool RectangleList::isEmpty() const { 90487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (mTransformedRectanglesCount < 1) { 91487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return true; 92487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 93487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 94487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk for (int i = 0; i < mTransformedRectanglesCount; i++) { 95487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (mTransformedRectangles[i].isEmpty()) { 96487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return true; 97487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 98487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 99487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return false; 100487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 101487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 102487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukint RectangleList::getTransformedRectanglesCount() const { 103487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return mTransformedRectanglesCount; 104487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 105487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 106487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukconst TransformedRectangle& RectangleList::getTransformedRectangle(int i) const { 107487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return mTransformedRectangles[i]; 108487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 109487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 110487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid RectangleList::setEmpty() { 111487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mTransformedRectanglesCount = 0; 112487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 113487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 114487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid RectangleList::set(const Rect& bounds, const Matrix4& transform) { 115487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mTransformedRectanglesCount = 1; 116487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mTransformedRectangles[0] = TransformedRectangle(bounds, transform); 117487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 118487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 119487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool RectangleList::intersectWith(const Rect& bounds, 120487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const Matrix4& transform) { 121487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk TransformedRectangle newRectangle(bounds, transform); 122487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 123487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // Try to find a rectangle with a compatible transformation 124487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk int index = 0; 125487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk for (; index < mTransformedRectanglesCount; index++) { 126487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk TransformedRectangle& tr(mTransformedRectangles[index]); 127487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (tr.canSimplyIntersectWith(newRectangle)) { 128487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk tr.intersectWith(newRectangle); 129487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return true; 130487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 131487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 132487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 133487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // Add it to the list if there is room 134487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (index < kMaxTransformedRectangles) { 135487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mTransformedRectangles[index] = newRectangle; 136487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mTransformedRectanglesCount += 1; 137487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return true; 138487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 139487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 140487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // This rectangle list is full 141487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return false; 142487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 143487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 144487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukRect RectangleList::calculateBounds() const { 145487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk Rect bounds; 146487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk for (int index = 0; index < mTransformedRectanglesCount; index++) { 147487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const TransformedRectangle& tr(mTransformedRectangles[index]); 148487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (index == 0) { 149487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk bounds = tr.transformedBounds(); 150487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } else { 151487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk bounds.intersect(tr.transformedBounds()); 152487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 153487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 154487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return bounds; 155487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 156487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 157487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukstatic SkPath pathFromTransformedRectangle(const Rect& bounds, 158487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const Matrix4& transform) { 159487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkPath rectPath; 160487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkPath rectPathTransformed; 161487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk rectPath.addRect(bounds.left, bounds.top, bounds.right, bounds.bottom); 162487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkMatrix skTransform; 163487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk transform.copyTo(skTransform); 164487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk rectPath.transform(skTransform, &rectPathTransformed); 165487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return rectPathTransformed; 166487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 167487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 168487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukSkRegion RectangleList::convertToRegion(const SkRegion& clip) const { 169487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion rectangleListAsRegion; 170487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk for (int index = 0; index < mTransformedRectanglesCount; index++) { 171487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const TransformedRectangle& tr(mTransformedRectangles[index]); 172487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkPath rectPathTransformed = pathFromTransformedRectangle( 173487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk tr.getBounds(), tr.getTransform()); 174487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (index == 0) { 175487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk rectangleListAsRegion.setPath(rectPathTransformed, clip); 176487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } else { 177487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion rectRegion; 178487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk rectRegion.setPath(rectPathTransformed, clip); 179487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk rectangleListAsRegion.op(rectRegion, SkRegion::kIntersect_Op); 180487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 181487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 182487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return rectangleListAsRegion; 183487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 184487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 185487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 186487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * ClipArea 187487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 188487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 189487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukClipArea::ClipArea() 190487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk : mMode(kModeRectangle) { 191487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 192487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 193487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 194487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * Interface 195487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 196487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 197487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::setViewportDimensions(int width, int height) { 198487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mViewportBounds.set(0, 0, width, height); 199487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect = mViewportBounds; 200487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 201487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 202487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::setEmpty() { 203487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mMode = kModeRectangle; 204487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect.setEmpty(); 205487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.setEmpty(); 206487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mRectangleList.setEmpty(); 207487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 208487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 209487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::setClip(float left, float top, float right, float bottom) { 210487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mMode = kModeRectangle; 211487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect.set(left, top, right, bottom); 212487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.setEmpty(); 213487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 214487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 215487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool ClipArea::clipRectWithTransform(float left, float top, float right, 216487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk float bottom, const mat4* transform, SkRegion::Op op) { 217487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk Rect r(left, top, right, bottom); 218487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return clipRectWithTransform(r, transform, op); 219487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 220487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 221487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool ClipArea::clipRectWithTransform(const Rect& r, const mat4* transform, 222487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion::Op op) { 223487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk switch (mMode) { 224487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk case kModeRectangle: 225487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return rectangleModeClipRectWithTransform(r, transform, op); 226487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk case kModeRectangleList: 227487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return rectangleListModeClipRectWithTransform(r, transform, op); 228487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk case kModeRegion: 229487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return regionModeClipRectWithTransform(r, transform, op); 230487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 231487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return false; 232487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 233487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 234487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool ClipArea::clipRegion(const SkRegion& region, SkRegion::Op op) { 235487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk enterRegionMode(); 236487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.op(region, op); 237487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk setClipRectToRegionBounds(); 238487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return true; 239487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 240487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 241487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool ClipArea::clipPathWithTransform(const SkPath& path, const mat4* transform, 242487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion::Op op) { 243487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkMatrix skTransform; 244487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk transform->copyTo(skTransform); 245487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkPath transformed; 246487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk path.transform(skTransform, &transformed); 247487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion region; 248487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk regionFromPath(transformed, region); 249487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return clipRegion(region, op); 250487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 251487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 252487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 253487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * Rectangle mode 254487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 255487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 256487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::enterRectangleMode() { 257487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // Entering rectangle mode discards any 258487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // existing clipping information from the other modes. 259487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // The only way this occurs is by a clip setting operation. 260487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mMode = kModeRectangle; 261487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 262487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 263487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool ClipArea::rectangleModeClipRectWithTransform(const Rect& r, 264487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const mat4* transform, SkRegion::Op op) { 265487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 266487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (op != SkRegion::kIntersect_Op) { 267487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk enterRegionMode(); 268487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return regionModeClipRectWithTransform(r, transform, op); 269487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 270487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 271487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (transform->rectToRect()) { 272487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk Rect transformed(r); 273487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk transform->mapRect(transformed); 274487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk bool hasIntersection = mClipRect.intersect(transformed); 275487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (!hasIntersection) { 276487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect.setEmpty(); 277487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 278487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return true; 279487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 280487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 281487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk enterRectangleListMode(); 282487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return rectangleListModeClipRectWithTransform(r, transform, op); 283487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 284487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 285487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool ClipArea::rectangleModeClipRectWithTransform(float left, float top, 286487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk float right, float bottom, const mat4* transform, SkRegion::Op op) { 287487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk Rect r(left, top, right, bottom); 288487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk bool result = rectangleModeClipRectWithTransform(r, transform, op); 289487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect = mRectangleList.calculateBounds(); 290487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return result; 291487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 292487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 293487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 294487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * RectangleList mode implementation 295487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 296487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 297487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::enterRectangleListMode() { 298487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // Is is only legal to enter rectangle list mode from 299487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // rectangle mode, since rectangle list mode cannot represent 300487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk // all clip areas that can be represented by a region. 301487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk ALOG_ASSERT(mMode == kModeRectangle); 302487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mMode = kModeRectangleList; 303487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mRectangleList.set(mClipRect, Matrix4::identity()); 304487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 305487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 306487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool ClipArea::rectangleListModeClipRectWithTransform(const Rect& r, 307487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const mat4* transform, SkRegion::Op op) { 308487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (op != SkRegion::kIntersect_Op 309487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk || !mRectangleList.intersectWith(r, *transform)) { 310487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk enterRegionMode(); 311487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return regionModeClipRectWithTransform(r, transform, op); 312487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 313487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return true; 314487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 315487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 316487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool ClipArea::rectangleListModeClipRectWithTransform(float left, float top, 317487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk float right, float bottom, const mat4* transform, SkRegion::Op op) { 318487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk Rect r(left, top, right, bottom); 319487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return rectangleListModeClipRectWithTransform(r, transform, op); 320487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 321487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 322487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk/* 323487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk * Region mode implementation 324487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk */ 325487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 326487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::enterRegionMode() { 327487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (mMode != kModeRegion) { 328487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (mMode == kModeRectangle) { 329487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.setRect(mClipRect.left, mClipRect.top, 330487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect.right, mClipRect.bottom); 331487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } else { 332487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion = mRectangleList.convertToRegion(createViewportRegion()); 333487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk setClipRectToRegionBounds(); 334487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 335487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mMode = kModeRegion; 336487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 337487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 338487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 339487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool ClipArea::regionModeClipRectWithTransform(const Rect& r, 340487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const mat4* transform, SkRegion::Op op) { 341487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkPath transformedRect = pathFromTransformedRectangle(r, *transform); 342487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk SkRegion transformedRectRegion; 343487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk regionFromPath(transformedRect, transformedRectRegion); 344487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.op(transformedRectRegion, op); 345487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk setClipRectToRegionBounds(); 346487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return true; 347487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 348487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 349487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool ClipArea::regionModeClipRectWithTransform(float left, float top, 350487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk float right, float bottom, const mat4* transform, SkRegion::Op op) { 351487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return regionModeClipRectWithTransform(Rect(left, top, right, bottom), 352487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk transform, op); 353487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 354487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 355487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukvoid ClipArea::setClipRectToRegionBounds() { 356487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (!mClipRegion.isEmpty()) { 357487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect.set(mClipRegion.getBounds()); 358487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 359487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk if (mClipRegion.isRect()) { 360487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRegion.setEmpty(); 361487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 362487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } else { 363487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipRect.setEmpty(); 364487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk } 365487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} 366487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk 367487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} /* namespace uirenderer */ 368487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} /* namespace android */ 369