ClipArea.h 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#ifndef CLIPAREA_H
17487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk#define CLIPAREA_H
18487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
19487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk#include <SkRegion.h>
20487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
21487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk#include "Matrix.h"
22487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk#include "Rect.h"
23487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk#include "utils/Pair.h"
24487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
25487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuknamespace android {
26487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuknamespace uirenderer {
27487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
28487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob TsukRect transformAndCalculateBounds(const Rect& r, const Matrix4& transform);
29487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
30487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukclass TransformedRectangle {
31487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukpublic:
32487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    TransformedRectangle();
33487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    TransformedRectangle(const Rect& bounds, const Matrix4& transform);
34487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
35487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    bool canSimplyIntersectWith(const TransformedRectangle& other) const;
36ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik    void intersectWith(const TransformedRectangle& other);
37487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
38487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    bool isEmpty() const;
39487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
40487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    const Rect& getBounds() const {
41487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        return mBounds;
42487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    }
43487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
44487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    Rect transformedBounds() const {
45487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        Rect transformedBounds(transformAndCalculateBounds(mBounds, mTransform));
46487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        return transformedBounds;
47487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    }
48487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
49487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    const Matrix4& getTransform() const {
50487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        return mTransform;
51487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    }
52487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
53487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukprivate:
54487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    Rect mBounds;
55487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    Matrix4 mTransform;
56487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk};
57487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
58487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukclass RectangleList {
59487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukpublic:
60487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    RectangleList();
61487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
62487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    bool isEmpty() const;
63487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    int getTransformedRectanglesCount() const;
64487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    const TransformedRectangle& getTransformedRectangle(int i) const;
65487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
66487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    void setEmpty();
67487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    void set(const Rect& bounds, const Matrix4& transform);
68487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    bool intersectWith(const Rect& bounds, const Matrix4& transform);
69487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
70487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    SkRegion convertToRegion(const SkRegion& clip) const;
71487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    Rect calculateBounds() const;
72487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
73487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukprivate:
74487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    enum {
75487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        kMaxTransformedRectangles = 5
76487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    };
77487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
78487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    int mTransformedRectanglesCount;
79487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    TransformedRectangle mTransformedRectangles[kMaxTransformedRectangles];
80487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk};
81487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
82487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukclass ClipArea {
834d3e704b04c6abd7995df640d12662b0271f6c7bChris Craikprivate:
844d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik    enum class Mode {
854d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik        Rectangle,
864d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik        Region,
874d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik        RectangleList
884d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik    };
894d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik
90487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukpublic:
91487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    ClipArea();
92487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
93487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    void setViewportDimensions(int width, int height);
94487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
95487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    bool isEmpty() const {
96487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        return mClipRect.isEmpty();
97487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    }
98487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
99487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    void setEmpty();
100487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    void setClip(float left, float top, float right, float bottom);
1014d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik    void clipRectWithTransform(float left, float top, float right, float bottom,
1024d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik            const mat4* transform, SkRegion::Op op);
1034d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik    void clipRectWithTransform(const Rect& r, const mat4* transform,
1044d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik            SkRegion::Op op);
1054d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik    void clipRegion(const SkRegion& region, SkRegion::Op op);
1064d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik    void clipPathWithTransform(const SkPath& path, const mat4* transform,
107487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            SkRegion::Op op);
108487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
109487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    const Rect& getClipRect() const {
110487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        return mClipRect;
111487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    }
112487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
113487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    const SkRegion& getClipRegion() const {
114487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        return mClipRegion;
115487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    }
116487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
117487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    const RectangleList& getRectangleList() const {
118487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        return mRectangleList;
119487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    }
120487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
121487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    bool isRegion() const {
1224d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik        return Mode::Region == mMode;
123487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    }
124487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
125487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    bool isSimple() const {
1264d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik        return mMode == Mode::Rectangle;
127487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    }
128487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
129487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    bool isRectangleList() const {
1304d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik        return mMode == Mode::RectangleList;
131487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    }
132487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
133487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukprivate:
134487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    void enterRectangleMode();
1354d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik    void rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
1364d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik    void rectangleModeClipRectWithTransform(float left, float top, float right,
137487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            float bottom, const mat4* transform, SkRegion::Op op);
138487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
139487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    void enterRectangleListMode();
1404d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik    void rectangleListModeClipRectWithTransform(float left, float top,
141487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            float right, float bottom, const mat4* transform, SkRegion::Op op);
1424d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik    void rectangleListModeClipRectWithTransform(const Rect& r,
143487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            const mat4* transform, SkRegion::Op op);
144487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
145487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    void enterRegionModeFromRectangleMode();
146487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    void enterRegionModeFromRectangleListMode();
147487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    void enterRegionMode();
1484d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik    void regionModeClipRectWithTransform(const Rect& r, const mat4* transform,
149487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            SkRegion::Op op);
1504d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik    void regionModeClipRectWithTransform(float left, float top, float right,
151487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk            float bottom, const mat4* transform, SkRegion::Op op);
152487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
153487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    void ensureClipRegion();
154e30b53cec5eb6eaa5d24231feb3207b917c1baabTom Hudson    void onClipRegionUpdated();
155487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
156487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    SkRegion createViewportRegion() {
157487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        return SkRegion(mViewportBounds.toSkIRect());
158487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    }
159487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
160487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    void regionFromPath(const SkPath& path, SkRegion& pathAsRegion) {
1618ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris Craik        // TODO: this should not mask every path to the viewport - this makes it impossible to use
1628ce8f3f4d68a7750bc02b5254ebbd8658281e675Chris Craik        // paths to clip to larger areas (which is valid e.g. with SkRegion::kReplace_Op)
163487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk        pathAsRegion.setPath(path, createViewportRegion());
164487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    }
165487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
166487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    Mode mMode;
167487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    Rect mViewportBounds;
168487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    Rect mClipRect;
169487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    SkRegion mClipRegion;
170487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk    RectangleList mRectangleList;
171487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk};
172487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
173487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} /* namespace uirenderer */
174487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk} /* namespace android */
175487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
176487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk#endif /* CLIPAREA_H_ */
177