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