ClipArea.h revision 8ce8f3f4d68a7750bc02b5254ebbd8658281e675
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#ifndef CLIPAREA_H
17#define CLIPAREA_H
18
19#include <SkRegion.h>
20
21#include "Matrix.h"
22#include "Rect.h"
23#include "utils/Pair.h"
24
25namespace android {
26namespace uirenderer {
27
28Rect transformAndCalculateBounds(const Rect& r, const Matrix4& transform);
29
30class TransformedRectangle {
31public:
32    TransformedRectangle();
33    TransformedRectangle(const Rect& bounds, const Matrix4& transform);
34
35    bool canSimplyIntersectWith(const TransformedRectangle& other) const;
36    bool intersectWith(const TransformedRectangle& other);
37
38    bool isEmpty() const;
39
40    const Rect& getBounds() const {
41        return mBounds;
42    }
43
44    Rect transformedBounds() const {
45        Rect transformedBounds(transformAndCalculateBounds(mBounds, mTransform));
46        return transformedBounds;
47    }
48
49    const Matrix4& getTransform() const {
50        return mTransform;
51    }
52
53private:
54    Rect mBounds;
55    Matrix4 mTransform;
56};
57
58class RectangleList {
59public:
60    RectangleList();
61
62    bool isEmpty() const;
63    int getTransformedRectanglesCount() const;
64    const TransformedRectangle& getTransformedRectangle(int i) const;
65
66    void setEmpty();
67    void set(const Rect& bounds, const Matrix4& transform);
68    bool intersectWith(const Rect& bounds, const Matrix4& transform);
69
70    SkRegion convertToRegion(const SkRegion& clip) const;
71    Rect calculateBounds() const;
72
73private:
74    enum {
75        kMaxTransformedRectangles = 5
76    };
77
78    int mTransformedRectanglesCount;
79    TransformedRectangle mTransformedRectangles[kMaxTransformedRectangles];
80};
81
82class ClipArea {
83public:
84    ClipArea();
85
86    void setViewportDimensions(int width, int height);
87
88    bool isEmpty() const {
89        return mClipRect.isEmpty();
90    }
91
92    void setEmpty();
93    void setClip(float left, float top, float right, float bottom);
94    bool clipRectWithTransform(float left, float top, float right, float bottom,
95            const mat4* transform, SkRegion::Op op = SkRegion::kIntersect_Op);
96    bool clipRectWithTransform(const Rect& r, const mat4* transform,
97            SkRegion::Op op = SkRegion::kIntersect_Op);
98    bool clipRegion(const SkRegion& region, SkRegion::Op op = SkRegion::kIntersect_Op);
99    bool clipPathWithTransform(const SkPath& path, const mat4* transform,
100            SkRegion::Op op);
101
102    const Rect& getClipRect() const {
103        return mClipRect;
104    }
105
106    const SkRegion& getClipRegion() const {
107        return mClipRegion;
108    }
109
110    const RectangleList& getRectangleList() const {
111        return mRectangleList;
112    }
113
114    bool isRegion() const {
115        return kModeRegion == mMode;
116    }
117
118    bool isSimple() const {
119        return mMode == kModeRectangle;
120    }
121
122    bool isRectangleList() const {
123        return mMode == kModeRectangleList;
124    }
125
126private:
127    void enterRectangleMode();
128    bool rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
129    bool rectangleModeClipRectWithTransform(float left, float top, float right,
130            float bottom, const mat4* transform, SkRegion::Op op);
131
132    void enterRectangleListMode();
133    bool rectangleListModeClipRectWithTransform(float left, float top,
134            float right, float bottom, const mat4* transform, SkRegion::Op op);
135    bool rectangleListModeClipRectWithTransform(const Rect& r,
136            const mat4* transform, SkRegion::Op op);
137
138    void enterRegionModeFromRectangleMode();
139    void enterRegionModeFromRectangleListMode();
140    void enterRegionMode();
141    bool regionModeClipRectWithTransform(const Rect& r, const mat4* transform,
142            SkRegion::Op op);
143    bool regionModeClipRectWithTransform(float left, float top, float right,
144            float bottom, const mat4* transform, SkRegion::Op op);
145
146    void ensureClipRegion();
147    void onClipRegionUpdated();
148    bool clipRegionOp(float left, float top, float right, float bottom,
149            SkRegion::Op op);
150
151    SkRegion createViewportRegion() {
152        return SkRegion(mViewportBounds.toSkIRect());
153    }
154
155    void regionFromPath(const SkPath& path, SkRegion& pathAsRegion) {
156        // TODO: this should not mask every path to the viewport - this makes it impossible to use
157        // paths to clip to larger areas (which is valid e.g. with SkRegion::kReplace_Op)
158        pathAsRegion.setPath(path, createViewportRegion());
159    }
160
161    enum Mode {
162        kModeRectangle,
163        kModeRegion,
164        kModeRectangleList
165    };
166
167    Mode mMode;
168    Rect mViewportBounds;
169    Rect mClipRect;
170    SkRegion mClipRegion;
171    RectangleList mRectangleList;
172};
173
174} /* namespace uirenderer */
175} /* namespace android */
176
177#endif /* CLIPAREA_H_ */
178