1acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck/*
2acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * Copyright (C) 2014 The Android Open Source Project
3acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck *
4acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * Licensed under the Apache License, Version 2.0 (the "License");
5acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * you may not use this file except in compliance with the License.
6acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * You may obtain a copy of the License at
7acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck *
8acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck *      http://www.apache.org/licenses/LICENSE-2.0
9acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck *
10acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * Unless required by applicable law or agreed to in writing, software
11acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * distributed under the License is distributed on an "AS IS" BASIS,
12acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * See the License for the specific language governing permissions and
14acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * limitations under the License.
15acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck */
16b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik#ifndef RENDERNODEPROPERTIES_H
17b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik#define RENDERNODEPROPERTIES_H
18acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
1976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik#include "Caches.h"
2076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik#include "DeviceInfo.h"
2176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik#include "Rect.h"
2276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik#include "RevealClip.h"
2376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik#include "Outline.h"
2476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik#include "utils/MathUtils.h"
25acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
26acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck#include <SkCamera.h>
27acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck#include <SkMatrix.h>
288c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik#include <SkRegion.h>
292dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson#include <SkXfermode.h>
30b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
3176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik#include <algorithm>
3276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik#include <stddef.h>
3376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik#include <vector>
3476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik#include <cutils/compiler.h>
3576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik#include <androidfw/ResourceTypes.h>
3676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik#include <utils/Log.h>
37acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
38acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckclass SkBitmap;
3925fbb3fa1138675379102a44405852555cefccbdJohn Reckclass SkColorFilter;
40acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckclass SkPaint;
41acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
42acb6f07623b7df3d4179f70ae03ade574616ffa6John Recknamespace android {
43acb6f07623b7df3d4179f70ae03ade574616ffa6John Recknamespace uirenderer {
44acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
45acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckclass Matrix4;
46acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckclass RenderNode;
4725fbb3fa1138675379102a44405852555cefccbdJohn Reckclass RenderProperties;
48acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
4979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck// The __VA_ARGS__ will be executed if a & b are not equal
5079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck#define RP_SET(a, b, ...) (a != b ? (a = b, ##__VA_ARGS__, true) : false)
5179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck#define RP_SET_AND_DIRTY(a, b) RP_SET(a, b, mPrimitiveFields.mMatrixOrPivotDirty = true)
5279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck
5325fbb3fa1138675379102a44405852555cefccbdJohn Reck// Keep in sync with View.java:LAYER_TYPE_*
54182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craikenum class LayerType {
55182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    None = 0,
5625fbb3fa1138675379102a44405852555cefccbdJohn Reck    // Although we cannot build the software layer directly (must be done at
5725fbb3fa1138675379102a44405852555cefccbdJohn Reck    // record time), this information is used when applying alpha.
58182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    Software = 1,
59182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    RenderLayer = 2,
6025fbb3fa1138675379102a44405852555cefccbdJohn Reck    // TODO: LayerTypeSurfaceTexture? Maybe?
6125fbb3fa1138675379102a44405852555cefccbdJohn Reck};
6225fbb3fa1138675379102a44405852555cefccbdJohn Reck
63a753f4c6cb8558795e673df1896532cd148781e2Chris Craikenum ClippingFlags {
64a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    CLIP_TO_BOUNDS =      0x1 << 0,
65a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    CLIP_TO_CLIP_BOUNDS = 0x1 << 1,
66a753f4c6cb8558795e673df1896532cd148781e2Chris Craik};
67a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
6825fbb3fa1138675379102a44405852555cefccbdJohn Reckclass ANDROID_API LayerProperties {
6925fbb3fa1138675379102a44405852555cefccbdJohn Reckpublic:
7025fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setType(LayerType type) {
7125fbb3fa1138675379102a44405852555cefccbdJohn Reck        if (RP_SET(mType, type)) {
7225fbb3fa1138675379102a44405852555cefccbdJohn Reck            reset();
7325fbb3fa1138675379102a44405852555cefccbdJohn Reck            return true;
7425fbb3fa1138675379102a44405852555cefccbdJohn Reck        }
7525fbb3fa1138675379102a44405852555cefccbdJohn Reck        return false;
7625fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
7725fbb3fa1138675379102a44405852555cefccbdJohn Reck
7825fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setOpaque(bool opaque) {
7925fbb3fa1138675379102a44405852555cefccbdJohn Reck        return RP_SET(mOpaque, opaque);
8025fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
8125fbb3fa1138675379102a44405852555cefccbdJohn Reck
8225fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool opaque() const {
8325fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mOpaque;
8425fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
8525fbb3fa1138675379102a44405852555cefccbdJohn Reck
8625fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setAlpha(uint8_t alpha) {
8725fbb3fa1138675379102a44405852555cefccbdJohn Reck        return RP_SET(mAlpha, alpha);
8825fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
8925fbb3fa1138675379102a44405852555cefccbdJohn Reck
9025fbb3fa1138675379102a44405852555cefccbdJohn Reck    uint8_t alpha() const {
9125fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mAlpha;
9225fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
9325fbb3fa1138675379102a44405852555cefccbdJohn Reck
9425fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setXferMode(SkXfermode::Mode mode) {
9525fbb3fa1138675379102a44405852555cefccbdJohn Reck        return RP_SET(mMode, mode);
9625fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
9725fbb3fa1138675379102a44405852555cefccbdJohn Reck
9825fbb3fa1138675379102a44405852555cefccbdJohn Reck    SkXfermode::Mode xferMode() const {
9925fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mMode;
10025fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
10125fbb3fa1138675379102a44405852555cefccbdJohn Reck
10225fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setColorFilter(SkColorFilter* filter);
10325fbb3fa1138675379102a44405852555cefccbdJohn Reck
10425fbb3fa1138675379102a44405852555cefccbdJohn Reck    SkColorFilter* colorFilter() const {
10525fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mColorFilter;
10625fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
10725fbb3fa1138675379102a44405852555cefccbdJohn Reck
10825fbb3fa1138675379102a44405852555cefccbdJohn Reck    // Sets alpha, xfermode, and colorfilter from an SkPaint
10925fbb3fa1138675379102a44405852555cefccbdJohn Reck    // paint may be NULL, in which case defaults will be set
11025fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setFromPaint(const SkPaint* paint);
11125fbb3fa1138675379102a44405852555cefccbdJohn Reck
11225fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool needsBlending() const {
11325fbb3fa1138675379102a44405852555cefccbdJohn Reck        return !opaque() || alpha() < 255;
11425fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
11525fbb3fa1138675379102a44405852555cefccbdJohn Reck
11625fbb3fa1138675379102a44405852555cefccbdJohn Reck    LayerProperties& operator=(const LayerProperties& other);
11725fbb3fa1138675379102a44405852555cefccbdJohn Reck
11825fbb3fa1138675379102a44405852555cefccbdJohn Reckprivate:
11925fbb3fa1138675379102a44405852555cefccbdJohn Reck    LayerProperties();
12025fbb3fa1138675379102a44405852555cefccbdJohn Reck    ~LayerProperties();
12125fbb3fa1138675379102a44405852555cefccbdJohn Reck    void reset();
12225fbb3fa1138675379102a44405852555cefccbdJohn Reck
123856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik    // Private since external users should go through properties().effectiveLayerType()
124856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik    LayerType type() const {
125856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik        return mType;
126856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik    }
127856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik
12825fbb3fa1138675379102a44405852555cefccbdJohn Reck    friend class RenderProperties;
12925fbb3fa1138675379102a44405852555cefccbdJohn Reck
130182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    LayerType mType = LayerType::None;
13125fbb3fa1138675379102a44405852555cefccbdJohn Reck    // Whether or not that Layer's content is opaque, doesn't include alpha
13225fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool mOpaque;
13325fbb3fa1138675379102a44405852555cefccbdJohn Reck    uint8_t mAlpha;
13425fbb3fa1138675379102a44405852555cefccbdJohn Reck    SkXfermode::Mode mMode;
135182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    SkColorFilter* mColorFilter = nullptr;
13625fbb3fa1138675379102a44405852555cefccbdJohn Reck};
13725fbb3fa1138675379102a44405852555cefccbdJohn Reck
138acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck/*
139acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * Data structure that holds the properties for a RenderNode
140acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck */
14125fbb3fa1138675379102a44405852555cefccbdJohn Reckclass ANDROID_API RenderProperties {
142acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckpublic:
143acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    RenderProperties();
144acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    virtual ~RenderProperties();
145acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
146a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    static bool setFlag(int flag, bool newValue, int* outFlags) {
147a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        if (newValue) {
148a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            if (!(flag & *outFlags)) {
149a753f4c6cb8558795e673df1896532cd148781e2Chris Craik                *outFlags |= flag;
150a753f4c6cb8558795e673df1896532cd148781e2Chris Craik                return true;
151a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            }
152a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            return false;
153a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        } else {
154a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            if (flag & *outFlags) {
155a753f4c6cb8558795e673df1896532cd148781e2Chris Craik                *outFlags &= ~flag;
156a753f4c6cb8558795e673df1896532cd148781e2Chris Craik                return true;
157a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            }
158a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            return false;
159a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        }
160a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    }
161a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
162a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik    /**
163a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik     * Set internal layer state based on whether this layer
164a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik     *
165a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik     * Additionally, returns true if child RenderNodes with functors will need to use a layer
166a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik     * to support clipping.
167a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik     */
168a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik    bool prepareForFunctorPresence(bool willHaveFunctor, bool ancestorDictatesFunctorsNeedLayer) {
169a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        // parent may have already dictated that a descendant layer is needed
170a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        bool functorsNeedLayer = ancestorDictatesFunctorsNeedLayer
171a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
172a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                // Round rect clipping forces layer for functors
173b60d3e7856f74c72898b2cba553db0d2e2d1365dChris Craik                || CC_UNLIKELY(getOutline().willRoundRectClip())
174a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                || CC_UNLIKELY(getRevealClip().willClip())
175a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
176a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                // Complex matrices forces layer, due to stencil clipping
177a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                || CC_UNLIKELY(getTransformMatrix() && !getTransformMatrix()->isScaleTranslate())
178a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                || CC_UNLIKELY(getAnimationMatrix() && !getAnimationMatrix()->isScaleTranslate())
179a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                || CC_UNLIKELY(getStaticMatrix() && !getStaticMatrix()->isScaleTranslate());
180a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
181a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        mComputedFields.mNeedLayerForFunctors = (willHaveFunctor && functorsNeedLayer);
182a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
183a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        // If on a layer, will have consumed the need for isolating functors from stencil.
184a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        // Thus, it's safe to reset the flag until some descendent sets it.
185a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        return CC_LIKELY(effectiveLayerType() == LayerType::None) && functorsNeedLayer;
186a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik    }
187a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
188d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    RenderProperties& operator=(const RenderProperties& other);
189d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
19079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setClipToBounds(bool clipToBounds) {
191a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        return setFlag(CLIP_TO_BOUNDS, clipToBounds, &mPrimitiveFields.mClippingFlags);
192a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    }
193a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
194a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    bool setClipBounds(const Rect& clipBounds) {
195a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        bool ret = setFlag(CLIP_TO_CLIP_BOUNDS, true, &mPrimitiveFields.mClippingFlags);
196a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        return RP_SET(mPrimitiveFields.mClipBounds, clipBounds) || ret;
197a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    }
198a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
199a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    bool setClipBoundsEmpty() {
200a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        return setFlag(CLIP_TO_CLIP_BOUNDS, false, &mPrimitiveFields.mClippingFlags);
201acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
202acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
20379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setProjectBackwards(bool shouldProject) {
20479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET(mPrimitiveFields.mProjectBackwards, shouldProject);
205acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
206acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
2076fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    bool setProjectionReceiver(bool shouldReceive) {
2086fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        return RP_SET(mPrimitiveFields.mProjectionReceiver, shouldReceive);
209acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
210acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
211d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    bool isProjectionReceiver() const {
212d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mProjectionReceiver;
213acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
214acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
21579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setStaticMatrix(const SkMatrix* matrix) {
216acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        delete mStaticMatrix;
217d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        if (matrix) {
218d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mStaticMatrix = new SkMatrix(*matrix);
219d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        } else {
220e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik            mStaticMatrix = nullptr;
221d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        }
22279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return true;
223acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
224acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
225acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    // Can return NULL
226d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    const SkMatrix* getStaticMatrix() const {
227acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        return mStaticMatrix;
228acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
229acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
23079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setAnimationMatrix(const SkMatrix* matrix) {
231acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        delete mAnimationMatrix;
232acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        if (matrix) {
233acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            mAnimationMatrix = new SkMatrix(*matrix);
234acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        } else {
235e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik            mAnimationMatrix = nullptr;
236acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
23779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return true;
238acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
239acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
24079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setAlpha(float alpha) {
2413b52c03f5035b833d365215420739aa840ac5080John Reck        alpha = MathUtils::clampAlpha(alpha);
24279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET(mPrimitiveFields.mAlpha, alpha);
243acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
244acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
245acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getAlpha() const {
246d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mAlpha;
247acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
248acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
24979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setHasOverlappingRendering(bool hasOverlappingRendering) {
25079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET(mPrimitiveFields.mHasOverlappingRendering, hasOverlappingRendering);
251acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
252acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
253acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    bool hasOverlappingRendering() const {
254d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mHasOverlappingRendering;
255acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
256acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
25779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setElevation(float elevation) {
25879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET(mPrimitiveFields.mElevation, elevation);
25979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        // Don't dirty matrix/pivot, since they don't respect Z
260cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik    }
261cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik
262cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik    float getElevation() const {
263cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik        return mPrimitiveFields.mElevation;
264cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik    }
265cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik
26679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setTranslationX(float translationX) {
26779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationX, translationX);
268acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
269acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
270acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getTranslationX() const {
271d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mTranslationX;
272acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
273acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
27479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setTranslationY(float translationY) {
27579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationY, translationY);
276acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
277acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
278acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getTranslationY() const {
279d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mTranslationY;
280acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
281acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
28279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setTranslationZ(float translationZ) {
28379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET(mPrimitiveFields.mTranslationZ, translationZ);
28479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        // mMatrixOrPivotDirty not set, since matrix doesn't respect Z
285acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
286acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
287acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getTranslationZ() const {
288d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mTranslationZ;
289acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
290acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
291e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    // Animation helper
29279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setX(float value) {
29379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return setTranslationX(value - getLeft());
294e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
295e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
296e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    // Animation helper
297e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    float getX() const {
298e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        return getLeft() + getTranslationX();
299e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
300e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
301e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    // Animation helper
30279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setY(float value) {
30379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return setTranslationY(value - getTop());
304e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
305e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
306e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    // Animation helper
307e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    float getY() const {
308e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        return getTop() + getTranslationY();
309e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
310e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
311e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    // Animation helper
31279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setZ(float value) {
31379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return setTranslationZ(value - getElevation());
314e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
315e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
316cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik    float getZ() const {
317cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik        return getElevation() + getTranslationZ();
318cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik    }
319cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik
32079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setRotation(float rotation) {
32179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mRotation, rotation);
322acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
323acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
324acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getRotation() const {
325d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mRotation;
326acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
327acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
32879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setRotationX(float rotationX) {
32979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationX, rotationX);
330acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
331acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
332acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getRotationX() const {
333d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mRotationX;
334acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
335acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
33679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setRotationY(float rotationY) {
33779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationY, rotationY);
338acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
339acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
340acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getRotationY() const {
341d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mRotationY;
342acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
343acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
34479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setScaleX(float scaleX) {
34579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleX, scaleX);
346acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
347acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
348acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getScaleX() const {
349d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mScaleX;
350acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
351acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
35279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setScaleY(float scaleY) {
35379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleY, scaleY);
354acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
355acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
356acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getScaleY() const {
357d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mScaleY;
358acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
359acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
36079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setPivotX(float pivotX) {
36179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mPivotX, pivotX)
36279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck                || !mPrimitiveFields.mPivotExplicitlySet) {
36379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            mPrimitiveFields.mMatrixOrPivotDirty = true;
36479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            mPrimitiveFields.mPivotExplicitlySet = true;
36579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
36679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        }
36779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
368acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
369acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
370d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    /* Note that getPivotX and getPivotY are adjusted by updateMatrix(),
37179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck     * so the value returned may be stale if the RenderProperties has been
37279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck     * modified since the last call to updateMatrix()
373d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck     */
374d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    float getPivotX() const {
375d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mPivotX;
376d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
377acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
37879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setPivotY(float pivotY) {
37979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mPivotY, pivotY)
38079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck                || !mPrimitiveFields.mPivotExplicitlySet) {
38179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            mPrimitiveFields.mMatrixOrPivotDirty = true;
38279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            mPrimitiveFields.mPivotExplicitlySet = true;
38379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
38479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        }
38579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
386acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
387acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
388d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    float getPivotY() const {
389d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mPivotY;
390d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
391acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
39249e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik    bool isPivotExplicitlySet() const {
39349e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        return mPrimitiveFields.mPivotExplicitlySet;
39449e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik    }
39549e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik
39679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setCameraDistance(float distance) {
39749e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        if (distance != getCameraDistance()) {
398f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            mPrimitiveFields.mMatrixOrPivotDirty = true;
39949e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik            mComputedFields.mTransformCamera.setCameraLocation(0, 0, distance);
40079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
401acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
40279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
403acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
404acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
405acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getCameraDistance() const {
40649e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        // TODO: update getCameraLocationZ() to be const
40749e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        return const_cast<Sk3DView*>(&mComputedFields.mTransformCamera)->getCameraLocationZ();
408acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
409acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
41079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setLeft(int left) {
41179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mLeft, left)) {
412d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
413f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            if (!mPrimitiveFields.mPivotExplicitlySet) {
414f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck                mPrimitiveFields.mMatrixOrPivotDirty = true;
415acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            }
41679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
417acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
41879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
419acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
420acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
421e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    int getLeft() const {
422d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mLeft;
423acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
424acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
42579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setTop(int top) {
42679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mTop, top)) {
427d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
428f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            if (!mPrimitiveFields.mPivotExplicitlySet) {
429f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck                mPrimitiveFields.mMatrixOrPivotDirty = true;
430acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            }
43179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
432acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
43379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
434acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
435acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
436e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    int getTop() const {
437d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mTop;
438acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
439acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
44079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setRight(int right) {
44179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mRight, right)) {
442d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
443f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            if (!mPrimitiveFields.mPivotExplicitlySet) {
444f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck                mPrimitiveFields.mMatrixOrPivotDirty = true;
445acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            }
44679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
447acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
44879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
449acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
450acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
451e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    int getRight() const {
452d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mRight;
453acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
454acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
45579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setBottom(int bottom) {
45679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mBottom, bottom)) {
457d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
458f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            if (!mPrimitiveFields.mPivotExplicitlySet) {
459f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck                mPrimitiveFields.mMatrixOrPivotDirty = true;
460acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            }
46179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
462acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
46379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
464acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
465acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
466e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    int getBottom() const {
467d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mBottom;
468acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
469acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
47079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setLeftTop(int left, int top) {
47179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        bool leftResult = setLeft(left);
47279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        bool topResult = setTop(top);
47379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return leftResult || topResult;
474acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
475acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
47679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setLeftTopRightBottom(int left, int top, int right, int bottom) {
477cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik        if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop
478cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik                || right != mPrimitiveFields.mRight || bottom != mPrimitiveFields.mBottom) {
479d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mLeft = left;
480d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mTop = top;
481d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mRight = right;
482d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mBottom = bottom;
483d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
484d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
485f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            if (!mPrimitiveFields.mPivotExplicitlySet) {
486f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck                mPrimitiveFields.mMatrixOrPivotDirty = true;
487acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            }
48879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
489acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
49079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
491acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
492acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
493a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    bool offsetLeftRight(int offset) {
494acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        if (offset != 0) {
495d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mLeft += offset;
496d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mRight += offset;
49779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
498acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
49979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
500acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
501acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
502a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    bool offsetTopBottom(int offset) {
503acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        if (offset != 0) {
504d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mTop += offset;
505d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mBottom += offset;
50679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
507acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
50879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
509acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
510acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
511b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    int getWidth() const {
512d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mWidth;
513acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
514acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
515b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    int getHeight() const {
516d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mHeight;
517d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
518d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
519d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    const SkMatrix* getAnimationMatrix() const {
520d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mAnimationMatrix;
521d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
522d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
523f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck    bool hasTransformMatrix() const {
524f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck        return getTransformMatrix() && !getTransformMatrix()->isIdentity();
525f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck    }
526f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck
527f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck    // May only call this if hasTransformMatrix() is true
528f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck    bool isTransformTranslateOnly() const {
529f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck        return getTransformMatrix()->getType() == SkMatrix::kTranslate_Mask;
530d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
531d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
53249e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik    const SkMatrix* getTransformMatrix() const {
533f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck        LOG_ALWAYS_FATAL_IF(mPrimitiveFields.mMatrixOrPivotDirty, "Cannot get a dirty matrix!");
534d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mComputedFields.mTransformMatrix;
535d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
536d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
537a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    int getClippingFlags() const {
538a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        return mPrimitiveFields.mClippingFlags;
539a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    }
540a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
541d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    bool getClipToBounds() const {
542a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        return mPrimitiveFields.mClippingFlags & CLIP_TO_BOUNDS;
543a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    }
544a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
545e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    const Rect& getClipBounds() const {
546e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        return mPrimitiveFields.mClipBounds;
547e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    }
548e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck
549a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    void getClippingRectForFlags(uint32_t flags, Rect* outRect) const {
550a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        if (flags & CLIP_TO_BOUNDS) {
551a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            outRect->set(0, 0, getWidth(), getHeight());
552a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            if (flags & CLIP_TO_CLIP_BOUNDS) {
553ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik                outRect->doIntersect(mPrimitiveFields.mClipBounds);
554a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            }
555a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        } else {
556a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            outRect->set(mPrimitiveFields.mClipBounds);
557a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        }
558d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
559d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
560d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    bool getHasOverlappingRendering() const {
561d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mHasOverlappingRendering;
562d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
563d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
564d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    const Outline& getOutline() const {
565d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mOutline;
566d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
567d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
5688c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik    const RevealClip& getRevealClip() const {
5698c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik        return mPrimitiveFields.mRevealClip;
5708c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik    }
5718c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik
572d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    bool getProjectBackwards() const {
573d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mProjectBackwards;
574d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
575d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
576d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    void debugOutputProperties(const int level) const;
577d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
57825fbb3fa1138675379102a44405852555cefccbdJohn Reck    void updateMatrix();
579d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
580d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    Outline& mutableOutline() {
581d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mOutline;
582b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    }
583b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
5848c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik    RevealClip& mutableRevealClip() {
5858c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik        return mPrimitiveFields.mRevealClip;
5868c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik    }
5878c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik
58825fbb3fa1138675379102a44405852555cefccbdJohn Reck    const LayerProperties& layerProperties() const {
58925fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mLayerProperties;
59025fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
59125fbb3fa1138675379102a44405852555cefccbdJohn Reck
59225fbb3fa1138675379102a44405852555cefccbdJohn Reck    LayerProperties& mutateLayerProperties() {
59325fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mLayerProperties;
59425fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
59525fbb3fa1138675379102a44405852555cefccbdJohn Reck
596293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    // Returns true if damage calculations should be clipped to bounds
597293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    // TODO: Figure out something better for getZ(), as children should still be
598293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    // clipped to this RP's bounds. But as we will damage -INT_MAX to INT_MAX
599293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    // for this RP's getZ() anyway, this can be optimized when we have a
600293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    // Z damage estimate instead of INT_MAX
601293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    bool getClipDamageToBounds() const {
602293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck        return getClipToBounds() && (getZ() <= 0 || getOutline().isEmpty());
603293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    }
604293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck
6055c75c52e048a01c23b18f4e31ae624b5fe43e23cChris Craik    bool hasShadow() const {
606b5a5435a77bae40b55053ccde93b1ed45d0e8329Chris Craik        return getZ() > 0.0f
607e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik                && getOutline().getPath() != nullptr
6089fa364dc72613f4301b0783f0547fe6b01abac39Chris Craik                && getOutline().getAlpha() != 0.0f;
6095c75c52e048a01c23b18f4e31ae624b5fe43e23cChris Craik    }
6105c75c52e048a01c23b18f4e31ae624b5fe43e23cChris Craik
6119fded232a9548a304e0145011df8849fba0dcda7Chris Craik    bool fitsOnLayer() const {
61276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        const DeviceInfo* deviceInfo = DeviceInfo::get();
6139fded232a9548a304e0145011df8849fba0dcda7Chris Craik        return mPrimitiveFields.mWidth <= deviceInfo->maxTextureSize()
6142e4e3dbb02a8d2c7efbe8b06c30abc183accc75bChris Craik                        && mPrimitiveFields.mHeight <= deviceInfo->maxTextureSize();
6159fded232a9548a304e0145011df8849fba0dcda7Chris Craik    }
6169fded232a9548a304e0145011df8849fba0dcda7Chris Craik
6179fded232a9548a304e0145011df8849fba0dcda7Chris Craik    bool promotedToLayer() const {
6181a0808e64c170fa7b620b858fa5875f6f08a2b54Chris Craik        return mLayerProperties.mType == LayerType::None
6199fded232a9548a304e0145011df8849fba0dcda7Chris Craik                && fitsOnLayer()
620a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                && (mComputedFields.mNeedLayerForFunctors
621a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                        || (!MathUtils::isZero(mPrimitiveFields.mAlpha)
622a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                                && mPrimitiveFields.mAlpha < 1
623a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                                && mPrimitiveFields.mHasOverlappingRendering));
6241a0808e64c170fa7b620b858fa5875f6f08a2b54Chris Craik    }
6251a0808e64c170fa7b620b858fa5875f6f08a2b54Chris Craik
6261a0808e64c170fa7b620b858fa5875f6f08a2b54Chris Craik    LayerType effectiveLayerType() const {
627a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        return CC_UNLIKELY(promotedToLayer()) ? LayerType::RenderLayer : mLayerProperties.mType;
628856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik    }
629856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik
630acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckprivate:
631acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    // Rendering properties
632d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    struct PrimitiveFields {
633e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        int mLeft = 0, mTop = 0, mRight = 0, mBottom = 0;
634e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        int mWidth = 0, mHeight = 0;
635e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        int mClippingFlags = CLIP_TO_BOUNDS;
636e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mAlpha = 1;
637e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mTranslationX = 0, mTranslationY = 0, mTranslationZ = 0;
638e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mElevation = 0;
639e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mRotation = 0, mRotationX = 0, mRotationY = 0;
640e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mScaleX = 1, mScaleY = 1;
641e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mPivotX = 0, mPivotY = 0;
642e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        bool mHasOverlappingRendering = false;
643e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        bool mPivotExplicitlySet = false;
644e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        bool mMatrixOrPivotDirty = false;
645e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        bool mProjectBackwards = false;
646e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        bool mProjectionReceiver = false;
647e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        Rect mClipBounds;
648d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        Outline mOutline;
6498c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik        RevealClip mRevealClip;
650d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    } mPrimitiveFields;
651d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
652acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    SkMatrix* mStaticMatrix;
653acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    SkMatrix* mAnimationMatrix;
65425fbb3fa1138675379102a44405852555cefccbdJohn Reck    LayerProperties mLayerProperties;
655acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
656d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    /**
657d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck     * These fields are all generated from other properties and are not set directly.
658d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck     */
659d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    struct ComputedFields {
660d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        ComputedFields();
661d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        ~ComputedFields();
662d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
663d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        /**
664d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck         * Stores the total transformation of the DisplayList based upon its scalar
665d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck         * translate/rotate/scale properties.
666d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck         *
66749e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik         * In the common translation-only case, the matrix isn't necessarily allocated,
66849e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik         * and the mTranslation properties are used directly.
669d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck         */
67049e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        SkMatrix* mTransformMatrix;
67149e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik
67249e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        Sk3DView mTransformCamera;
673a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
674a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        // Force layer on for functors to enable render features they don't yet support (clipping)
675a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        bool mNeedLayerForFunctors = false;
676d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    } mComputedFields;
677acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck};
678acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
679acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck} /* namespace uirenderer */
680acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck} /* namespace android */
681acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
682b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik#endif /* RENDERNODEPROPERTIES_H */
683