• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 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 
17 #include "Snapshot.h"
18 
19 #include <SkCanvas.h>
20 
21 namespace android {
22 namespace uirenderer {
23 
24 ///////////////////////////////////////////////////////////////////////////////
25 // Constructors
26 ///////////////////////////////////////////////////////////////////////////////
27 
Snapshot()28 Snapshot::Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0),
29         invisible(false), empty(false), alpha(1.0f) {
30 
31     transform = &mTransformRoot;
32     clipRect = &mClipRectRoot;
33     region = NULL;
34     clipRegion = NULL;
35 }
36 
37 /**
38  * Copies the specified snapshot/ The specified snapshot is stored as
39  * the previous snapshot.
40  */
Snapshot(const sp<Snapshot> & s,int saveFlags)41 Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags):
42         flags(0), previous(s), layer(NULL), fbo(s->fbo),
43         invisible(s->invisible), empty(false),
44         viewport(s->viewport), height(s->height), alpha(s->alpha) {
45 
46     clipRegion = NULL;
47 
48     if (saveFlags & SkCanvas::kMatrix_SaveFlag) {
49         mTransformRoot.load(*s->transform);
50         transform = &mTransformRoot;
51     } else {
52         transform = s->transform;
53     }
54 
55     if (saveFlags & SkCanvas::kClip_SaveFlag) {
56         mClipRectRoot.set(*s->clipRect);
57         clipRect = &mClipRectRoot;
58 #if STENCIL_BUFFER_SIZE
59         if (s->clipRegion) {
60             mClipRegionRoot.merge(*s->clipRegion);
61             clipRegion = &mClipRegionRoot;
62         }
63 #endif
64     } else {
65         clipRect = s->clipRect;
66 #if STENCIL_BUFFER_SIZE
67         clipRegion = s->clipRegion;
68 #endif
69     }
70 
71     if (s->flags & Snapshot::kFlagFboTarget) {
72         flags |= Snapshot::kFlagFboTarget;
73         region = s->region;
74     } else {
75         region = NULL;
76     }
77 }
78 
79 ///////////////////////////////////////////////////////////////////////////////
80 // Clipping
81 ///////////////////////////////////////////////////////////////////////////////
82 
ensureClipRegion()83 void Snapshot::ensureClipRegion() {
84 #if STENCIL_BUFFER_SIZE
85     if (!clipRegion) {
86         clipRegion = &mClipRegionRoot;
87         android::Rect tmp(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom);
88         clipRegion->set(tmp);
89     }
90 #endif
91 }
92 
copyClipRectFromRegion()93 void Snapshot::copyClipRectFromRegion() {
94 #if STENCIL_BUFFER_SIZE
95     if (!clipRegion->isEmpty()) {
96         android::Rect bounds(clipRegion->bounds());
97         clipRect->set(bounds.left, bounds.top, bounds.right, bounds.bottom);
98 
99         if (clipRegion->isRect()) {
100             clipRegion->clear();
101             clipRegion = NULL;
102         }
103     } else {
104         clipRect->setEmpty();
105         clipRegion = NULL;
106     }
107 #endif
108 }
109 
clipRegionOr(float left,float top,float right,float bottom)110 bool Snapshot::clipRegionOr(float left, float top, float right, float bottom) {
111 #if STENCIL_BUFFER_SIZE
112     android::Rect tmp(left, top, right, bottom);
113     clipRegion->orSelf(tmp);
114     copyClipRectFromRegion();
115     return true;
116 #else
117     return false;
118 #endif
119 }
120 
clipRegionXor(float left,float top,float right,float bottom)121 bool Snapshot::clipRegionXor(float left, float top, float right, float bottom) {
122 #if STENCIL_BUFFER_SIZE
123     android::Rect tmp(left, top, right, bottom);
124     clipRegion->xorSelf(tmp);
125     copyClipRectFromRegion();
126     return true;
127 #else
128     return false;
129 #endif
130 }
131 
clipRegionAnd(float left,float top,float right,float bottom)132 bool Snapshot::clipRegionAnd(float left, float top, float right, float bottom) {
133 #if STENCIL_BUFFER_SIZE
134     android::Rect tmp(left, top, right, bottom);
135     clipRegion->andSelf(tmp);
136     copyClipRectFromRegion();
137     return true;
138 #else
139     return false;
140 #endif
141 }
142 
clipRegionNand(float left,float top,float right,float bottom)143 bool Snapshot::clipRegionNand(float left, float top, float right, float bottom) {
144 #if STENCIL_BUFFER_SIZE
145     android::Rect tmp(left, top, right, bottom);
146     clipRegion->subtractSelf(tmp);
147     copyClipRectFromRegion();
148     return true;
149 #else
150     return false;
151 #endif
152 }
153 
clip(float left,float top,float right,float bottom,SkRegion::Op op)154 bool Snapshot::clip(float left, float top, float right, float bottom, SkRegion::Op op) {
155     Rect r(left, top, right, bottom);
156     transform->mapRect(r);
157     return clipTransformed(r, op);
158 }
159 
clipTransformed(const Rect & r,SkRegion::Op op)160 bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) {
161     bool clipped = false;
162 
163     switch (op) {
164         case SkRegion::kDifference_Op: {
165             ensureClipRegion();
166             clipped = clipRegionNand(r.left, r.top, r.right, r.bottom);
167             break;
168         }
169         case SkRegion::kIntersect_Op: {
170             if (CC_UNLIKELY(clipRegion)) {
171                 clipped = clipRegionOr(r.left, r.top, r.right, r.bottom);
172             } else {
173                 clipped = clipRect->intersect(r);
174                 if (!clipped) {
175                     clipRect->setEmpty();
176                     clipped = true;
177                 }
178             }
179             break;
180         }
181         case SkRegion::kUnion_Op: {
182             if (CC_UNLIKELY(clipRegion)) {
183                 clipped = clipRegionAnd(r.left, r.top, r.right, r.bottom);
184             } else {
185                 clipped = clipRect->unionWith(r);
186             }
187             break;
188         }
189         case SkRegion::kXOR_Op: {
190             ensureClipRegion();
191             clipped = clipRegionXor(r.left, r.top, r.right, r.bottom);
192             break;
193         }
194         case SkRegion::kReverseDifference_Op: {
195             // TODO!!!!!!!
196             break;
197         }
198         case SkRegion::kReplace_Op: {
199             setClip(r.left, r.top, r.right, r.bottom);
200             clipped = true;
201             break;
202         }
203     }
204 
205     if (clipped) {
206         flags |= Snapshot::kFlagClipSet;
207     }
208 
209     return clipped;
210 }
211 
setClip(float left,float top,float right,float bottom)212 void Snapshot::setClip(float left, float top, float right, float bottom) {
213     clipRect->set(left, top, right, bottom);
214 #if STENCIL_BUFFER_SIZE
215     if (clipRegion) {
216         clipRegion->clear();
217         clipRegion = NULL;
218     }
219 #endif
220     flags |= Snapshot::kFlagClipSet;
221 }
222 
getLocalClip()223 const Rect& Snapshot::getLocalClip() {
224     mat4 inverse;
225     inverse.loadInverse(*transform);
226 
227     mLocalClip.set(*clipRect);
228     inverse.mapRect(mLocalClip);
229 
230     return mLocalClip;
231 }
232 
resetClip(float left,float top,float right,float bottom)233 void Snapshot::resetClip(float left, float top, float right, float bottom) {
234     clipRect = &mClipRectRoot;
235     setClip(left, top, right, bottom);
236 }
237 
238 ///////////////////////////////////////////////////////////////////////////////
239 // Transforms
240 ///////////////////////////////////////////////////////////////////////////////
241 
resetTransform(float x,float y,float z)242 void Snapshot::resetTransform(float x, float y, float z) {
243     transform = &mTransformRoot;
244     transform->loadTranslate(x, y, z);
245 }
246 
247 ///////////////////////////////////////////////////////////////////////////////
248 // Queries
249 ///////////////////////////////////////////////////////////////////////////////
250 
isIgnored() const251 bool Snapshot::isIgnored() const {
252     return invisible || empty;
253 }
254 
255 }; // namespace uirenderer
256 }; // namespace android
257