Snapshot.cpp revision 3c099c42fd7ead1429076055990ae39b72c904f4
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 = &mClipRegionRoot; 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(s->layer), fbo(s->fbo), 43 invisible(s->invisible), empty(false), 44 viewport(s->viewport), height(s->height), alpha(s->alpha) { 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; 56 if (!s->clipRegion->isEmpty()) { 57 mClipRegionRoot.op(*s->clipRegion, SkRegion::kUnion_Op); 58 } 59 clipRegion = &mClipRegionRoot; 60 } else { 61 clipRect = s->clipRect; 62 clipRegion = s->clipRegion; 63 } 64 65 if (s->flags & Snapshot::kFlagFboTarget) { 66 flags |= Snapshot::kFlagFboTarget; 67 region = s->region; 68 } else { 69 region = NULL; 70 } 71} 72 73/////////////////////////////////////////////////////////////////////////////// 74// Clipping 75/////////////////////////////////////////////////////////////////////////////// 76 77void Snapshot::ensureClipRegion() { 78 if (clipRegion->isEmpty()) { 79 clipRegion->setRect(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom); 80 } 81} 82 83void Snapshot::copyClipRectFromRegion() { 84 if (!clipRegion->isEmpty()) { 85 const SkIRect& bounds = clipRegion->getBounds(); 86 clipRect->set(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); 87 88 if (clipRegion->isRect()) { 89 clipRegion->setEmpty(); 90 } 91 } else { 92 clipRect->setEmpty(); 93 } 94} 95 96bool Snapshot::clipRegionOp(float left, float top, float right, float bottom, SkRegion::Op op) { 97 SkIRect tmp; 98 tmp.set(left, top, right, bottom); 99 clipRegion->op(tmp, op); 100 copyClipRectFromRegion(); 101 return true; 102} 103 104bool Snapshot::clipRegionTransformed(const SkRegion& region, SkRegion::Op op) { 105 ensureClipRegion(); 106 clipRegion->op(region, op); 107 copyClipRectFromRegion(); 108 flags |= Snapshot::kFlagClipSet; 109 return true; 110} 111 112bool Snapshot::clip(float left, float top, float right, float bottom, SkRegion::Op op) { 113 Rect r(left, top, right, bottom); 114 transform->mapRect(r); 115 return clipTransformed(r, op); 116} 117 118bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) { 119 bool clipped = false; 120 121 switch (op) { 122 case SkRegion::kIntersect_Op: { 123 if (CC_UNLIKELY(!clipRegion->isEmpty())) { 124 ensureClipRegion(); 125 clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kIntersect_Op); 126 } else { 127 clipped = clipRect->intersect(r); 128 if (!clipped) { 129 clipRect->setEmpty(); 130 clipped = true; 131 } 132 } 133 break; 134 } 135 case SkRegion::kUnion_Op: { 136 if (CC_UNLIKELY(!clipRegion->isEmpty())) { 137 ensureClipRegion(); 138 clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kUnion_Op); 139 } else { 140 clipped = clipRect->unionWith(r); 141 } 142 break; 143 } 144 case SkRegion::kReplace_Op: { 145 setClip(r.left, r.top, r.right, r.bottom); 146 clipped = true; 147 break; 148 } 149 default: { 150 ensureClipRegion(); 151 clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, op); 152 break; 153 } 154 } 155 156 if (clipped) { 157 flags |= Snapshot::kFlagClipSet; 158 } 159 160 return clipped; 161} 162 163void Snapshot::setClip(float left, float top, float right, float bottom) { 164 clipRect->set(left, top, right, bottom); 165 if (!clipRegion->isEmpty()) { 166 clipRegion->setEmpty(); 167 } 168 flags |= Snapshot::kFlagClipSet; 169} 170 171bool Snapshot::hasPerspectiveTransform() const { 172 return transform->isPerspective(); 173} 174 175const Rect& Snapshot::getLocalClip() { 176 mat4 inverse; 177 inverse.loadInverse(*transform); 178 179 mLocalClip.set(*clipRect); 180 inverse.mapRect(mLocalClip); 181 182 return mLocalClip; 183} 184 185void Snapshot::resetClip(float left, float top, float right, float bottom) { 186 clipRect = &mClipRectRoot; 187 clipRegion = &mClipRegionRoot; 188 setClip(left, top, right, bottom); 189} 190 191/////////////////////////////////////////////////////////////////////////////// 192// Transforms 193/////////////////////////////////////////////////////////////////////////////// 194 195void Snapshot::resetTransform(float x, float y, float z) { 196 transform = &mTransformRoot; 197 transform->loadTranslate(x, y, z); 198} 199 200/////////////////////////////////////////////////////////////////////////////// 201// Queries 202/////////////////////////////////////////////////////////////////////////////// 203 204bool Snapshot::isIgnored() const { 205 return invisible || empty; 206} 207 208}; // namespace uirenderer 209}; // namespace android 210