• 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.op(*s->clipRegion, SkRegion::kUnion_Op);
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         clipRegion->setRect(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom);
88     }
89 #endif
90 }
91 
copyClipRectFromRegion()92 void Snapshot::copyClipRectFromRegion() {
93 #if STENCIL_BUFFER_SIZE
94     if (!clipRegion->isEmpty()) {
95         const SkIRect& bounds = clipRegion->getBounds();
96         clipRect->set(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
97 
98         if (clipRegion->isRect()) {
99             clipRegion->setEmpty();
100             clipRegion = NULL;
101         }
102     } else {
103         clipRect->setEmpty();
104         clipRegion = NULL;
105     }
106 #endif
107 }
108 
clipRegionOp(float left,float top,float right,float bottom,SkRegion::Op op)109 bool Snapshot::clipRegionOp(float left, float top, float right, float bottom, SkRegion::Op op) {
110 #if STENCIL_BUFFER_SIZE
111     SkIRect tmp;
112     tmp.set(left, top, right, bottom);
113     clipRegion->op(tmp, op);
114     copyClipRectFromRegion();
115     return true;
116 #else
117     return false;
118 #endif
119 }
120 
clip(float left,float top,float right,float bottom,SkRegion::Op op)121 bool Snapshot::clip(float left, float top, float right, float bottom, SkRegion::Op op) {
122     Rect r(left, top, right, bottom);
123     transform->mapRect(r);
124     return clipTransformed(r, op);
125 }
126 
clipTransformed(const Rect & r,SkRegion::Op op)127 bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) {
128     bool clipped = false;
129 
130     switch (op) {
131         case SkRegion::kIntersect_Op: {
132             if (CC_UNLIKELY(clipRegion)) {
133                 clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kIntersect_Op);
134             } else {
135                 clipped = clipRect->intersect(r);
136                 if (!clipped) {
137                     clipRect->setEmpty();
138                     clipped = true;
139                 }
140             }
141             break;
142         }
143         case SkRegion::kUnion_Op: {
144             if (CC_UNLIKELY(clipRegion)) {
145                 clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kUnion_Op);
146             } else {
147                 clipped = clipRect->unionWith(r);
148             }
149             break;
150         }
151         case SkRegion::kReplace_Op: {
152             setClip(r.left, r.top, r.right, r.bottom);
153             clipped = true;
154             break;
155         }
156         default: {
157             ensureClipRegion();
158             clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, op);
159             break;
160         }
161     }
162 
163     if (clipped) {
164         flags |= Snapshot::kFlagClipSet;
165     }
166 
167     return clipped;
168 }
169 
setClip(float left,float top,float right,float bottom)170 void Snapshot::setClip(float left, float top, float right, float bottom) {
171     clipRect->set(left, top, right, bottom);
172 #if STENCIL_BUFFER_SIZE
173     if (clipRegion) {
174         clipRegion->setEmpty();
175         clipRegion = NULL;
176     }
177 #endif
178     flags |= Snapshot::kFlagClipSet;
179 }
180 
hasPerspectiveTransform() const181 bool Snapshot::hasPerspectiveTransform() const {
182     return transform->isPerspective();
183 }
184 
getLocalClip()185 const Rect& Snapshot::getLocalClip() {
186     mat4 inverse;
187     inverse.loadInverse(*transform);
188 
189     mLocalClip.set(*clipRect);
190     inverse.mapRect(mLocalClip);
191 
192     return mLocalClip;
193 }
194 
resetClip(float left,float top,float right,float bottom)195 void Snapshot::resetClip(float left, float top, float right, float bottom) {
196     clipRect = &mClipRectRoot;
197     setClip(left, top, right, bottom);
198 }
199 
200 ///////////////////////////////////////////////////////////////////////////////
201 // Transforms
202 ///////////////////////////////////////////////////////////////////////////////
203 
resetTransform(float x,float y,float z)204 void Snapshot::resetTransform(float x, float y, float z) {
205     transform = &mTransformRoot;
206     transform->loadTranslate(x, y, z);
207 }
208 
209 ///////////////////////////////////////////////////////////////////////////////
210 // Queries
211 ///////////////////////////////////////////////////////////////////////////////
212 
isIgnored() const213 bool Snapshot::isIgnored() const {
214     return invisible || empty;
215 }
216 
217 }; // namespace uirenderer
218 }; // namespace android
219