RenderProperties.h revision 6fe991e5e76f9af9dab960100d5768d96d5f4daa
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
19e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck#include <algorithm>
20acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck#include <stddef.h>
21e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck#include <vector>
22acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck#include <cutils/compiler.h>
23acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck#include <androidfw/ResourceTypes.h>
24fe02b4b344c37200486d8afc972560fb550cb17eChris Craik#include <utils/Log.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
314e9d9b2a590105035c29f12ecf0689333e6b55e7Chris Craik#include "Caches.h"
32b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik#include "Rect.h"
338c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik#include "RevealClip.h"
34b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik#include "Outline.h"
35293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck#include "utils/MathUtils.h"
36acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
37acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckclass SkBitmap;
3825fbb3fa1138675379102a44405852555cefccbdJohn Reckclass SkColorFilter;
39acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckclass SkPaint;
40acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
41acb6f07623b7df3d4179f70ae03ade574616ffa6John Recknamespace android {
42acb6f07623b7df3d4179f70ae03ade574616ffa6John Recknamespace uirenderer {
43acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
44acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckclass Matrix4;
45acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckclass RenderNode;
4625fbb3fa1138675379102a44405852555cefccbdJohn Reckclass RenderProperties;
47acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
4879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck// The __VA_ARGS__ will be executed if a & b are not equal
4979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck#define RP_SET(a, b, ...) (a != b ? (a = b, ##__VA_ARGS__, true) : false)
5079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck#define RP_SET_AND_DIRTY(a, b) RP_SET(a, b, mPrimitiveFields.mMatrixOrPivotDirty = true)
5179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck
5225fbb3fa1138675379102a44405852555cefccbdJohn Reck// Keep in sync with View.java:LAYER_TYPE_*
53182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craikenum class LayerType {
54182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    None = 0,
5525fbb3fa1138675379102a44405852555cefccbdJohn Reck    // Although we cannot build the software layer directly (must be done at
5625fbb3fa1138675379102a44405852555cefccbdJohn Reck    // record time), this information is used when applying alpha.
57182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    Software = 1,
58182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    RenderLayer = 2,
5925fbb3fa1138675379102a44405852555cefccbdJohn Reck    // TODO: LayerTypeSurfaceTexture? Maybe?
6025fbb3fa1138675379102a44405852555cefccbdJohn Reck};
6125fbb3fa1138675379102a44405852555cefccbdJohn Reck
62a753f4c6cb8558795e673df1896532cd148781e2Chris Craikenum ClippingFlags {
63a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    CLIP_TO_BOUNDS =      0x1 << 0,
64a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    CLIP_TO_CLIP_BOUNDS = 0x1 << 1,
65a753f4c6cb8558795e673df1896532cd148781e2Chris Craik};
66a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
6725fbb3fa1138675379102a44405852555cefccbdJohn Reckclass ANDROID_API LayerProperties {
6825fbb3fa1138675379102a44405852555cefccbdJohn Reckpublic:
6925fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setType(LayerType type) {
7025fbb3fa1138675379102a44405852555cefccbdJohn Reck        if (RP_SET(mType, type)) {
7125fbb3fa1138675379102a44405852555cefccbdJohn Reck            reset();
7225fbb3fa1138675379102a44405852555cefccbdJohn Reck            return true;
7325fbb3fa1138675379102a44405852555cefccbdJohn Reck        }
7425fbb3fa1138675379102a44405852555cefccbdJohn Reck        return false;
7525fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
7625fbb3fa1138675379102a44405852555cefccbdJohn Reck
7725fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setOpaque(bool opaque) {
7825fbb3fa1138675379102a44405852555cefccbdJohn Reck        return RP_SET(mOpaque, opaque);
7925fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
8025fbb3fa1138675379102a44405852555cefccbdJohn Reck
8125fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool opaque() const {
8225fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mOpaque;
8325fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
8425fbb3fa1138675379102a44405852555cefccbdJohn Reck
8525fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setAlpha(uint8_t alpha) {
8625fbb3fa1138675379102a44405852555cefccbdJohn Reck        return RP_SET(mAlpha, alpha);
8725fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
8825fbb3fa1138675379102a44405852555cefccbdJohn Reck
8925fbb3fa1138675379102a44405852555cefccbdJohn Reck    uint8_t alpha() const {
9025fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mAlpha;
9125fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
9225fbb3fa1138675379102a44405852555cefccbdJohn Reck
9325fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setXferMode(SkXfermode::Mode mode) {
9425fbb3fa1138675379102a44405852555cefccbdJohn Reck        return RP_SET(mMode, mode);
9525fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
9625fbb3fa1138675379102a44405852555cefccbdJohn Reck
9725fbb3fa1138675379102a44405852555cefccbdJohn Reck    SkXfermode::Mode xferMode() const {
9825fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mMode;
9925fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
10025fbb3fa1138675379102a44405852555cefccbdJohn Reck
10125fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setColorFilter(SkColorFilter* filter);
10225fbb3fa1138675379102a44405852555cefccbdJohn Reck
10325fbb3fa1138675379102a44405852555cefccbdJohn Reck    SkColorFilter* colorFilter() const {
10425fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mColorFilter;
10525fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
10625fbb3fa1138675379102a44405852555cefccbdJohn Reck
10725fbb3fa1138675379102a44405852555cefccbdJohn Reck    // Sets alpha, xfermode, and colorfilter from an SkPaint
10825fbb3fa1138675379102a44405852555cefccbdJohn Reck    // paint may be NULL, in which case defaults will be set
10925fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setFromPaint(const SkPaint* paint);
11025fbb3fa1138675379102a44405852555cefccbdJohn Reck
11125fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool needsBlending() const {
11225fbb3fa1138675379102a44405852555cefccbdJohn Reck        return !opaque() || alpha() < 255;
11325fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
11425fbb3fa1138675379102a44405852555cefccbdJohn Reck
11525fbb3fa1138675379102a44405852555cefccbdJohn Reck    LayerProperties& operator=(const LayerProperties& other);
11625fbb3fa1138675379102a44405852555cefccbdJohn Reck
11725fbb3fa1138675379102a44405852555cefccbdJohn Reckprivate:
11825fbb3fa1138675379102a44405852555cefccbdJohn Reck    LayerProperties();
11925fbb3fa1138675379102a44405852555cefccbdJohn Reck    ~LayerProperties();
12025fbb3fa1138675379102a44405852555cefccbdJohn Reck    void reset();
12125fbb3fa1138675379102a44405852555cefccbdJohn Reck
122856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik    // Private since external users should go through properties().effectiveLayerType()
123856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik    LayerType type() const {
124856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik        return mType;
125856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik    }
126856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik
12725fbb3fa1138675379102a44405852555cefccbdJohn Reck    friend class RenderProperties;
12825fbb3fa1138675379102a44405852555cefccbdJohn Reck
129182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    LayerType mType = LayerType::None;
13025fbb3fa1138675379102a44405852555cefccbdJohn Reck    // Whether or not that Layer's content is opaque, doesn't include alpha
13125fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool mOpaque;
13225fbb3fa1138675379102a44405852555cefccbdJohn Reck    uint8_t mAlpha;
13325fbb3fa1138675379102a44405852555cefccbdJohn Reck    SkXfermode::Mode mMode;
134182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    SkColorFilter* mColorFilter = nullptr;
13525fbb3fa1138675379102a44405852555cefccbdJohn Reck};
13625fbb3fa1138675379102a44405852555cefccbdJohn Reck
137acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck/*
138acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * Data structure that holds the properties for a RenderNode
139acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck */
14025fbb3fa1138675379102a44405852555cefccbdJohn Reckclass ANDROID_API RenderProperties {
141acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckpublic:
142acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    RenderProperties();
143acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    virtual ~RenderProperties();
144acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
145a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    static bool setFlag(int flag, bool newValue, int* outFlags) {
146a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        if (newValue) {
147a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            if (!(flag & *outFlags)) {
148a753f4c6cb8558795e673df1896532cd148781e2Chris Craik                *outFlags |= flag;
149a753f4c6cb8558795e673df1896532cd148781e2Chris Craik                return true;
150a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            }
151a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            return false;
152a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        } else {
153a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            if (flag & *outFlags) {
154a753f4c6cb8558795e673df1896532cd148781e2Chris Craik                *outFlags &= ~flag;
155a753f4c6cb8558795e673df1896532cd148781e2Chris Craik                return true;
156a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            }
157a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            return false;
158a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        }
159a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    }
160a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
161a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik    /**
162a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik     * Set internal layer state based on whether this layer
163a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik     *
164a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik     * Additionally, returns true if child RenderNodes with functors will need to use a layer
165a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik     * to support clipping.
166a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik     */
167a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik    bool prepareForFunctorPresence(bool willHaveFunctor, bool ancestorDictatesFunctorsNeedLayer) {
168a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        // parent may have already dictated that a descendant layer is needed
169a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        bool functorsNeedLayer = ancestorDictatesFunctorsNeedLayer
170a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
171a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                // Round rect clipping forces layer for functors
172b60d3e7856f74c72898b2cba553db0d2e2d1365dChris Craik                || CC_UNLIKELY(getOutline().willRoundRectClip())
173a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                || CC_UNLIKELY(getRevealClip().willClip())
174a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
175a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                // Complex matrices forces layer, due to stencil clipping
176a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                || CC_UNLIKELY(getTransformMatrix() && !getTransformMatrix()->isScaleTranslate())
177a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                || CC_UNLIKELY(getAnimationMatrix() && !getAnimationMatrix()->isScaleTranslate())
178a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                || CC_UNLIKELY(getStaticMatrix() && !getStaticMatrix()->isScaleTranslate());
179a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
180a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        mComputedFields.mNeedLayerForFunctors = (willHaveFunctor && functorsNeedLayer);
181a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
182a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        // If on a layer, will have consumed the need for isolating functors from stencil.
183a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        // Thus, it's safe to reset the flag until some descendent sets it.
184a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        return CC_LIKELY(effectiveLayerType() == LayerType::None) && functorsNeedLayer;
185a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik    }
186a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
187d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    RenderProperties& operator=(const RenderProperties& other);
188d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
18979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setClipToBounds(bool clipToBounds) {
190a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        return setFlag(CLIP_TO_BOUNDS, clipToBounds, &mPrimitiveFields.mClippingFlags);
191a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    }
192a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
193a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    bool setClipBounds(const Rect& clipBounds) {
194a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        bool ret = setFlag(CLIP_TO_CLIP_BOUNDS, true, &mPrimitiveFields.mClippingFlags);
195a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        return RP_SET(mPrimitiveFields.mClipBounds, clipBounds) || ret;
196a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    }
197a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
198a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    bool setClipBoundsEmpty() {
199a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        return setFlag(CLIP_TO_CLIP_BOUNDS, false, &mPrimitiveFields.mClippingFlags);
200acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
201acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
20279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setProjectBackwards(bool shouldProject) {
20379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET(mPrimitiveFields.mProjectBackwards, shouldProject);
204acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
205acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
2066fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    bool setProjectionReceiver(bool shouldReceive) {
2076fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        return RP_SET(mPrimitiveFields.mProjectionReceiver, shouldReceive);
208acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
209acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
210d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    bool isProjectionReceiver() const {
211d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mProjectionReceiver;
212acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
213acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
21479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setStaticMatrix(const SkMatrix* matrix) {
215acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        delete mStaticMatrix;
216d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        if (matrix) {
217d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mStaticMatrix = new SkMatrix(*matrix);
218d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        } else {
219e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik            mStaticMatrix = nullptr;
220d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        }
22179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return true;
222acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
223acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
224acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    // Can return NULL
225d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    const SkMatrix* getStaticMatrix() const {
226acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        return mStaticMatrix;
227acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
228acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
22979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setAnimationMatrix(const SkMatrix* matrix) {
230acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        delete mAnimationMatrix;
231acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        if (matrix) {
232acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            mAnimationMatrix = new SkMatrix(*matrix);
233acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        } else {
234e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik            mAnimationMatrix = nullptr;
235acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
23679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return true;
237acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
238acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
23979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setAlpha(float alpha) {
2403b52c03f5035b833d365215420739aa840ac5080John Reck        alpha = MathUtils::clampAlpha(alpha);
24179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET(mPrimitiveFields.mAlpha, alpha);
242acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
243acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
244acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getAlpha() const {
245d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mAlpha;
246acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
247acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
24879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setHasOverlappingRendering(bool hasOverlappingRendering) {
24979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET(mPrimitiveFields.mHasOverlappingRendering, hasOverlappingRendering);
250acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
251acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
252acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    bool hasOverlappingRendering() const {
253d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mHasOverlappingRendering;
254acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
255acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
25679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setElevation(float elevation) {
25779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET(mPrimitiveFields.mElevation, elevation);
25879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        // Don't dirty matrix/pivot, since they don't respect Z
259cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik    }
260cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik
261cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik    float getElevation() const {
262cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik        return mPrimitiveFields.mElevation;
263cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik    }
264cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik
26579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setTranslationX(float translationX) {
26679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationX, translationX);
267acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
268acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
269acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getTranslationX() const {
270d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mTranslationX;
271acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
272acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
27379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setTranslationY(float translationY) {
27479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationY, translationY);
275acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
276acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
277acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getTranslationY() const {
278d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mTranslationY;
279acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
280acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
28179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setTranslationZ(float translationZ) {
28279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET(mPrimitiveFields.mTranslationZ, translationZ);
28379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        // mMatrixOrPivotDirty not set, since matrix doesn't respect Z
284acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
285acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
286acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getTranslationZ() const {
287d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mTranslationZ;
288acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
289acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
290e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    // Animation helper
29179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setX(float value) {
29279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return setTranslationX(value - getLeft());
293e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
294e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
295e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    // Animation helper
296e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    float getX() const {
297e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        return getLeft() + getTranslationX();
298e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
299e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
300e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    // Animation helper
30179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setY(float value) {
30279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return setTranslationY(value - getTop());
303e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
304e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
305e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    // Animation helper
306e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    float getY() const {
307e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        return getTop() + getTranslationY();
308e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
309e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
310e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    // Animation helper
31179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setZ(float value) {
31279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return setTranslationZ(value - getElevation());
313e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
314e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
315cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik    float getZ() const {
316cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik        return getElevation() + getTranslationZ();
317cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik    }
318cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik
31979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setRotation(float rotation) {
32079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mRotation, rotation);
321acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
322acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
323acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getRotation() const {
324d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mRotation;
325acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
326acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
32779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setRotationX(float rotationX) {
32879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationX, rotationX);
329acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
330acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
331acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getRotationX() const {
332d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mRotationX;
333acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
334acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
33579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setRotationY(float rotationY) {
33679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationY, rotationY);
337acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
338acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
339acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getRotationY() const {
340d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mRotationY;
341acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
342acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
34379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setScaleX(float scaleX) {
34479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleX, scaleX);
345acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
346acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
347acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getScaleX() const {
348d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mScaleX;
349acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
350acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
35179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setScaleY(float scaleY) {
35279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleY, scaleY);
353acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
354acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
355acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getScaleY() const {
356d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mScaleY;
357acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
358acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
35979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setPivotX(float pivotX) {
36079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mPivotX, pivotX)
36179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck                || !mPrimitiveFields.mPivotExplicitlySet) {
36279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            mPrimitiveFields.mMatrixOrPivotDirty = true;
36379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            mPrimitiveFields.mPivotExplicitlySet = true;
36479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
36579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        }
36679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
367acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
368acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
369d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    /* Note that getPivotX and getPivotY are adjusted by updateMatrix(),
37079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck     * so the value returned may be stale if the RenderProperties has been
37179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck     * modified since the last call to updateMatrix()
372d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck     */
373d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    float getPivotX() const {
374d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mPivotX;
375d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
376acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
37779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setPivotY(float pivotY) {
37879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mPivotY, pivotY)
37979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck                || !mPrimitiveFields.mPivotExplicitlySet) {
38079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            mPrimitiveFields.mMatrixOrPivotDirty = true;
38179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            mPrimitiveFields.mPivotExplicitlySet = true;
38279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
38379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        }
38479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
385acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
386acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
387d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    float getPivotY() const {
388d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mPivotY;
389d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
390acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
39149e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik    bool isPivotExplicitlySet() const {
39249e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        return mPrimitiveFields.mPivotExplicitlySet;
39349e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik    }
39449e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik
39579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setCameraDistance(float distance) {
39649e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        if (distance != getCameraDistance()) {
397f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            mPrimitiveFields.mMatrixOrPivotDirty = true;
39849e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik            mComputedFields.mTransformCamera.setCameraLocation(0, 0, distance);
39979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
400acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
40179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
402acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
403acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
404acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getCameraDistance() const {
40549e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        // TODO: update getCameraLocationZ() to be const
40649e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        return const_cast<Sk3DView*>(&mComputedFields.mTransformCamera)->getCameraLocationZ();
407acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
408acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
40979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setLeft(int left) {
41079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mLeft, left)) {
411d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
412f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            if (!mPrimitiveFields.mPivotExplicitlySet) {
413f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck                mPrimitiveFields.mMatrixOrPivotDirty = true;
414acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            }
41579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
416acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
41779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
418acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
419acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
420e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    int getLeft() const {
421d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mLeft;
422acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
423acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
42479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setTop(int top) {
42579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mTop, top)) {
426d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
427f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            if (!mPrimitiveFields.mPivotExplicitlySet) {
428f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck                mPrimitiveFields.mMatrixOrPivotDirty = true;
429acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            }
43079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
431acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
43279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
433acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
434acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
435e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    int getTop() const {
436d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mTop;
437acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
438acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
43979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setRight(int right) {
44079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mRight, right)) {
441d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
442f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            if (!mPrimitiveFields.mPivotExplicitlySet) {
443f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck                mPrimitiveFields.mMatrixOrPivotDirty = true;
444acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            }
44579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
446acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
44779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
448acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
449acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
450e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    int getRight() const {
451d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mRight;
452acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
453acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
45479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setBottom(int bottom) {
45579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mBottom, bottom)) {
456d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
457f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            if (!mPrimitiveFields.mPivotExplicitlySet) {
458f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck                mPrimitiveFields.mMatrixOrPivotDirty = true;
459acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            }
46079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
461acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
46279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
463acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
464acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
465e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    int getBottom() const {
466d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mBottom;
467acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
468acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
46979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setLeftTop(int left, int top) {
47079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        bool leftResult = setLeft(left);
47179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        bool topResult = setTop(top);
47279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return leftResult || topResult;
473acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
474acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
47579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setLeftTopRightBottom(int left, int top, int right, int bottom) {
476cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik        if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop
477cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik                || right != mPrimitiveFields.mRight || bottom != mPrimitiveFields.mBottom) {
478d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mLeft = left;
479d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mTop = top;
480d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mRight = right;
481d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mBottom = bottom;
482d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
483d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
484f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            if (!mPrimitiveFields.mPivotExplicitlySet) {
485f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck                mPrimitiveFields.mMatrixOrPivotDirty = true;
486acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            }
48779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
488acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
48979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
490acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
491acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
492a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    bool offsetLeftRight(int offset) {
493acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        if (offset != 0) {
494d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mLeft += offset;
495d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mRight += offset;
49679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
497acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
49879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
499acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
500acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
501a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    bool offsetTopBottom(int offset) {
502acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        if (offset != 0) {
503d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mTop += offset;
504d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mBottom += offset;
50579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
506acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
50779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
508acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
509acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
510b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    int getWidth() const {
511d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mWidth;
512acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
513acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
514b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    int getHeight() const {
515d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mHeight;
516d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
517d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
518d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    const SkMatrix* getAnimationMatrix() const {
519d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mAnimationMatrix;
520d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
521d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
522f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck    bool hasTransformMatrix() const {
523f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck        return getTransformMatrix() && !getTransformMatrix()->isIdentity();
524f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck    }
525f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck
526f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck    // May only call this if hasTransformMatrix() is true
527f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck    bool isTransformTranslateOnly() const {
528f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck        return getTransformMatrix()->getType() == SkMatrix::kTranslate_Mask;
529d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
530d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
53149e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik    const SkMatrix* getTransformMatrix() const {
532f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck        LOG_ALWAYS_FATAL_IF(mPrimitiveFields.mMatrixOrPivotDirty, "Cannot get a dirty matrix!");
533d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mComputedFields.mTransformMatrix;
534d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
535d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
536a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    int getClippingFlags() const {
537a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        return mPrimitiveFields.mClippingFlags;
538a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    }
539a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
540d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    bool getClipToBounds() const {
541a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        return mPrimitiveFields.mClippingFlags & CLIP_TO_BOUNDS;
542a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    }
543a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
544e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    const Rect& getClipBounds() const {
545e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        return mPrimitiveFields.mClipBounds;
546e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    }
547e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck
548a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    void getClippingRectForFlags(uint32_t flags, Rect* outRect) const {
549a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        if (flags & CLIP_TO_BOUNDS) {
550a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            outRect->set(0, 0, getWidth(), getHeight());
551a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            if (flags & CLIP_TO_CLIP_BOUNDS) {
552ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik                outRect->doIntersect(mPrimitiveFields.mClipBounds);
553a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            }
554a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        } else {
555a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            outRect->set(mPrimitiveFields.mClipBounds);
556a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        }
557d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
558d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
559d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    bool getHasOverlappingRendering() const {
560d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mHasOverlappingRendering;
561d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
562d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
563d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    const Outline& getOutline() const {
564d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mOutline;
565d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
566d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
5678c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik    const RevealClip& getRevealClip() const {
5688c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik        return mPrimitiveFields.mRevealClip;
5698c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik    }
5708c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik
571d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    bool getProjectBackwards() const {
572d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mProjectBackwards;
573d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
574d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
575d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    void debugOutputProperties(const int level) const;
576d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
57725fbb3fa1138675379102a44405852555cefccbdJohn Reck    void updateMatrix();
578d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
579d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    Outline& mutableOutline() {
580d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mOutline;
581b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    }
582b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
5838c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik    RevealClip& mutableRevealClip() {
5848c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik        return mPrimitiveFields.mRevealClip;
5858c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik    }
5868c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik
58725fbb3fa1138675379102a44405852555cefccbdJohn Reck    const LayerProperties& layerProperties() const {
58825fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mLayerProperties;
58925fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
59025fbb3fa1138675379102a44405852555cefccbdJohn Reck
59125fbb3fa1138675379102a44405852555cefccbdJohn Reck    LayerProperties& mutateLayerProperties() {
59225fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mLayerProperties;
59325fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
59425fbb3fa1138675379102a44405852555cefccbdJohn Reck
595293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    // Returns true if damage calculations should be clipped to bounds
596293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    // TODO: Figure out something better for getZ(), as children should still be
597293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    // clipped to this RP's bounds. But as we will damage -INT_MAX to INT_MAX
598293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    // for this RP's getZ() anyway, this can be optimized when we have a
599293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    // Z damage estimate instead of INT_MAX
600293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    bool getClipDamageToBounds() const {
601293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck        return getClipToBounds() && (getZ() <= 0 || getOutline().isEmpty());
602293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    }
603293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck
6045c75c52e048a01c23b18f4e31ae624b5fe43e23cChris Craik    bool hasShadow() const {
605b5a5435a77bae40b55053ccde93b1ed45d0e8329Chris Craik        return getZ() > 0.0f
606e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik                && getOutline().getPath() != nullptr
6079fa364dc72613f4301b0783f0547fe6b01abac39Chris Craik                && getOutline().getAlpha() != 0.0f;
6085c75c52e048a01c23b18f4e31ae624b5fe43e23cChris Craik    }
6095c75c52e048a01c23b18f4e31ae624b5fe43e23cChris Craik
6101a0808e64c170fa7b620b858fa5875f6f08a2b54Chris Craik    bool promotedToLayer() const {
6114e9d9b2a590105035c29f12ecf0689333e6b55e7Chris Craik        const int maxTextureSize = Caches::getInstance().maxTextureSize;
6121a0808e64c170fa7b620b858fa5875f6f08a2b54Chris Craik        return mLayerProperties.mType == LayerType::None
6134e9d9b2a590105035c29f12ecf0689333e6b55e7Chris Craik                && mPrimitiveFields.mWidth <= maxTextureSize
614a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                && mPrimitiveFields.mHeight <= maxTextureSize
615a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                && (mComputedFields.mNeedLayerForFunctors
616a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                        || (!MathUtils::isZero(mPrimitiveFields.mAlpha)
617a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                                && mPrimitiveFields.mAlpha < 1
618a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                                && mPrimitiveFields.mHasOverlappingRendering));
6191a0808e64c170fa7b620b858fa5875f6f08a2b54Chris Craik    }
6201a0808e64c170fa7b620b858fa5875f6f08a2b54Chris Craik
6211a0808e64c170fa7b620b858fa5875f6f08a2b54Chris Craik    LayerType effectiveLayerType() const {
622a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        return CC_UNLIKELY(promotedToLayer()) ? LayerType::RenderLayer : mLayerProperties.mType;
623856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik    }
624856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik
625acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckprivate:
626acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    // Rendering properties
627d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    struct PrimitiveFields {
628e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        int mLeft = 0, mTop = 0, mRight = 0, mBottom = 0;
629e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        int mWidth = 0, mHeight = 0;
630e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        int mClippingFlags = CLIP_TO_BOUNDS;
631e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mAlpha = 1;
632e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mTranslationX = 0, mTranslationY = 0, mTranslationZ = 0;
633e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mElevation = 0;
634e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mRotation = 0, mRotationX = 0, mRotationY = 0;
635e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mScaleX = 1, mScaleY = 1;
636e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mPivotX = 0, mPivotY = 0;
637e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        bool mHasOverlappingRendering = false;
638e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        bool mPivotExplicitlySet = false;
639e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        bool mMatrixOrPivotDirty = false;
640e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        bool mProjectBackwards = false;
641e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        bool mProjectionReceiver = false;
642e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        Rect mClipBounds;
643d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        Outline mOutline;
6448c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik        RevealClip mRevealClip;
645d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    } mPrimitiveFields;
646d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
647acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    SkMatrix* mStaticMatrix;
648acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    SkMatrix* mAnimationMatrix;
64925fbb3fa1138675379102a44405852555cefccbdJohn Reck    LayerProperties mLayerProperties;
650acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
651d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    /**
652d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck     * These fields are all generated from other properties and are not set directly.
653d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck     */
654d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    struct ComputedFields {
655d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        ComputedFields();
656d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        ~ComputedFields();
657d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
658d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        /**
659d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck         * Stores the total transformation of the DisplayList based upon its scalar
660d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck         * translate/rotate/scale properties.
661d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck         *
66249e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik         * In the common translation-only case, the matrix isn't necessarily allocated,
66349e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik         * and the mTranslation properties are used directly.
664d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck         */
66549e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        SkMatrix* mTransformMatrix;
66649e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik
66749e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        Sk3DView mTransformCamera;
668a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
669a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        // Force layer on for functors to enable render features they don't yet support (clipping)
670a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        bool mNeedLayerForFunctors = false;
671d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    } mComputedFields;
672acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck};
673acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
674acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck} /* namespace uirenderer */
675acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck} /* namespace android */
676acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
677b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik#endif /* RENDERNODEPROPERTIES_H */
678