blob: 5f801fbb50430f923ac270f36d04d37b24f0b5ac [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),
29 invisible(false), empty(false) {
30
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),
44 viewport(s->viewport), height(s->height) {
45
46 if (saveFlags & SkCanvas::kMatrix_SaveFlag) {
47 mTransformRoot.load(*s->transform);
48 transform = &mTransformRoot;
49 } else {
50 transform = s->transform;
51 }
52
53 if (saveFlags & SkCanvas::kClip_SaveFlag) {
54 mClipRectRoot.set(*s->clipRect);
55 clipRect = &mClipRectRoot;
Romain Guy967e2bf2012-02-07 17:04:34 -080056#if STENCIL_BUFFER_SIZE
57 if (s->clipRegion) {
58 mClipRegionRoot.merge(*s->clipRegion);
59 clipRegion = &mClipRegionRoot;
60 } else {
61 clipRegion = NULL;
62 }
63#else
64 clipRegion = NULL;
65#endif
Romain Guyada4d532012-02-02 17:31:16 -080066 } else {
67 clipRect = s->clipRect;
Romain Guy967e2bf2012-02-07 17:04:34 -080068#if STENCIL_BUFFER_SIZE
69 clipRegion = s->clipRegion;
70#endif
Romain Guyada4d532012-02-02 17:31:16 -080071 }
72
73 if (s->flags & Snapshot::kFlagFboTarget) {
74 flags |= Snapshot::kFlagFboTarget;
75 region = s->region;
76 } else {
77 region = NULL;
78 }
79}
80
81///////////////////////////////////////////////////////////////////////////////
82// Clipping
83///////////////////////////////////////////////////////////////////////////////
84
Romain Guy967e2bf2012-02-07 17:04:34 -080085void Snapshot::ensureClipRegion() {
86#if STENCIL_BUFFER_SIZE
87 if (!clipRegion) {
88 clipRegion = &mClipRegionRoot;
89 android::Rect tmp(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom);
90 clipRegion->set(tmp);
91 }
92#endif
93}
94
95void Snapshot::copyClipRectFromRegion() {
96#if STENCIL_BUFFER_SIZE
97 if (!clipRegion->isEmpty()) {
98 android::Rect bounds(clipRegion->bounds());
99 clipRect->set(bounds.left, bounds.top, bounds.right, bounds.bottom);
100
101 if (clipRegion->isRect()) {
102 clipRegion->clear();
103 clipRegion = NULL;
104 }
105 } else {
106 clipRect->setEmpty();
107 clipRegion = NULL;
108 }
109#endif
110}
111
112bool Snapshot::clipRegionOr(float left, float top, float right, float bottom) {
113#if STENCIL_BUFFER_SIZE
114 android::Rect tmp(left, top, right, bottom);
115 clipRegion->orSelf(tmp);
116 copyClipRectFromRegion();
117 return true;
118#else
119 return false;
120#endif
121}
122
123bool Snapshot::clipRegionXor(float left, float top, float right, float bottom) {
124#if STENCIL_BUFFER_SIZE
125 android::Rect tmp(left, top, right, bottom);
126 clipRegion->xorSelf(tmp);
127 copyClipRectFromRegion();
128 return true;
129#else
130 return false;
131#endif
132}
133
134bool Snapshot::clipRegionAnd(float left, float top, float right, float bottom) {
135#if STENCIL_BUFFER_SIZE
136 android::Rect tmp(left, top, right, bottom);
137 clipRegion->andSelf(tmp);
138 copyClipRectFromRegion();
139 return true;
140#else
141 return false;
142#endif
143}
144
145bool Snapshot::clipRegionNand(float left, float top, float right, float bottom) {
146#if STENCIL_BUFFER_SIZE
147 android::Rect tmp(left, top, right, bottom);
148 clipRegion->subtractSelf(tmp);
149 copyClipRectFromRegion();
150 return true;
151#else
152 return false;
153#endif
154}
155
Romain Guyada4d532012-02-02 17:31:16 -0800156bool Snapshot::clip(float left, float top, float right, float bottom, SkRegion::Op op) {
157 Rect r(left, top, right, bottom);
158 transform->mapRect(r);
159 return clipTransformed(r, op);
160}
161
162bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) {
163 bool clipped = false;
164
Romain Guyada4d532012-02-02 17:31:16 -0800165 switch (op) {
Romain Guy967e2bf2012-02-07 17:04:34 -0800166 case SkRegion::kDifference_Op: {
167 ensureClipRegion();
168 clipped = clipRegionNand(r.left, r.top, r.right, r.bottom);
Romain Guyada4d532012-02-02 17:31:16 -0800169 break;
Romain Guy967e2bf2012-02-07 17:04:34 -0800170 }
171 case SkRegion::kIntersect_Op: {
172 if (CC_UNLIKELY(clipRegion)) {
173 clipped = clipRegionOr(r.left, r.top, r.right, r.bottom);
174 } else {
175 clipped = clipRect->intersect(r);
176 if (!clipped) {
177 clipRect->setEmpty();
178 clipped = true;
179 }
Romain Guyada4d532012-02-02 17:31:16 -0800180 }
181 break;
Romain Guy967e2bf2012-02-07 17:04:34 -0800182 }
183 case SkRegion::kUnion_Op: {
184 if (CC_UNLIKELY(clipRegion)) {
185 clipped = clipRegionAnd(r.left, r.top, r.right, r.bottom);
186 } else {
187 clipped = clipRect->unionWith(r);
188 }
Romain Guyada4d532012-02-02 17:31:16 -0800189 break;
Romain Guy967e2bf2012-02-07 17:04:34 -0800190 }
191 case SkRegion::kXOR_Op: {
192 ensureClipRegion();
193 clipped = clipRegionXor(r.left, r.top, r.right, r.bottom);
Romain Guyada4d532012-02-02 17:31:16 -0800194 break;
Romain Guy967e2bf2012-02-07 17:04:34 -0800195 }
196 case SkRegion::kReverseDifference_Op: {
197 // TODO!!!!!!!
Romain Guyada4d532012-02-02 17:31:16 -0800198 break;
Romain Guy967e2bf2012-02-07 17:04:34 -0800199 }
200 case SkRegion::kReplace_Op: {
201 setClip(r.left, r.top, r.right, r.bottom);
Romain Guyada4d532012-02-02 17:31:16 -0800202 clipped = true;
203 break;
Romain Guy967e2bf2012-02-07 17:04:34 -0800204 }
Romain Guyada4d532012-02-02 17:31:16 -0800205 }
206
207 if (clipped) {
208 flags |= Snapshot::kFlagClipSet;
209 }
210
211 return clipped;
212}
213
214void Snapshot::setClip(float left, float top, float right, float bottom) {
215 clipRect->set(left, top, right, bottom);
Romain Guy967e2bf2012-02-07 17:04:34 -0800216 if (clipRegion) {
217 clipRegion->clear();
218 clipRegion = NULL;
219 }
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