Snapshot.cpp revision ada4d53d50dc869b8278573ad640dc44118d3bcf
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) {
30
31    transform = &mTransformRoot;
32    clipRect = &mClipRectRoot;
33    region = NULL;
34}
35
36/**
37 * Copies the specified snapshot/ The specified snapshot is stored as
38 * the previous snapshot.
39 */
40Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags):
41        flags(0), previous(s), layer(NULL), fbo(s->fbo),
42        invisible(s->invisible), empty(false),
43        viewport(s->viewport), height(s->height) {
44
45    if (saveFlags & SkCanvas::kMatrix_SaveFlag) {
46        mTransformRoot.load(*s->transform);
47        transform = &mTransformRoot;
48    } else {
49        transform = s->transform;
50    }
51
52    if (saveFlags & SkCanvas::kClip_SaveFlag) {
53        mClipRectRoot.set(*s->clipRect);
54        clipRect = &mClipRectRoot;
55    } else {
56        clipRect = s->clipRect;
57    }
58
59    if (s->flags & Snapshot::kFlagFboTarget) {
60        flags |= Snapshot::kFlagFboTarget;
61        region = s->region;
62    } else {
63        region = NULL;
64    }
65}
66
67///////////////////////////////////////////////////////////////////////////////
68// Clipping
69///////////////////////////////////////////////////////////////////////////////
70
71bool Snapshot::clip(float left, float top, float right, float bottom, SkRegion::Op op) {
72    Rect r(left, top, right, bottom);
73    transform->mapRect(r);
74    return clipTransformed(r, op);
75}
76
77bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) {
78    bool clipped = false;
79
80    // NOTE: The unimplemented operations require support for regions
81    // Supporting regions would require using a stencil buffer instead
82    // of the scissor. The stencil buffer itself is not too expensive
83    // (memory cost excluded) but on fillrate limited devices, managing
84    // the stencil might have a negative impact on the framerate.
85    switch (op) {
86        case SkRegion::kDifference_Op:
87            break;
88        case SkRegion::kIntersect_Op:
89            clipped = clipRect->intersect(r);
90            if (!clipped) {
91                clipRect->setEmpty();
92                clipped = true;
93            }
94            break;
95        case SkRegion::kUnion_Op:
96            clipped = clipRect->unionWith(r);
97            break;
98        case SkRegion::kXOR_Op:
99            break;
100        case SkRegion::kReverseDifference_Op:
101            break;
102        case SkRegion::kReplace_Op:
103            clipRect->set(r);
104            clipped = true;
105            break;
106    }
107
108    if (clipped) {
109        flags |= Snapshot::kFlagClipSet;
110    }
111
112    return clipped;
113}
114
115void Snapshot::setClip(float left, float top, float right, float bottom) {
116    clipRect->set(left, top, right, bottom);
117    flags |= Snapshot::kFlagClipSet;
118}
119
120const Rect& Snapshot::getLocalClip() {
121    mat4 inverse;
122    inverse.loadInverse(*transform);
123
124    mLocalClip.set(*clipRect);
125    inverse.mapRect(mLocalClip);
126
127    return mLocalClip;
128}
129
130void Snapshot::resetClip(float left, float top, float right, float bottom) {
131    clipRect = &mClipRectRoot;
132    clipRect->set(left, top, right, bottom);
133    flags |= Snapshot::kFlagClipSet;
134}
135
136///////////////////////////////////////////////////////////////////////////////
137// Transforms
138///////////////////////////////////////////////////////////////////////////////
139
140void Snapshot::resetTransform(float x, float y, float z) {
141    transform = &mTransformRoot;
142    transform->loadTranslate(x, y, z);
143}
144
145///////////////////////////////////////////////////////////////////////////////
146// Queries
147///////////////////////////////////////////////////////////////////////////////
148
149bool Snapshot::isIgnored() const {
150    return invisible || empty;
151}
152
153}; // namespace uirenderer
154}; // namespace android
155