• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "Matrix.h"
20  #include "Rect.h"
21  #include "utils/Pair.h"
22  
23  #include <SkRegion.h>
24  
25  namespace android {
26  namespace uirenderer {
27  
28  class LinearAllocator;
29  
30  Rect transformAndCalculateBounds(const Rect& r, const Matrix4& transform);
31  
32  class TransformedRectangle {
33  public:
34      TransformedRectangle();
35      TransformedRectangle(const Rect& bounds, const Matrix4& transform);
36  
37      bool canSimplyIntersectWith(const TransformedRectangle& other) const;
38      void intersectWith(const TransformedRectangle& other);
39  
40      bool isEmpty() const;
41  
getBounds()42      const Rect& getBounds() const {
43          return mBounds;
44      }
45  
transformedBounds()46      Rect transformedBounds() const {
47          Rect transformedBounds(transformAndCalculateBounds(mBounds, mTransform));
48          return transformedBounds;
49      }
50  
getTransform()51      const Matrix4& getTransform() const {
52          return mTransform;
53      }
54  
transform(const Matrix4 & transform)55      void transform(const Matrix4& transform) {
56          Matrix4 t;
57          t.loadMultiply(transform, mTransform);
58          mTransform = t;
59      }
60  
61  private:
62      Rect mBounds;
63      Matrix4 mTransform;
64  };
65  
66  class RectangleList {
67  public:
68      RectangleList();
69  
70      bool isEmpty() const;
71      int getTransformedRectanglesCount() const;
72      const TransformedRectangle& getTransformedRectangle(int i) const;
73  
74      void setEmpty();
75      void set(const Rect& bounds, const Matrix4& transform);
76      bool intersectWith(const Rect& bounds, const Matrix4& transform);
77      void transform(const Matrix4& transform);
78  
79      SkRegion convertToRegion(const SkRegion& clip) const;
80      Rect calculateBounds() const;
81  
82      enum {
83          kMaxTransformedRectangles = 5
84      };
85  
86  private:
87      int mTransformedRectanglesCount;
88      TransformedRectangle mTransformedRectangles[kMaxTransformedRectangles];
89  };
90  
91  enum class ClipMode {
92      Rectangle,
93      RectangleList,
94  
95      // region and path - intersected. if either is empty, don't use
96      Region
97  };
98  
99  struct ClipBase {
ClipBaseClipBase100      explicit ClipBase(ClipMode mode)
101              : mode(mode) {}
ClipBaseClipBase102      explicit ClipBase(const Rect& rect)
103              : mode(ClipMode::Rectangle)
104              , rect(rect) {}
105      const ClipMode mode;
106      bool intersectWithRoot = false;
107      // Bounds of the clipping area, used to define the scissor, and define which
108      // portion of the stencil is updated/used
109      Rect rect;
110  
111      void dump() const;
112  };
113  
114  struct ClipRect : ClipBase {
ClipRectClipRect115      explicit ClipRect(const Rect& rect)
116              : ClipBase(rect) {}
117  };
118  
119  struct ClipRectList : ClipBase {
ClipRectListClipRectList120      explicit ClipRectList(const RectangleList& rectList)
121              : ClipBase(ClipMode::RectangleList)
122              , rectList(rectList) {}
123      RectangleList rectList;
124  };
125  
126  struct ClipRegion : ClipBase {
ClipRegionClipRegion127      explicit ClipRegion(const SkRegion& region)
128              : ClipBase(ClipMode::Region)
129              , region(region) {}
ClipRegionClipRegion130      ClipRegion()
131              : ClipBase(ClipMode::Region) {}
132      SkRegion region;
133  };
134  
135  class ClipArea {
136  public:
137      ClipArea();
138  
139      void setViewportDimensions(int width, int height);
140  
isEmpty()141      bool isEmpty() const {
142          return mClipRect.isEmpty();
143      }
144  
145      void setEmpty();
146      void setClip(float left, float top, float right, float bottom);
147      void clipRectWithTransform(const Rect& r, const mat4* transform,
148              SkRegion::Op op);
149      void clipPathWithTransform(const SkPath& path, const mat4* transform,
150              SkRegion::Op op);
151  
getClipRect()152      const Rect& getClipRect() const {
153          return mClipRect;
154      }
155  
getClipRegion()156      const SkRegion& getClipRegion() const {
157          return mClipRegion;
158      }
159  
getRectangleList()160      const RectangleList& getRectangleList() const {
161          return mRectangleList;
162      }
163  
isRegion()164      bool isRegion() const {
165          return ClipMode::Region == mMode;
166      }
167  
isSimple()168      bool isSimple() const {
169          return mMode == ClipMode::Rectangle;
170      }
171  
isRectangleList()172      bool isRectangleList() const {
173          return mMode == ClipMode::RectangleList;
174      }
175  
176      WARN_UNUSED_RESULT const ClipBase* serializeClip(LinearAllocator& allocator);
177      WARN_UNUSED_RESULT const ClipBase* serializeIntersectedClip(LinearAllocator& allocator,
178              const ClipBase* recordedClip, const Matrix4& recordedClipTransform);
179      void applyClip(const ClipBase* recordedClip, const Matrix4& recordedClipTransform);
180  
181      static void applyTransformToRegion(const Matrix4& transform, SkRegion* region);
182  
183  private:
184      void enterRectangleMode();
185      void rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
186  
187      void enterRectangleListMode();
188      void rectangleListModeClipRectWithTransform(const Rect& r,
189              const mat4* transform, SkRegion::Op op);
190  
191      void enterRegionModeFromRectangleMode();
192      void enterRegionModeFromRectangleListMode();
193      void enterRegionMode();
194      void regionModeClipRectWithTransform(const Rect& r, const mat4* transform,
195              SkRegion::Op op);
196  
197      void clipRegion(const SkRegion& region, SkRegion::Op op);
198      void ensureClipRegion();
199      void onClipRegionUpdated();
200  
201      // Called by every state modifying public method.
onClipUpdated()202      void onClipUpdated() {
203          mPostViewportClipObserved = true;
204          mLastSerialization = nullptr;
205          mLastResolutionResult = nullptr;
206      }
207  
createViewportRegion()208      SkRegion createViewportRegion() {
209          return SkRegion(mViewportBounds.toSkIRect());
210      }
211  
regionFromPath(const SkPath & path,SkRegion & pathAsRegion)212      void regionFromPath(const SkPath& path, SkRegion& pathAsRegion) {
213          // TODO: this should not mask every path to the viewport - this makes it impossible to use
214          // paths to clip to larger areas (which is valid e.g. with SkRegion::kReplace_Op)
215          pathAsRegion.setPath(path, createViewportRegion());
216      }
217  
218      ClipMode mMode;
219      bool mPostViewportClipObserved = false;
220      bool mReplaceOpObserved = false;
221  
222      /**
223       * If mLastSerialization is non-null, it represents an already serialized copy
224       * of the current clip state. If null, it has not been computed.
225       */
226      const ClipBase* mLastSerialization = nullptr;
227  
228      /**
229       * This pair of pointers is a single entry cache of most recently seen
230       */
231      const ClipBase* mLastResolutionResult = nullptr;
232      const ClipBase* mLastResolutionClip = nullptr;
233      Matrix4 mLastResolutionTransform;
234  
235      Rect mViewportBounds;
236      Rect mClipRect;
237      SkRegion mClipRegion;
238      RectangleList mRectangleList;
239  };
240  
241  } /* namespace uirenderer */
242  } /* namespace android */
243  
244  #endif /* CLIPAREA_H_ */
245