RenderProperties.h revision 5e00c7ce063116c11315639f0035aca8ad73e8cc
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 */
165e00c7ce063116c11315639f0035aca8ad73e8ccChris Craik
175e00c7ce063116c11315639f0035aca8ad73e8ccChris Craik#pragma once
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"
255e00c7ce063116c11315639f0035aca8ad73e8ccChris Craik#include "utils/PaintUtils.h"
26acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
27acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck#include <SkCamera.h>
28acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck#include <SkMatrix.h>
298c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik#include <SkRegion.h>
302dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson#include <SkXfermode.h>
31b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
3276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik#include <algorithm>
3376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik#include <stddef.h>
3476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik#include <vector>
3576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik#include <cutils/compiler.h>
3676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik#include <androidfw/ResourceTypes.h>
3776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik#include <utils/Log.h>
38acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
39acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckclass SkBitmap;
4025fbb3fa1138675379102a44405852555cefccbdJohn Reckclass SkColorFilter;
41acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckclass SkPaint;
42acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
43acb6f07623b7df3d4179f70ae03ade574616ffa6John Recknamespace android {
44acb6f07623b7df3d4179f70ae03ade574616ffa6John Recknamespace uirenderer {
45acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
46acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckclass Matrix4;
47acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckclass RenderNode;
4825fbb3fa1138675379102a44405852555cefccbdJohn Reckclass RenderProperties;
49acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
5079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck// The __VA_ARGS__ will be executed if a & b are not equal
51cef190de850f163dd4b95d667a8d46d46e860363Chih-Hung Hsieh#define RP_SET(a, b, ...) ((a) != (b) ? ((a) = (b), ##__VA_ARGS__, true) : false)
5279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck#define RP_SET_AND_DIRTY(a, b) RP_SET(a, b, mPrimitiveFields.mMatrixOrPivotDirty = true)
5379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck
5425fbb3fa1138675379102a44405852555cefccbdJohn Reck// Keep in sync with View.java:LAYER_TYPE_*
55182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craikenum class LayerType {
56182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    None = 0,
5725fbb3fa1138675379102a44405852555cefccbdJohn Reck    // Although we cannot build the software layer directly (must be done at
5825fbb3fa1138675379102a44405852555cefccbdJohn Reck    // record time), this information is used when applying alpha.
59182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    Software = 1,
60182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    RenderLayer = 2,
6125fbb3fa1138675379102a44405852555cefccbdJohn Reck    // TODO: LayerTypeSurfaceTexture? Maybe?
6225fbb3fa1138675379102a44405852555cefccbdJohn Reck};
6325fbb3fa1138675379102a44405852555cefccbdJohn Reck
64a753f4c6cb8558795e673df1896532cd148781e2Chris Craikenum ClippingFlags {
65a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    CLIP_TO_BOUNDS =      0x1 << 0,
66a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    CLIP_TO_CLIP_BOUNDS = 0x1 << 1,
67a753f4c6cb8558795e673df1896532cd148781e2Chris Craik};
68a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
6925fbb3fa1138675379102a44405852555cefccbdJohn Reckclass ANDROID_API LayerProperties {
7025fbb3fa1138675379102a44405852555cefccbdJohn Reckpublic:
7125fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setType(LayerType type) {
7225fbb3fa1138675379102a44405852555cefccbdJohn Reck        if (RP_SET(mType, type)) {
7325fbb3fa1138675379102a44405852555cefccbdJohn Reck            reset();
7425fbb3fa1138675379102a44405852555cefccbdJohn Reck            return true;
7525fbb3fa1138675379102a44405852555cefccbdJohn Reck        }
7625fbb3fa1138675379102a44405852555cefccbdJohn Reck        return false;
7725fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
7825fbb3fa1138675379102a44405852555cefccbdJohn Reck
7925fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setOpaque(bool opaque) {
8025fbb3fa1138675379102a44405852555cefccbdJohn Reck        return RP_SET(mOpaque, opaque);
8125fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
8225fbb3fa1138675379102a44405852555cefccbdJohn Reck
8325fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool opaque() const {
8425fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mOpaque;
8525fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
8625fbb3fa1138675379102a44405852555cefccbdJohn Reck
8725fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setAlpha(uint8_t alpha) {
8825fbb3fa1138675379102a44405852555cefccbdJohn Reck        return RP_SET(mAlpha, alpha);
8925fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
9025fbb3fa1138675379102a44405852555cefccbdJohn Reck
9125fbb3fa1138675379102a44405852555cefccbdJohn Reck    uint8_t alpha() const {
9225fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mAlpha;
9325fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
9425fbb3fa1138675379102a44405852555cefccbdJohn Reck
9525fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setXferMode(SkXfermode::Mode mode) {
9625fbb3fa1138675379102a44405852555cefccbdJohn Reck        return RP_SET(mMode, mode);
9725fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
9825fbb3fa1138675379102a44405852555cefccbdJohn Reck
9925fbb3fa1138675379102a44405852555cefccbdJohn Reck    SkXfermode::Mode xferMode() const {
10025fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mMode;
10125fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
10225fbb3fa1138675379102a44405852555cefccbdJohn Reck
10325fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setColorFilter(SkColorFilter* filter);
10425fbb3fa1138675379102a44405852555cefccbdJohn Reck
10525fbb3fa1138675379102a44405852555cefccbdJohn Reck    SkColorFilter* colorFilter() const {
10625fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mColorFilter;
10725fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
10825fbb3fa1138675379102a44405852555cefccbdJohn Reck
10925fbb3fa1138675379102a44405852555cefccbdJohn Reck    // Sets alpha, xfermode, and colorfilter from an SkPaint
11025fbb3fa1138675379102a44405852555cefccbdJohn Reck    // paint may be NULL, in which case defaults will be set
11125fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setFromPaint(const SkPaint* paint);
11225fbb3fa1138675379102a44405852555cefccbdJohn Reck
11325fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool needsBlending() const {
11425fbb3fa1138675379102a44405852555cefccbdJohn Reck        return !opaque() || alpha() < 255;
11525fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
11625fbb3fa1138675379102a44405852555cefccbdJohn Reck
11725fbb3fa1138675379102a44405852555cefccbdJohn Reck    LayerProperties& operator=(const LayerProperties& other);
11825fbb3fa1138675379102a44405852555cefccbdJohn Reck
11925fbb3fa1138675379102a44405852555cefccbdJohn Reckprivate:
12025fbb3fa1138675379102a44405852555cefccbdJohn Reck    LayerProperties();
12125fbb3fa1138675379102a44405852555cefccbdJohn Reck    ~LayerProperties();
12225fbb3fa1138675379102a44405852555cefccbdJohn Reck    void reset();
12325fbb3fa1138675379102a44405852555cefccbdJohn Reck
124856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik    // Private since external users should go through properties().effectiveLayerType()
125856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik    LayerType type() const {
126856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik        return mType;
127856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik    }
128856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik
12925fbb3fa1138675379102a44405852555cefccbdJohn Reck    friend class RenderProperties;
13025fbb3fa1138675379102a44405852555cefccbdJohn Reck
131182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    LayerType mType = LayerType::None;
13225fbb3fa1138675379102a44405852555cefccbdJohn Reck    // Whether or not that Layer's content is opaque, doesn't include alpha
13325fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool mOpaque;
13425fbb3fa1138675379102a44405852555cefccbdJohn Reck    uint8_t mAlpha;
13525fbb3fa1138675379102a44405852555cefccbdJohn Reck    SkXfermode::Mode mMode;
136182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    SkColorFilter* mColorFilter = nullptr;
13725fbb3fa1138675379102a44405852555cefccbdJohn Reck};
13825fbb3fa1138675379102a44405852555cefccbdJohn Reck
139acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck/*
140acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * Data structure that holds the properties for a RenderNode
141acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck */
14225fbb3fa1138675379102a44405852555cefccbdJohn Reckclass ANDROID_API RenderProperties {
143acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckpublic:
144acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    RenderProperties();
145acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    virtual ~RenderProperties();
146acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
147a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    static bool setFlag(int flag, bool newValue, int* outFlags) {
148a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        if (newValue) {
149a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            if (!(flag & *outFlags)) {
150a753f4c6cb8558795e673df1896532cd148781e2Chris Craik                *outFlags |= flag;
151a753f4c6cb8558795e673df1896532cd148781e2Chris Craik                return true;
152a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            }
153a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            return false;
154a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        } else {
155a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            if (flag & *outFlags) {
156a753f4c6cb8558795e673df1896532cd148781e2Chris Craik                *outFlags &= ~flag;
157a753f4c6cb8558795e673df1896532cd148781e2Chris Craik                return true;
158a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            }
159a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            return false;
160a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        }
161a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    }
162a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
163a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik    /**
164a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik     * Set internal layer state based on whether this layer
165a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik     *
166a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik     * Additionally, returns true if child RenderNodes with functors will need to use a layer
167a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik     * to support clipping.
168a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik     */
169a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik    bool prepareForFunctorPresence(bool willHaveFunctor, bool ancestorDictatesFunctorsNeedLayer) {
170a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        // parent may have already dictated that a descendant layer is needed
171a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        bool functorsNeedLayer = ancestorDictatesFunctorsNeedLayer
172a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
173a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                // Round rect clipping forces layer for functors
174b60d3e7856f74c72898b2cba553db0d2e2d1365dChris Craik                || CC_UNLIKELY(getOutline().willRoundRectClip())
175a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                || CC_UNLIKELY(getRevealClip().willClip())
176a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
177a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                // Complex matrices forces layer, due to stencil clipping
178a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                || CC_UNLIKELY(getTransformMatrix() && !getTransformMatrix()->isScaleTranslate())
179a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                || CC_UNLIKELY(getAnimationMatrix() && !getAnimationMatrix()->isScaleTranslate())
180a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                || CC_UNLIKELY(getStaticMatrix() && !getStaticMatrix()->isScaleTranslate());
181a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
182a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        mComputedFields.mNeedLayerForFunctors = (willHaveFunctor && functorsNeedLayer);
183a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
184a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        // If on a layer, will have consumed the need for isolating functors from stencil.
185a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        // Thus, it's safe to reset the flag until some descendent sets it.
186a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        return CC_LIKELY(effectiveLayerType() == LayerType::None) && functorsNeedLayer;
187a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik    }
188a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
189d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    RenderProperties& operator=(const RenderProperties& other);
190d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
19179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setClipToBounds(bool clipToBounds) {
192a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        return setFlag(CLIP_TO_BOUNDS, clipToBounds, &mPrimitiveFields.mClippingFlags);
193a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    }
194a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
195a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    bool setClipBounds(const Rect& clipBounds) {
196a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        bool ret = setFlag(CLIP_TO_CLIP_BOUNDS, true, &mPrimitiveFields.mClippingFlags);
197a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        return RP_SET(mPrimitiveFields.mClipBounds, clipBounds) || ret;
198a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    }
199a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
200a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    bool setClipBoundsEmpty() {
201a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        return setFlag(CLIP_TO_CLIP_BOUNDS, false, &mPrimitiveFields.mClippingFlags);
202acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
203acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
20479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setProjectBackwards(bool shouldProject) {
20579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET(mPrimitiveFields.mProjectBackwards, shouldProject);
206acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
207acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
2086fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    bool setProjectionReceiver(bool shouldReceive) {
2096fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        return RP_SET(mPrimitiveFields.mProjectionReceiver, shouldReceive);
210acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
211acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
212d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    bool isProjectionReceiver() const {
213d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mProjectionReceiver;
214acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
215acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
21679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setStaticMatrix(const SkMatrix* matrix) {
217acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        delete mStaticMatrix;
218d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        if (matrix) {
219d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mStaticMatrix = new SkMatrix(*matrix);
220d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        } else {
221e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik            mStaticMatrix = nullptr;
222d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        }
22379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return true;
224acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
225acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
226acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    // Can return NULL
227d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    const SkMatrix* getStaticMatrix() const {
228acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        return mStaticMatrix;
229acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
230acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
23179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setAnimationMatrix(const SkMatrix* matrix) {
232acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        delete mAnimationMatrix;
233acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        if (matrix) {
234acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            mAnimationMatrix = new SkMatrix(*matrix);
235acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        } else {
236e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik            mAnimationMatrix = nullptr;
237acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
23879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return true;
239acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
240acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
24179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setAlpha(float alpha) {
2423b52c03f5035b833d365215420739aa840ac5080John Reck        alpha = MathUtils::clampAlpha(alpha);
24379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET(mPrimitiveFields.mAlpha, alpha);
244acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
245acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
246acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getAlpha() const {
247d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mAlpha;
248acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
249acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
25079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setHasOverlappingRendering(bool hasOverlappingRendering) {
25179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET(mPrimitiveFields.mHasOverlappingRendering, hasOverlappingRendering);
252acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
253acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
254acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    bool hasOverlappingRendering() const {
255d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mHasOverlappingRendering;
256acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
257acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
25879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setElevation(float elevation) {
25979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET(mPrimitiveFields.mElevation, elevation);
26079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        // Don't dirty matrix/pivot, since they don't respect Z
261cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik    }
262cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik
263cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik    float getElevation() const {
264cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik        return mPrimitiveFields.mElevation;
265cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik    }
266cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik
26779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setTranslationX(float translationX) {
26879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationX, translationX);
269acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
270acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
271acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getTranslationX() const {
272d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mTranslationX;
273acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
274acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
27579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setTranslationY(float translationY) {
27679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationY, translationY);
277acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
278acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
279acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getTranslationY() const {
280d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mTranslationY;
281acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
282acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
28379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setTranslationZ(float translationZ) {
28479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET(mPrimitiveFields.mTranslationZ, translationZ);
28579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        // mMatrixOrPivotDirty not set, since matrix doesn't respect Z
286acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
287acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
288acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getTranslationZ() const {
289d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mTranslationZ;
290acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
291acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
292e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    // Animation helper
29379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setX(float value) {
29479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return setTranslationX(value - getLeft());
295e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
296e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
297e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    // Animation helper
298e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    float getX() const {
299e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        return getLeft() + getTranslationX();
300e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
301e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
302e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    // Animation helper
30379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setY(float value) {
30479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return setTranslationY(value - getTop());
305e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
306e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
307e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    // Animation helper
308e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    float getY() const {
309e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        return getTop() + getTranslationY();
310e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
311e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
312e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    // Animation helper
31379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setZ(float value) {
31479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return setTranslationZ(value - getElevation());
315e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
316e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
317cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik    float getZ() const {
318cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik        return getElevation() + getTranslationZ();
319cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik    }
320cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik
32179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setRotation(float rotation) {
32279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mRotation, rotation);
323acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
324acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
325acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getRotation() const {
326d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mRotation;
327acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
328acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
32979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setRotationX(float rotationX) {
33079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationX, rotationX);
331acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
332acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
333acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getRotationX() const {
334d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mRotationX;
335acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
336acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
33779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setRotationY(float rotationY) {
33879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationY, rotationY);
339acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
340acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
341acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getRotationY() const {
342d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mRotationY;
343acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
344acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
34579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setScaleX(float scaleX) {
34679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleX, scaleX);
347acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
348acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
349acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getScaleX() const {
350d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mScaleX;
351acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
352acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
35379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setScaleY(float scaleY) {
35479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleY, scaleY);
355acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
356acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
357acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getScaleY() const {
358d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mScaleY;
359acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
360acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
36179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setPivotX(float pivotX) {
36279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mPivotX, pivotX)
36379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck                || !mPrimitiveFields.mPivotExplicitlySet) {
36479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            mPrimitiveFields.mMatrixOrPivotDirty = true;
36579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            mPrimitiveFields.mPivotExplicitlySet = true;
36679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
36779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        }
36879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
369acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
370acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
371d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    /* Note that getPivotX and getPivotY are adjusted by updateMatrix(),
37279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck     * so the value returned may be stale if the RenderProperties has been
37379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck     * modified since the last call to updateMatrix()
374d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck     */
375d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    float getPivotX() const {
376d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mPivotX;
377d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
378acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
37979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setPivotY(float pivotY) {
38079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mPivotY, pivotY)
38179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck                || !mPrimitiveFields.mPivotExplicitlySet) {
38279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            mPrimitiveFields.mMatrixOrPivotDirty = true;
38379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            mPrimitiveFields.mPivotExplicitlySet = true;
38479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
38579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        }
38679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
387acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
388acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
389d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    float getPivotY() const {
390d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mPivotY;
391d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
392acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
39349e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik    bool isPivotExplicitlySet() const {
39449e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        return mPrimitiveFields.mPivotExplicitlySet;
39549e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik    }
39649e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik
39779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setCameraDistance(float distance) {
39849e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        if (distance != getCameraDistance()) {
399f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            mPrimitiveFields.mMatrixOrPivotDirty = true;
40049e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik            mComputedFields.mTransformCamera.setCameraLocation(0, 0, distance);
40179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
402acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
40379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
404acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
405acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
406acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getCameraDistance() const {
40749e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        // TODO: update getCameraLocationZ() to be const
40849e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        return const_cast<Sk3DView*>(&mComputedFields.mTransformCamera)->getCameraLocationZ();
409acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
410acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
41179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setLeft(int left) {
41279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mLeft, left)) {
413d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
414f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            if (!mPrimitiveFields.mPivotExplicitlySet) {
415f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck                mPrimitiveFields.mMatrixOrPivotDirty = true;
416acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            }
41779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
418acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
41979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
420acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
421acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
422e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    int getLeft() const {
423d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mLeft;
424acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
425acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
42679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setTop(int top) {
42779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mTop, top)) {
428d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
429f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            if (!mPrimitiveFields.mPivotExplicitlySet) {
430f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck                mPrimitiveFields.mMatrixOrPivotDirty = true;
431acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            }
43279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
433acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
43479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
435acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
436acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
437e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    int getTop() const {
438d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mTop;
439acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
440acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
44179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setRight(int right) {
44279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mRight, right)) {
443d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
444f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            if (!mPrimitiveFields.mPivotExplicitlySet) {
445f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck                mPrimitiveFields.mMatrixOrPivotDirty = true;
446acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            }
44779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
448acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
44979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
450acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
451acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
452e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    int getRight() const {
453d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mRight;
454acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
455acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
45679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setBottom(int bottom) {
45779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mBottom, bottom)) {
458d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
459f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            if (!mPrimitiveFields.mPivotExplicitlySet) {
460f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck                mPrimitiveFields.mMatrixOrPivotDirty = true;
461acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            }
46279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
463acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
46479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
465acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
466acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
467e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    int getBottom() const {
468d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mBottom;
469acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
470acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
47179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setLeftTop(int left, int top) {
47279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        bool leftResult = setLeft(left);
47379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        bool topResult = setTop(top);
47479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return leftResult || topResult;
475acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
476acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
47779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setLeftTopRightBottom(int left, int top, int right, int bottom) {
478cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik        if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop
479cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik                || right != mPrimitiveFields.mRight || bottom != mPrimitiveFields.mBottom) {
480d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mLeft = left;
481d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mTop = top;
482d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mRight = right;
483d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mBottom = bottom;
484d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
485d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
486f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            if (!mPrimitiveFields.mPivotExplicitlySet) {
487f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck                mPrimitiveFields.mMatrixOrPivotDirty = true;
488acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            }
48979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
490acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
49179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
492acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
493acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
494a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    bool offsetLeftRight(int offset) {
495acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        if (offset != 0) {
496d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mLeft += offset;
497d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mRight += offset;
49879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
499acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
50079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
501acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
502acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
503a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    bool offsetTopBottom(int offset) {
504acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        if (offset != 0) {
505d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mTop += offset;
506d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mBottom += offset;
50779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
508acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
50979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
510acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
511acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
512b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    int getWidth() const {
513d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mWidth;
514acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
515acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
516b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    int getHeight() const {
517d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mHeight;
518d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
519d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
520d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    const SkMatrix* getAnimationMatrix() const {
521d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mAnimationMatrix;
522d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
523d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
524f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck    bool hasTransformMatrix() const {
525f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck        return getTransformMatrix() && !getTransformMatrix()->isIdentity();
526f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck    }
527f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck
528f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck    // May only call this if hasTransformMatrix() is true
529f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck    bool isTransformTranslateOnly() const {
530f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck        return getTransformMatrix()->getType() == SkMatrix::kTranslate_Mask;
531d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
532d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
53349e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik    const SkMatrix* getTransformMatrix() const {
534f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck        LOG_ALWAYS_FATAL_IF(mPrimitiveFields.mMatrixOrPivotDirty, "Cannot get a dirty matrix!");
535d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mComputedFields.mTransformMatrix;
536d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
537d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
538a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    int getClippingFlags() const {
539a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        return mPrimitiveFields.mClippingFlags;
540a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    }
541a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
542d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    bool getClipToBounds() const {
543a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        return mPrimitiveFields.mClippingFlags & CLIP_TO_BOUNDS;
544a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    }
545a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
546e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    const Rect& getClipBounds() const {
547e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        return mPrimitiveFields.mClipBounds;
548e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    }
549e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck
550a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    void getClippingRectForFlags(uint32_t flags, Rect* outRect) const {
551a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        if (flags & CLIP_TO_BOUNDS) {
552a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            outRect->set(0, 0, getWidth(), getHeight());
553a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            if (flags & CLIP_TO_CLIP_BOUNDS) {
554ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik                outRect->doIntersect(mPrimitiveFields.mClipBounds);
555a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            }
556a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        } else {
557a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            outRect->set(mPrimitiveFields.mClipBounds);
558a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        }
559d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
560d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
561d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    bool getHasOverlappingRendering() const {
562d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mHasOverlappingRendering;
563d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
564d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
565d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    const Outline& getOutline() const {
566d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mOutline;
567d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
568d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
5698c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik    const RevealClip& getRevealClip() const {
5708c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik        return mPrimitiveFields.mRevealClip;
5718c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik    }
5728c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik
573d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    bool getProjectBackwards() const {
574d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mProjectBackwards;
575d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
576d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
577d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    void debugOutputProperties(const int level) const;
578d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
57925fbb3fa1138675379102a44405852555cefccbdJohn Reck    void updateMatrix();
580d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
581d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    Outline& mutableOutline() {
582d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mOutline;
583b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    }
584b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
5858c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik    RevealClip& mutableRevealClip() {
5868c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik        return mPrimitiveFields.mRevealClip;
5878c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik    }
5888c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik
58925fbb3fa1138675379102a44405852555cefccbdJohn Reck    const LayerProperties& layerProperties() const {
59025fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mLayerProperties;
59125fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
59225fbb3fa1138675379102a44405852555cefccbdJohn Reck
59325fbb3fa1138675379102a44405852555cefccbdJohn Reck    LayerProperties& mutateLayerProperties() {
59425fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mLayerProperties;
59525fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
59625fbb3fa1138675379102a44405852555cefccbdJohn Reck
597293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    // Returns true if damage calculations should be clipped to bounds
598293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    // TODO: Figure out something better for getZ(), as children should still be
599293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    // clipped to this RP's bounds. But as we will damage -INT_MAX to INT_MAX
600293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    // for this RP's getZ() anyway, this can be optimized when we have a
601293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    // Z damage estimate instead of INT_MAX
602293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    bool getClipDamageToBounds() const {
603293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck        return getClipToBounds() && (getZ() <= 0 || getOutline().isEmpty());
604293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    }
605293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck
6065c75c52e048a01c23b18f4e31ae624b5fe43e23cChris Craik    bool hasShadow() const {
607b5a5435a77bae40b55053ccde93b1ed45d0e8329Chris Craik        return getZ() > 0.0f
608e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik                && getOutline().getPath() != nullptr
6099fa364dc72613f4301b0783f0547fe6b01abac39Chris Craik                && getOutline().getAlpha() != 0.0f;
6105c75c52e048a01c23b18f4e31ae624b5fe43e23cChris Craik    }
6115c75c52e048a01c23b18f4e31ae624b5fe43e23cChris Craik
6129fded232a9548a304e0145011df8849fba0dcda7Chris Craik    bool fitsOnLayer() const {
61376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        const DeviceInfo* deviceInfo = DeviceInfo::get();
6149fded232a9548a304e0145011df8849fba0dcda7Chris Craik        return mPrimitiveFields.mWidth <= deviceInfo->maxTextureSize()
615d4fe4d3b30aaefcaaae6a6d1b8dc4bf59e034768Chris Craik                        && mPrimitiveFields.mHeight <= deviceInfo->maxTextureSize()
616d4fe4d3b30aaefcaaae6a6d1b8dc4bf59e034768Chris Craik                        && mPrimitiveFields.mWidth > 0
617d4fe4d3b30aaefcaaae6a6d1b8dc4bf59e034768Chris Craik                        && mPrimitiveFields.mHeight > 0;
6189fded232a9548a304e0145011df8849fba0dcda7Chris Craik    }
6199fded232a9548a304e0145011df8849fba0dcda7Chris Craik
6209fded232a9548a304e0145011df8849fba0dcda7Chris Craik    bool promotedToLayer() const {
6211a0808e64c170fa7b620b858fa5875f6f08a2b54Chris Craik        return mLayerProperties.mType == LayerType::None
6229fded232a9548a304e0145011df8849fba0dcda7Chris Craik                && fitsOnLayer()
623a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                && (mComputedFields.mNeedLayerForFunctors
624a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                        || (!MathUtils::isZero(mPrimitiveFields.mAlpha)
625a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                                && mPrimitiveFields.mAlpha < 1
626a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                                && mPrimitiveFields.mHasOverlappingRendering));
6271a0808e64c170fa7b620b858fa5875f6f08a2b54Chris Craik    }
6281a0808e64c170fa7b620b858fa5875f6f08a2b54Chris Craik
6291a0808e64c170fa7b620b858fa5875f6f08a2b54Chris Craik    LayerType effectiveLayerType() const {
630a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        return CC_UNLIKELY(promotedToLayer()) ? LayerType::RenderLayer : mLayerProperties.mType;
631856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik    }
632856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik
633acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckprivate:
634acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    // Rendering properties
635d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    struct PrimitiveFields {
636e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        int mLeft = 0, mTop = 0, mRight = 0, mBottom = 0;
637e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        int mWidth = 0, mHeight = 0;
638e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        int mClippingFlags = CLIP_TO_BOUNDS;
639e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mAlpha = 1;
640e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mTranslationX = 0, mTranslationY = 0, mTranslationZ = 0;
641e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mElevation = 0;
642e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mRotation = 0, mRotationX = 0, mRotationY = 0;
643e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mScaleX = 1, mScaleY = 1;
644e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mPivotX = 0, mPivotY = 0;
645e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        bool mHasOverlappingRendering = false;
646e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        bool mPivotExplicitlySet = false;
647e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        bool mMatrixOrPivotDirty = false;
648e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        bool mProjectBackwards = false;
649e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        bool mProjectionReceiver = false;
650e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        Rect mClipBounds;
651d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        Outline mOutline;
6528c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik        RevealClip mRevealClip;
653d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    } mPrimitiveFields;
654d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
655acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    SkMatrix* mStaticMatrix;
656acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    SkMatrix* mAnimationMatrix;
65725fbb3fa1138675379102a44405852555cefccbdJohn Reck    LayerProperties mLayerProperties;
658acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
659d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    /**
660d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck     * These fields are all generated from other properties and are not set directly.
661d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck     */
662d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    struct ComputedFields {
663d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        ComputedFields();
664d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        ~ComputedFields();
665d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
666d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        /**
667d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck         * Stores the total transformation of the DisplayList based upon its scalar
668d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck         * translate/rotate/scale properties.
669d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck         *
67049e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik         * In the common translation-only case, the matrix isn't necessarily allocated,
67149e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik         * and the mTranslation properties are used directly.
672d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck         */
67349e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        SkMatrix* mTransformMatrix;
67449e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik
67549e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        Sk3DView mTransformCamera;
676a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
677a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        // Force layer on for functors to enable render features they don't yet support (clipping)
678a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        bool mNeedLayerForFunctors = false;
679d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    } mComputedFields;
680acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck};
681acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
682acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck} /* namespace uirenderer */
683acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck} /* namespace android */
684