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