blob: 5d5961a140040a3701cd9d12abe031c9d8f4a073 [file] [log] [blame]
Romain Guyada4d532012-02-02 17:31:16 -08001/*
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
21namespace android {
22namespace uirenderer {
23
24///////////////////////////////////////////////////////////////////////////////
25// Constructors
26///////////////////////////////////////////////////////////////////////////////
27
28Snapshot::Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0),
Chet Haasedb8c9a62012-03-21 18:54:18 -070029 invisible(false), empty(false), alpha(1.0f) {
Romain Guyada4d532012-02-02 17:31:16 -080030
31 transform = &mTransformRoot;
32 clipRect = &mClipRectRoot;
33 region = NULL;
Romain Guy967e2bf2012-02-07 17:04:34 -080034 clipRegion = NULL;
Romain Guyada4d532012-02-02 17:31:16 -080035}
36
37/**
38 * Copies the specified snapshot/ The specified snapshot is stored as
39 * the previous snapshot.
40 */
41Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags):
42 flags(0), previous(s), layer(NULL), fbo(s->fbo),
43 invisible(s->invisible), empty(false),
Chet Haasedb8c9a62012-03-21 18:54:18 -070044 viewport(s->viewport), height(s->height), alpha(s->alpha) {
Romain Guyada4d532012-02-02 17:31:16 -080045
Romain Guy21c9c852012-02-07 18:22:07 -080046 clipRegion = NULL;
47
Romain Guyada4d532012-02-02 17:31:16 -080048 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;
Romain Guy967e2bf2012-02-07 17:04:34 -080058#if STENCIL_BUFFER_SIZE
59 if (s->clipRegion) {
60 mClipRegionRoot.merge(*s->clipRegion);
61 clipRegion = &mClipRegionRoot;
Romain Guy967e2bf2012-02-07 17:04:34 -080062 }
Romain Guy967e2bf2012-02-07 17:04:34 -080063#endif
Romain Guyada4d532012-02-02 17:31:16 -080064 } else {
65 clipRect = s->clipRect;
Romain Guy967e2bf2012-02-07 17:04:34 -080066#if STENCIL_BUFFER_SIZE
67 clipRegion = s->clipRegion;
68#endif
Romain Guyada4d532012-02-02 17:31:16 -080069 }
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
Romain Guy967e2bf2012-02-07 17:04:34 -080083void 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
93void 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
110bool 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
121bool 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
132bool 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
143bool 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
Romain Guyada4d532012-02-02 17:31:16 -0800154bool 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
160bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) {
161 bool clipped = false;
162
Romain Guyada4d532012-02-02 17:31:16 -0800163 switch (op) {
Romain Guy967e2bf2012-02-07 17:04:34 -0800164 case SkRegion::kDifference_Op: {
165 ensureClipRegion();
166 clipped = clipRegionNand(r.left, r.top, r.right, r.bottom);
Romain Guyada4d532012-02-02 17:31:16 -0800167 break;
Romain Guy967e2bf2012-02-07 17:04:34 -0800168 }
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 }
Romain Guyada4d532012-02-02 17:31:16 -0800178 }
179 break;
Romain Guy967e2bf2012-02-07 17:04:34 -0800180 }
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 }
Romain Guyada4d532012-02-02 17:31:16 -0800187 break;
Romain Guy967e2bf2012-02-07 17:04:34 -0800188 }
189 case SkRegion::kXOR_Op: {
190 ensureClipRegion();
191 clipped = clipRegionXor(r.left, r.top, r.right, r.bottom);
Romain Guyada4d532012-02-02 17:31:16 -0800192 break;
Romain Guy967e2bf2012-02-07 17:04:34 -0800193 }
194 case SkRegion::kReverseDifference_Op: {
195 // TODO!!!!!!!
Romain Guyada4d532012-02-02 17:31:16 -0800196 break;
Romain Guy967e2bf2012-02-07 17:04:34 -0800197 }
198 case SkRegion::kReplace_Op: {
199 setClip(r.left, r.top, r.right, r.bottom);
Romain Guyada4d532012-02-02 17:31:16 -0800200 clipped = true;
201 break;
Romain Guy967e2bf2012-02-07 17:04:34 -0800202 }
Romain Guyada4d532012-02-02 17:31:16 -0800203 }
204
205 if (clipped) {
206 flags |= Snapshot::kFlagClipSet;
207 }
208
209 return clipped;
210}
211
212void Snapshot::setClip(float left, float top, float right, float bottom) {
213 clipRect->set(left, top, right, bottom);
Romain Guy21c9c852012-02-07 18:22:07 -0800214#if STENCIL_BUFFER_SIZE
Romain Guy967e2bf2012-02-07 17:04:34 -0800215 if (clipRegion) {
216 clipRegion->clear();
217 clipRegion = NULL;
218 }
Romain Guy21c9c852012-02-07 18:22:07 -0800219#endif
Romain Guyada4d532012-02-02 17:31:16 -0800220 flags |= Snapshot::kFlagClipSet;
221}
222
223const 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
233void Snapshot::resetClip(float left, float top, float right, float bottom) {
234 clipRect = &mClipRectRoot;
Romain Guy967e2bf2012-02-07 17:04:34 -0800235 setClip(left, top, right, bottom);
Romain Guyada4d532012-02-02 17:31:16 -0800236}
237
238///////////////////////////////////////////////////////////////////////////////
239// Transforms
240///////////////////////////////////////////////////////////////////////////////
241
242void Snapshot::resetTransform(float x, float y, float z) {
243 transform = &mTransformRoot;
244 transform->loadTranslate(x, y, z);
245}
246
247///////////////////////////////////////////////////////////////////////////////
248// Queries
249///////////////////////////////////////////////////////////////////////////////
250
251bool Snapshot::isIgnored() const {
252 return invisible || empty;
253}
254
255}; // namespace uirenderer
256}; // namespace android