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