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
27260ab726486317496bc12a57d599ea96dcde3284Mike Reed#include <SkBlendMode.h>
28acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck#include <SkCamera.h>
29acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck#include <SkMatrix.h>
308c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik#include <SkRegion.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>
38c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv#include <ostream>
39acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
40acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckclass SkBitmap;
4125fbb3fa1138675379102a44405852555cefccbdJohn Reckclass SkColorFilter;
42acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckclass SkPaint;
43acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
44acb6f07623b7df3d4179f70ae03ade574616ffa6John Recknamespace android {
45acb6f07623b7df3d4179f70ae03ade574616ffa6John Recknamespace uirenderer {
46acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
47acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckclass Matrix4;
48acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckclass RenderNode;
4925fbb3fa1138675379102a44405852555cefccbdJohn Reckclass RenderProperties;
50acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
5179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck// The __VA_ARGS__ will be executed if a & b are not equal
52cef190de850f163dd4b95d667a8d46d46e860363Chih-Hung Hsieh#define RP_SET(a, b, ...) ((a) != (b) ? ((a) = (b), ##__VA_ARGS__, true) : false)
5379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck#define RP_SET_AND_DIRTY(a, b) RP_SET(a, b, mPrimitiveFields.mMatrixOrPivotDirty = true)
5479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck
5525fbb3fa1138675379102a44405852555cefccbdJohn Reck// Keep in sync with View.java:LAYER_TYPE_*
56182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craikenum class LayerType {
57182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    None = 0,
5825fbb3fa1138675379102a44405852555cefccbdJohn Reck    // Although we cannot build the software layer directly (must be done at
5925fbb3fa1138675379102a44405852555cefccbdJohn Reck    // record time), this information is used when applying alpha.
60182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    Software = 1,
61182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    RenderLayer = 2,
6225fbb3fa1138675379102a44405852555cefccbdJohn Reck    // TODO: LayerTypeSurfaceTexture? Maybe?
6325fbb3fa1138675379102a44405852555cefccbdJohn Reck};
6425fbb3fa1138675379102a44405852555cefccbdJohn Reck
65a753f4c6cb8558795e673df1896532cd148781e2Chris Craikenum ClippingFlags {
66a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    CLIP_TO_BOUNDS =      0x1 << 0,
67a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    CLIP_TO_CLIP_BOUNDS = 0x1 << 1,
68a753f4c6cb8558795e673df1896532cd148781e2Chris Craik};
69a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
7025fbb3fa1138675379102a44405852555cefccbdJohn Reckclass ANDROID_API LayerProperties {
7125fbb3fa1138675379102a44405852555cefccbdJohn Reckpublic:
7225fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setType(LayerType type) {
7325fbb3fa1138675379102a44405852555cefccbdJohn Reck        if (RP_SET(mType, type)) {
7425fbb3fa1138675379102a44405852555cefccbdJohn Reck            reset();
7525fbb3fa1138675379102a44405852555cefccbdJohn Reck            return true;
7625fbb3fa1138675379102a44405852555cefccbdJohn Reck        }
7725fbb3fa1138675379102a44405852555cefccbdJohn Reck        return false;
7825fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
7925fbb3fa1138675379102a44405852555cefccbdJohn Reck
8025fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setOpaque(bool opaque) {
8125fbb3fa1138675379102a44405852555cefccbdJohn Reck        return RP_SET(mOpaque, opaque);
8225fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
8325fbb3fa1138675379102a44405852555cefccbdJohn Reck
8425fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool opaque() const {
8525fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mOpaque;
8625fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
8725fbb3fa1138675379102a44405852555cefccbdJohn Reck
8825fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setAlpha(uint8_t alpha) {
8925fbb3fa1138675379102a44405852555cefccbdJohn Reck        return RP_SET(mAlpha, alpha);
9025fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
9125fbb3fa1138675379102a44405852555cefccbdJohn Reck
9225fbb3fa1138675379102a44405852555cefccbdJohn Reck    uint8_t alpha() const {
9325fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mAlpha;
9425fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
9525fbb3fa1138675379102a44405852555cefccbdJohn Reck
96260ab726486317496bc12a57d599ea96dcde3284Mike Reed    bool setXferMode(SkBlendMode mode) {
9725fbb3fa1138675379102a44405852555cefccbdJohn Reck        return RP_SET(mMode, mode);
9825fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
9925fbb3fa1138675379102a44405852555cefccbdJohn Reck
100260ab726486317496bc12a57d599ea96dcde3284Mike Reed    SkBlendMode xferMode() const {
10125fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mMode;
10225fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
10325fbb3fa1138675379102a44405852555cefccbdJohn Reck
10425fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setColorFilter(SkColorFilter* filter);
10525fbb3fa1138675379102a44405852555cefccbdJohn Reck
10625fbb3fa1138675379102a44405852555cefccbdJohn Reck    SkColorFilter* colorFilter() const {
10725fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mColorFilter;
10825fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
10925fbb3fa1138675379102a44405852555cefccbdJohn Reck
11025fbb3fa1138675379102a44405852555cefccbdJohn Reck    // Sets alpha, xfermode, and colorfilter from an SkPaint
11125fbb3fa1138675379102a44405852555cefccbdJohn Reck    // paint may be NULL, in which case defaults will be set
11225fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool setFromPaint(const SkPaint* paint);
11325fbb3fa1138675379102a44405852555cefccbdJohn Reck
11425fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool needsBlending() const {
11525fbb3fa1138675379102a44405852555cefccbdJohn Reck        return !opaque() || alpha() < 255;
11625fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
11725fbb3fa1138675379102a44405852555cefccbdJohn Reck
11825fbb3fa1138675379102a44405852555cefccbdJohn Reck    LayerProperties& operator=(const LayerProperties& other);
11925fbb3fa1138675379102a44405852555cefccbdJohn Reck
12025fbb3fa1138675379102a44405852555cefccbdJohn Reckprivate:
12125fbb3fa1138675379102a44405852555cefccbdJohn Reck    LayerProperties();
12225fbb3fa1138675379102a44405852555cefccbdJohn Reck    ~LayerProperties();
12325fbb3fa1138675379102a44405852555cefccbdJohn Reck    void reset();
12425fbb3fa1138675379102a44405852555cefccbdJohn Reck
125856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik    // Private since external users should go through properties().effectiveLayerType()
126856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik    LayerType type() const {
127856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik        return mType;
128856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik    }
129856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik
13025fbb3fa1138675379102a44405852555cefccbdJohn Reck    friend class RenderProperties;
13125fbb3fa1138675379102a44405852555cefccbdJohn Reck
132182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    LayerType mType = LayerType::None;
13325fbb3fa1138675379102a44405852555cefccbdJohn Reck    // Whether or not that Layer's content is opaque, doesn't include alpha
13425fbb3fa1138675379102a44405852555cefccbdJohn Reck    bool mOpaque;
13525fbb3fa1138675379102a44405852555cefccbdJohn Reck    uint8_t mAlpha;
136260ab726486317496bc12a57d599ea96dcde3284Mike Reed    SkBlendMode mMode;
137182952f5eeefc2a21d76d4664ada0e2d78c1105cChris Craik    SkColorFilter* mColorFilter = nullptr;
13825fbb3fa1138675379102a44405852555cefccbdJohn Reck};
13925fbb3fa1138675379102a44405852555cefccbdJohn Reck
140acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck/*
141acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * Data structure that holds the properties for a RenderNode
142acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck */
14325fbb3fa1138675379102a44405852555cefccbdJohn Reckclass ANDROID_API RenderProperties {
144acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckpublic:
145acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    RenderProperties();
146acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    virtual ~RenderProperties();
147acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
148a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    static bool setFlag(int flag, bool newValue, int* outFlags) {
149a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        if (newValue) {
150a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            if (!(flag & *outFlags)) {
151a753f4c6cb8558795e673df1896532cd148781e2Chris Craik                *outFlags |= flag;
152a753f4c6cb8558795e673df1896532cd148781e2Chris Craik                return true;
153a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            }
154a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            return false;
155a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        } else {
156a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            if (flag & *outFlags) {
157a753f4c6cb8558795e673df1896532cd148781e2Chris Craik                *outFlags &= ~flag;
158a753f4c6cb8558795e673df1896532cd148781e2Chris Craik                return true;
159a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            }
160a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            return false;
161a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        }
162a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    }
163a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
164a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik    /**
165a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik     * Set internal layer state based on whether this layer
166a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik     *
167a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik     * Additionally, returns true if child RenderNodes with functors will need to use a layer
168a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik     * to support clipping.
169a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik     */
170a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik    bool prepareForFunctorPresence(bool willHaveFunctor, bool ancestorDictatesFunctorsNeedLayer) {
171a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        // parent may have already dictated that a descendant layer is needed
172a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        bool functorsNeedLayer = ancestorDictatesFunctorsNeedLayer
173a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
174a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                // Round rect clipping forces layer for functors
175b60d3e7856f74c72898b2cba553db0d2e2d1365dChris Craik                || CC_UNLIKELY(getOutline().willRoundRectClip())
176a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                || CC_UNLIKELY(getRevealClip().willClip())
177a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
178a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                // Complex matrices forces layer, due to stencil clipping
179a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                || CC_UNLIKELY(getTransformMatrix() && !getTransformMatrix()->isScaleTranslate())
180a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                || CC_UNLIKELY(getAnimationMatrix() && !getAnimationMatrix()->isScaleTranslate())
181a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                || CC_UNLIKELY(getStaticMatrix() && !getStaticMatrix()->isScaleTranslate());
182a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
183a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        mComputedFields.mNeedLayerForFunctors = (willHaveFunctor && functorsNeedLayer);
184a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
185a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        // If on a layer, will have consumed the need for isolating functors from stencil.
186a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        // Thus, it's safe to reset the flag until some descendent sets it.
187a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        return CC_LIKELY(effectiveLayerType() == LayerType::None) && functorsNeedLayer;
188a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik    }
189a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
190d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    RenderProperties& operator=(const RenderProperties& other);
191d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
19279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setClipToBounds(bool clipToBounds) {
193a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        return setFlag(CLIP_TO_BOUNDS, clipToBounds, &mPrimitiveFields.mClippingFlags);
194a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    }
195a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
196a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    bool setClipBounds(const Rect& clipBounds) {
197a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        bool ret = setFlag(CLIP_TO_CLIP_BOUNDS, true, &mPrimitiveFields.mClippingFlags);
198a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        return RP_SET(mPrimitiveFields.mClipBounds, clipBounds) || ret;
199a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    }
200a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
201a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    bool setClipBoundsEmpty() {
202a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        return setFlag(CLIP_TO_CLIP_BOUNDS, false, &mPrimitiveFields.mClippingFlags);
203acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
204acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
20579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setProjectBackwards(bool shouldProject) {
20679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET(mPrimitiveFields.mProjectBackwards, shouldProject);
207acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
208acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
2096fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    bool setProjectionReceiver(bool shouldReceive) {
2106fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        return RP_SET(mPrimitiveFields.mProjectionReceiver, shouldReceive);
211acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
212acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
213d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    bool isProjectionReceiver() const {
214d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mProjectionReceiver;
215acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
216acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
21779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setStaticMatrix(const SkMatrix* matrix) {
218acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        delete mStaticMatrix;
219d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        if (matrix) {
220d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mStaticMatrix = new SkMatrix(*matrix);
221d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        } else {
222e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik            mStaticMatrix = nullptr;
223d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        }
22479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return true;
225acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
226acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
227acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    // Can return NULL
228d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    const SkMatrix* getStaticMatrix() const {
229acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        return mStaticMatrix;
230acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
231acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
23279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setAnimationMatrix(const SkMatrix* matrix) {
233acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        delete mAnimationMatrix;
234acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        if (matrix) {
235acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            mAnimationMatrix = new SkMatrix(*matrix);
236acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        } else {
237e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik            mAnimationMatrix = nullptr;
238acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
23979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return true;
240acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
241acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
24279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setAlpha(float alpha) {
2433b52c03f5035b833d365215420739aa840ac5080John Reck        alpha = MathUtils::clampAlpha(alpha);
24479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET(mPrimitiveFields.mAlpha, alpha);
245acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
246acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
247acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getAlpha() const {
248d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mAlpha;
249acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
250acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
25179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setHasOverlappingRendering(bool hasOverlappingRendering) {
25279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET(mPrimitiveFields.mHasOverlappingRendering, hasOverlappingRendering);
253acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
254acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
255acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    bool hasOverlappingRendering() const {
256d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mHasOverlappingRendering;
257acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
258acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
25979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setElevation(float elevation) {
26079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET(mPrimitiveFields.mElevation, elevation);
26179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        // Don't dirty matrix/pivot, since they don't respect Z
262cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik    }
263cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik
264cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik    float getElevation() const {
265cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik        return mPrimitiveFields.mElevation;
266cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik    }
267cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik
26879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setTranslationX(float translationX) {
26979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationX, translationX);
270acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
271acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
272acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getTranslationX() const {
273d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mTranslationX;
274acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
275acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
27679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setTranslationY(float translationY) {
27779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationY, translationY);
278acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
279acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
280acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getTranslationY() const {
281d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mTranslationY;
282acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
283acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
28479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setTranslationZ(float translationZ) {
28579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET(mPrimitiveFields.mTranslationZ, translationZ);
28679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        // mMatrixOrPivotDirty not set, since matrix doesn't respect Z
287acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
288acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
289acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getTranslationZ() const {
290d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mTranslationZ;
291acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
292acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
293e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    // Animation helper
29479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setX(float value) {
29579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return setTranslationX(value - getLeft());
296e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
297e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
298e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    // Animation helper
299e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    float getX() const {
300e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        return getLeft() + getTranslationX();
301e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
302e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
303e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    // Animation helper
30479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setY(float value) {
30579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return setTranslationY(value - getTop());
306e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
307e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
308e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    // Animation helper
309e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    float getY() const {
310e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        return getTop() + getTranslationY();
311e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
312e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
313e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    // Animation helper
31479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setZ(float value) {
31579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return setTranslationZ(value - getElevation());
316e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
317e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
318cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik    float getZ() const {
319cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik        return getElevation() + getTranslationZ();
320cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik    }
321cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik
32279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setRotation(float rotation) {
32379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mRotation, rotation);
324acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
325acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
326acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getRotation() const {
327d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mRotation;
328acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
329acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
33079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setRotationX(float rotationX) {
33179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationX, rotationX);
332acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
333acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
334acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getRotationX() const {
335d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mRotationX;
336acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
337acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
33879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setRotationY(float rotationY) {
33979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationY, rotationY);
340acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
341acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
342acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getRotationY() const {
343d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mRotationY;
344acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
345acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
34679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setScaleX(float scaleX) {
34779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleX, scaleX);
348acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
349acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
350acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getScaleX() const {
351d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mScaleX;
352acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
353acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
35479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setScaleY(float scaleY) {
35579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleY, scaleY);
356acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
357acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
358acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getScaleY() const {
359d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mScaleY;
360acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
361acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
36279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setPivotX(float pivotX) {
36379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mPivotX, pivotX)
36479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck                || !mPrimitiveFields.mPivotExplicitlySet) {
36579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            mPrimitiveFields.mMatrixOrPivotDirty = true;
36679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            mPrimitiveFields.mPivotExplicitlySet = true;
36779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
36879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        }
36979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
370acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
371acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
372d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    /* Note that getPivotX and getPivotY are adjusted by updateMatrix(),
37379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck     * so the value returned may be stale if the RenderProperties has been
37479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck     * modified since the last call to updateMatrix()
375d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck     */
376d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    float getPivotX() const {
377d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mPivotX;
378d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
379acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
38079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setPivotY(float pivotY) {
38179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mPivotY, pivotY)
38279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck                || !mPrimitiveFields.mPivotExplicitlySet) {
38379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            mPrimitiveFields.mMatrixOrPivotDirty = true;
38479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            mPrimitiveFields.mPivotExplicitlySet = true;
38579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
38679c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        }
38779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
388acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
389acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
390d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    float getPivotY() const {
391d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mPivotY;
392d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
393acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
39449e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik    bool isPivotExplicitlySet() const {
39549e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        return mPrimitiveFields.mPivotExplicitlySet;
39649e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik    }
39749e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik
39879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setCameraDistance(float distance) {
39949e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        if (distance != getCameraDistance()) {
400f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            mPrimitiveFields.mMatrixOrPivotDirty = true;
40149e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik            mComputedFields.mTransformCamera.setCameraLocation(0, 0, distance);
40279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
403acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
40479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
405acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
406acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
407acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    float getCameraDistance() const {
40849e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        // TODO: update getCameraLocationZ() to be const
40949e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        return const_cast<Sk3DView*>(&mComputedFields.mTransformCamera)->getCameraLocationZ();
410acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
411acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
41279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setLeft(int left) {
41379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mLeft, left)) {
414d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
415f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            if (!mPrimitiveFields.mPivotExplicitlySet) {
416f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck                mPrimitiveFields.mMatrixOrPivotDirty = true;
417acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            }
41879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
419acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
42079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
421acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
422acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
423e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    int getLeft() const {
424d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mLeft;
425acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
426acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
42779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setTop(int top) {
42879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mTop, top)) {
429d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
430f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            if (!mPrimitiveFields.mPivotExplicitlySet) {
431f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck                mPrimitiveFields.mMatrixOrPivotDirty = true;
432acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            }
43379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
434acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
43579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
436acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
437acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
438e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    int getTop() const {
439d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mTop;
440acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
441acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
44279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setRight(int right) {
44379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mRight, right)) {
444d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
445f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            if (!mPrimitiveFields.mPivotExplicitlySet) {
446f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck                mPrimitiveFields.mMatrixOrPivotDirty = true;
447acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            }
44879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
449acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
45079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
451acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
452acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
453e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    int getRight() const {
454d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mRight;
455acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
456acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
45779c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setBottom(int bottom) {
45879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        if (RP_SET(mPrimitiveFields.mBottom, bottom)) {
459d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
460f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            if (!mPrimitiveFields.mPivotExplicitlySet) {
461f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck                mPrimitiveFields.mMatrixOrPivotDirty = true;
462acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            }
46379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
464acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
46579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
466acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
467acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
468e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    int getBottom() const {
469d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mBottom;
470acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
471acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
47279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setLeftTop(int left, int top) {
47379c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        bool leftResult = setLeft(left);
47479c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        bool topResult = setTop(top);
47579c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return leftResult || topResult;
476acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
477acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
47879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck    bool setLeftTopRightBottom(int left, int top, int right, int bottom) {
479cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik        if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop
480cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik                || right != mPrimitiveFields.mRight || bottom != mPrimitiveFields.mBottom) {
481d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mLeft = left;
482d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mTop = top;
483d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mRight = right;
484d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mBottom = bottom;
485d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
486d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
487f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck            if (!mPrimitiveFields.mPivotExplicitlySet) {
488f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck                mPrimitiveFields.mMatrixOrPivotDirty = true;
489acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck            }
49079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
491acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
49279c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
493acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
494acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
495a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    bool offsetLeftRight(int offset) {
496acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        if (offset != 0) {
497d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mLeft += offset;
498d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mRight += offset;
49979c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
500acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
50179c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
502acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
503acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
504a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    bool offsetTopBottom(int offset) {
505acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        if (offset != 0) {
506d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mTop += offset;
507d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck            mPrimitiveFields.mBottom += offset;
50879c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck            return true;
509acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck        }
51079c7de77a7da9cbcb9428ab6203987feb35a427fJohn Reck        return false;
511acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
512acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
513b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    int getWidth() const {
514d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mWidth;
515acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    }
516acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
517b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    int getHeight() const {
518d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mHeight;
519d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
520d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
521d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    const SkMatrix* getAnimationMatrix() const {
522d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mAnimationMatrix;
523d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
524d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
525f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck    bool hasTransformMatrix() const {
526f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck        return getTransformMatrix() && !getTransformMatrix()->isIdentity();
527f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck    }
528f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck
529f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck    // May only call this if hasTransformMatrix() is true
530f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck    bool isTransformTranslateOnly() const {
531f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck        return getTransformMatrix()->getType() == SkMatrix::kTranslate_Mask;
532d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
533d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
53449e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik    const SkMatrix* getTransformMatrix() const {
535f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck        LOG_ALWAYS_FATAL_IF(mPrimitiveFields.mMatrixOrPivotDirty, "Cannot get a dirty matrix!");
536d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mComputedFields.mTransformMatrix;
537d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
538d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
539a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    int getClippingFlags() const {
540a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        return mPrimitiveFields.mClippingFlags;
541a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    }
542a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
543d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    bool getClipToBounds() const {
544a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        return mPrimitiveFields.mClippingFlags & CLIP_TO_BOUNDS;
545a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    }
546a753f4c6cb8558795e673df1896532cd148781e2Chris Craik
547e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    const Rect& getClipBounds() const {
548e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        return mPrimitiveFields.mClipBounds;
549e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    }
550e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck
551a753f4c6cb8558795e673df1896532cd148781e2Chris Craik    void getClippingRectForFlags(uint32_t flags, Rect* outRect) const {
552a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        if (flags & CLIP_TO_BOUNDS) {
553a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            outRect->set(0, 0, getWidth(), getHeight());
554a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            if (flags & CLIP_TO_CLIP_BOUNDS) {
555ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik                outRect->doIntersect(mPrimitiveFields.mClipBounds);
556a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            }
557a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        } else {
558a753f4c6cb8558795e673df1896532cd148781e2Chris Craik            outRect->set(mPrimitiveFields.mClipBounds);
559a753f4c6cb8558795e673df1896532cd148781e2Chris Craik        }
560d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
561d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
562d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    bool getHasOverlappingRendering() const {
563d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mHasOverlappingRendering;
564d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
565d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
566d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    const Outline& getOutline() const {
567d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mOutline;
568d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
569d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
5708c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik    const RevealClip& getRevealClip() const {
5718c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik        return mPrimitiveFields.mRevealClip;
5728c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik    }
5738c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik
574d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    bool getProjectBackwards() const {
575d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mProjectBackwards;
576d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    }
577d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
578c3849aa786db65dbda254b90b7db3b13efd98e65sergeyv    void debugOutputProperties(std::ostream& output, const int level) const;
579d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
58025fbb3fa1138675379102a44405852555cefccbdJohn Reck    void updateMatrix();
581d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
582d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    Outline& mutableOutline() {
583d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        return mPrimitiveFields.mOutline;
584b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    }
585b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
5868c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik    RevealClip& mutableRevealClip() {
5878c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik        return mPrimitiveFields.mRevealClip;
5888c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik    }
5898c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik
59025fbb3fa1138675379102a44405852555cefccbdJohn Reck    const LayerProperties& layerProperties() const {
59125fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mLayerProperties;
59225fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
59325fbb3fa1138675379102a44405852555cefccbdJohn Reck
59425fbb3fa1138675379102a44405852555cefccbdJohn Reck    LayerProperties& mutateLayerProperties() {
59525fbb3fa1138675379102a44405852555cefccbdJohn Reck        return mLayerProperties;
59625fbb3fa1138675379102a44405852555cefccbdJohn Reck    }
59725fbb3fa1138675379102a44405852555cefccbdJohn Reck
598293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    // Returns true if damage calculations should be clipped to bounds
599293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    // TODO: Figure out something better for getZ(), as children should still be
600293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    // clipped to this RP's bounds. But as we will damage -INT_MAX to INT_MAX
601293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    // for this RP's getZ() anyway, this can be optimized when we have a
602293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    // Z damage estimate instead of INT_MAX
603293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    bool getClipDamageToBounds() const {
604293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck        return getClipToBounds() && (getZ() <= 0 || getOutline().isEmpty());
605293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    }
606293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck
6075c75c52e048a01c23b18f4e31ae624b5fe43e23cChris Craik    bool hasShadow() const {
608b5a5435a77bae40b55053ccde93b1ed45d0e8329Chris Craik        return getZ() > 0.0f
609e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik                && getOutline().getPath() != nullptr
6109fa364dc72613f4301b0783f0547fe6b01abac39Chris Craik                && getOutline().getAlpha() != 0.0f;
6115c75c52e048a01c23b18f4e31ae624b5fe43e23cChris Craik    }
6125c75c52e048a01c23b18f4e31ae624b5fe43e23cChris Craik
6139fded232a9548a304e0145011df8849fba0dcda7Chris Craik    bool fitsOnLayer() const {
61476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        const DeviceInfo* deviceInfo = DeviceInfo::get();
6159fded232a9548a304e0145011df8849fba0dcda7Chris Craik        return mPrimitiveFields.mWidth <= deviceInfo->maxTextureSize()
616e3e481df762747c5f01bbd1503800fa29457fc1bChris Craik                        && mPrimitiveFields.mHeight <= deviceInfo->maxTextureSize();
6179fded232a9548a304e0145011df8849fba0dcda7Chris Craik    }
6189fded232a9548a304e0145011df8849fba0dcda7Chris Craik
6199fded232a9548a304e0145011df8849fba0dcda7Chris Craik    bool promotedToLayer() const {
6201a0808e64c170fa7b620b858fa5875f6f08a2b54Chris Craik        return mLayerProperties.mType == LayerType::None
6219fded232a9548a304e0145011df8849fba0dcda7Chris Craik                && fitsOnLayer()
622a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                && (mComputedFields.mNeedLayerForFunctors
623a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                        || (!MathUtils::isZero(mPrimitiveFields.mAlpha)
624a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                                && mPrimitiveFields.mAlpha < 1
625a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik                                && mPrimitiveFields.mHasOverlappingRendering));
6261a0808e64c170fa7b620b858fa5875f6f08a2b54Chris Craik    }
6271a0808e64c170fa7b620b858fa5875f6f08a2b54Chris Craik
6281a0808e64c170fa7b620b858fa5875f6f08a2b54Chris Craik    LayerType effectiveLayerType() const {
629a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        return CC_UNLIKELY(promotedToLayer()) ? LayerType::RenderLayer : mLayerProperties.mType;
630856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik    }
631856f0cc3e382206e67c1a62fe878627d7dd9ada5Chris Craik
632acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckprivate:
633acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    // Rendering properties
634d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    struct PrimitiveFields {
635e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        int mLeft = 0, mTop = 0, mRight = 0, mBottom = 0;
636e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        int mWidth = 0, mHeight = 0;
637e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        int mClippingFlags = CLIP_TO_BOUNDS;
638e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mAlpha = 1;
639e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mTranslationX = 0, mTranslationY = 0, mTranslationZ = 0;
640e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mElevation = 0;
641e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mRotation = 0, mRotationX = 0, mRotationY = 0;
642e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mScaleX = 1, mScaleY = 1;
643e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        float mPivotX = 0, mPivotY = 0;
644e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        bool mHasOverlappingRendering = false;
645e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        bool mPivotExplicitlySet = false;
646e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        bool mMatrixOrPivotDirty = false;
647e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        bool mProjectBackwards = false;
648e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        bool mProjectionReceiver = false;
649e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        Rect mClipBounds;
650d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        Outline mOutline;
6518c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik        RevealClip mRevealClip;
652d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    } mPrimitiveFields;
653d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
654acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    SkMatrix* mStaticMatrix;
655acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck    SkMatrix* mAnimationMatrix;
65625fbb3fa1138675379102a44405852555cefccbdJohn Reck    LayerProperties mLayerProperties;
657acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
658d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    /**
659d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck     * These fields are all generated from other properties and are not set directly.
660d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck     */
661d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    struct ComputedFields {
662d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        ComputedFields();
663d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        ~ComputedFields();
664d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck
665d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck        /**
666d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck         * Stores the total transformation of the DisplayList based upon its scalar
667d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck         * translate/rotate/scale properties.
668d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck         *
66949e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik         * In the common translation-only case, the matrix isn't necessarily allocated,
67049e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik         * and the mTranslation properties are used directly.
671d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck         */
67249e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        SkMatrix* mTransformMatrix;
67349e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik
67449e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        Sk3DView mTransformCamera;
675a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik
676a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        // Force layer on for functors to enable render features they don't yet support (clipping)
677a766cb2bce5db9108c0266fbebea6aa18d5713ffChris Craik        bool mNeedLayerForFunctors = false;
678d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    } mComputedFields;
679acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck};
680acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck
681acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck} /* namespace uirenderer */
682acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck} /* namespace android */
683