Snapshot.cpp revision 735738c4ddf3229caa5f6e634bf591953ac29944
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 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), 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 */ 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), 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 83void 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 92void 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 109bool 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 121bool 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 127bool 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 ensureClipRegion(); 134 clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kIntersect_Op); 135 } else { 136 clipped = clipRect->intersect(r); 137 if (!clipped) { 138 clipRect->setEmpty(); 139 clipped = true; 140 } 141 } 142 break; 143 } 144 case SkRegion::kUnion_Op: { 145 if (CC_UNLIKELY(clipRegion)) { 146 ensureClipRegion(); 147 clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kUnion_Op); 148 } else { 149 clipped = clipRect->unionWith(r); 150 } 151 break; 152 } 153 case SkRegion::kReplace_Op: { 154 setClip(r.left, r.top, r.right, r.bottom); 155 clipped = true; 156 break; 157 } 158 default: { 159 ensureClipRegion(); 160 clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, op); 161 break; 162 } 163 } 164 165 if (clipped) { 166 flags |= Snapshot::kFlagClipSet; 167 } 168 169 return clipped; 170} 171 172void Snapshot::setClip(float left, float top, float right, float bottom) { 173 clipRect->set(left, top, right, bottom); 174#if STENCIL_BUFFER_SIZE 175 if (clipRegion) { 176 clipRegion->setEmpty(); 177 clipRegion = NULL; 178 } 179#endif 180 flags |= Snapshot::kFlagClipSet; 181} 182 183bool Snapshot::hasPerspectiveTransform() const { 184 return transform->isPerspective(); 185} 186 187const Rect& Snapshot::getLocalClip() { 188 mat4 inverse; 189 inverse.loadInverse(*transform); 190 191 mLocalClip.set(*clipRect); 192 inverse.mapRect(mLocalClip); 193 194 return mLocalClip; 195} 196 197void Snapshot::resetClip(float left, float top, float right, float bottom) { 198 clipRect = &mClipRectRoot; 199 setClip(left, top, right, bottom); 200} 201 202/////////////////////////////////////////////////////////////////////////////// 203// Transforms 204/////////////////////////////////////////////////////////////////////////////// 205 206void Snapshot::resetTransform(float x, float y, float z) { 207 transform = &mTransformRoot; 208 transform->loadTranslate(x, y, z); 209} 210 211/////////////////////////////////////////////////////////////////////////////// 212// Queries 213/////////////////////////////////////////////////////////////////////////////// 214 215bool Snapshot::isIgnored() const { 216 return invisible || empty; 217} 218 219}; // namespace uirenderer 220}; // namespace android 221