1*d57664e9SAndroid Build Coastguard Worker /* 2*d57664e9SAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project 3*d57664e9SAndroid Build Coastguard Worker * 4*d57664e9SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*d57664e9SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*d57664e9SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*d57664e9SAndroid Build Coastguard Worker * 8*d57664e9SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*d57664e9SAndroid Build Coastguard Worker * 10*d57664e9SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*d57664e9SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*d57664e9SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*d57664e9SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*d57664e9SAndroid Build Coastguard Worker * limitations under the License. 15*d57664e9SAndroid Build Coastguard Worker */ 16*d57664e9SAndroid Build Coastguard Worker 17*d57664e9SAndroid Build Coastguard Worker #pragma once 18*d57664e9SAndroid Build Coastguard Worker 19*d57664e9SAndroid Build Coastguard Worker #include <SkBlendMode.h> 20*d57664e9SAndroid Build Coastguard Worker #include <SkCamera.h> 21*d57664e9SAndroid Build Coastguard Worker #include <SkColor.h> 22*d57664e9SAndroid Build Coastguard Worker #include <SkImageFilter.h> 23*d57664e9SAndroid Build Coastguard Worker #include <SkMatrix.h> 24*d57664e9SAndroid Build Coastguard Worker #include <SkRegion.h> 25*d57664e9SAndroid Build Coastguard Worker #include <androidfw/ResourceTypes.h> 26*d57664e9SAndroid Build Coastguard Worker #include <cutils/compiler.h> 27*d57664e9SAndroid Build Coastguard Worker #include <stddef.h> 28*d57664e9SAndroid Build Coastguard Worker #include <utils/Log.h> 29*d57664e9SAndroid Build Coastguard Worker 30*d57664e9SAndroid Build Coastguard Worker #include <algorithm> 31*d57664e9SAndroid Build Coastguard Worker #include <ostream> 32*d57664e9SAndroid Build Coastguard Worker #include <vector> 33*d57664e9SAndroid Build Coastguard Worker 34*d57664e9SAndroid Build Coastguard Worker #include "DeviceInfo.h" 35*d57664e9SAndroid Build Coastguard Worker #include "Outline.h" 36*d57664e9SAndroid Build Coastguard Worker #include "Rect.h" 37*d57664e9SAndroid Build Coastguard Worker #include "RevealClip.h" 38*d57664e9SAndroid Build Coastguard Worker #include "effects/StretchEffect.h" 39*d57664e9SAndroid Build Coastguard Worker #include "utils/MathUtils.h" 40*d57664e9SAndroid Build Coastguard Worker #include "utils/PaintUtils.h" 41*d57664e9SAndroid Build Coastguard Worker 42*d57664e9SAndroid Build Coastguard Worker class SkBitmap; 43*d57664e9SAndroid Build Coastguard Worker class SkColorFilter; 44*d57664e9SAndroid Build Coastguard Worker class SkPaint; 45*d57664e9SAndroid Build Coastguard Worker 46*d57664e9SAndroid Build Coastguard Worker namespace android { 47*d57664e9SAndroid Build Coastguard Worker namespace uirenderer { 48*d57664e9SAndroid Build Coastguard Worker 49*d57664e9SAndroid Build Coastguard Worker class Matrix4; 50*d57664e9SAndroid Build Coastguard Worker class RenderNode; 51*d57664e9SAndroid Build Coastguard Worker class RenderProperties; 52*d57664e9SAndroid Build Coastguard Worker 53*d57664e9SAndroid Build Coastguard Worker // The __VA_ARGS__ will be executed if a & b are not equal 54*d57664e9SAndroid Build Coastguard Worker #define RP_SET(a, b, ...) ((a) != (b) ? ((a) = (b), ##__VA_ARGS__, true) : false) 55*d57664e9SAndroid Build Coastguard Worker #define RP_SET_AND_DIRTY(a, b) RP_SET(a, b, mPrimitiveFields.mMatrixOrPivotDirty = true) 56*d57664e9SAndroid Build Coastguard Worker 57*d57664e9SAndroid Build Coastguard Worker // Keep in sync with View.java:LAYER_TYPE_* 58*d57664e9SAndroid Build Coastguard Worker enum class LayerType { 59*d57664e9SAndroid Build Coastguard Worker None = 0, 60*d57664e9SAndroid Build Coastguard Worker // We cannot build the software layer directly (must be done at record time) and all management 61*d57664e9SAndroid Build Coastguard Worker // of software layers is handled in Java. 62*d57664e9SAndroid Build Coastguard Worker Software = 1, 63*d57664e9SAndroid Build Coastguard Worker RenderLayer = 2, 64*d57664e9SAndroid Build Coastguard Worker }; 65*d57664e9SAndroid Build Coastguard Worker 66*d57664e9SAndroid Build Coastguard Worker enum ClippingFlags { 67*d57664e9SAndroid Build Coastguard Worker CLIP_TO_BOUNDS = 0x1 << 0, 68*d57664e9SAndroid Build Coastguard Worker CLIP_TO_CLIP_BOUNDS = 0x1 << 1, 69*d57664e9SAndroid Build Coastguard Worker }; 70*d57664e9SAndroid Build Coastguard Worker 71*d57664e9SAndroid Build Coastguard Worker class LayerProperties { 72*d57664e9SAndroid Build Coastguard Worker public: setType(LayerType type)73*d57664e9SAndroid Build Coastguard Worker bool setType(LayerType type) { 74*d57664e9SAndroid Build Coastguard Worker if (RP_SET(mType, type)) { 75*d57664e9SAndroid Build Coastguard Worker reset(); 76*d57664e9SAndroid Build Coastguard Worker return true; 77*d57664e9SAndroid Build Coastguard Worker } 78*d57664e9SAndroid Build Coastguard Worker return false; 79*d57664e9SAndroid Build Coastguard Worker } 80*d57664e9SAndroid Build Coastguard Worker setOpaque(bool opaque)81*d57664e9SAndroid Build Coastguard Worker bool setOpaque(bool opaque) { return RP_SET(mOpaque, opaque); } 82*d57664e9SAndroid Build Coastguard Worker opaque()83*d57664e9SAndroid Build Coastguard Worker bool opaque() const { return mOpaque; } 84*d57664e9SAndroid Build Coastguard Worker setAlpha(uint8_t alpha)85*d57664e9SAndroid Build Coastguard Worker bool setAlpha(uint8_t alpha) { return RP_SET(mAlpha, alpha); } 86*d57664e9SAndroid Build Coastguard Worker alpha()87*d57664e9SAndroid Build Coastguard Worker uint8_t alpha() const { return mAlpha; } 88*d57664e9SAndroid Build Coastguard Worker setXferMode(SkBlendMode mode)89*d57664e9SAndroid Build Coastguard Worker bool setXferMode(SkBlendMode mode) { return RP_SET(mMode, mode); } 90*d57664e9SAndroid Build Coastguard Worker xferMode()91*d57664e9SAndroid Build Coastguard Worker SkBlendMode xferMode() const { return mMode; } 92*d57664e9SAndroid Build Coastguard Worker getColorFilter()93*d57664e9SAndroid Build Coastguard Worker SkColorFilter* getColorFilter() const { return mColorFilter.get(); } 94*d57664e9SAndroid Build Coastguard Worker 95*d57664e9SAndroid Build Coastguard Worker bool setImageFilter(SkImageFilter* imageFilter); 96*d57664e9SAndroid Build Coastguard Worker 97*d57664e9SAndroid Build Coastguard Worker bool setBackdropImageFilter(SkImageFilter* imageFilter); 98*d57664e9SAndroid Build Coastguard Worker getImageFilter()99*d57664e9SAndroid Build Coastguard Worker SkImageFilter* getImageFilter() const { return mImageFilter.get(); } 100*d57664e9SAndroid Build Coastguard Worker getBackdropImageFilter()101*d57664e9SAndroid Build Coastguard Worker SkImageFilter* getBackdropImageFilter() const { return mBackdropImageFilter.get(); } 102*d57664e9SAndroid Build Coastguard Worker getStretchEffect()103*d57664e9SAndroid Build Coastguard Worker const StretchEffect& getStretchEffect() const { return mStretchEffect; } 104*d57664e9SAndroid Build Coastguard Worker mutableStretchEffect()105*d57664e9SAndroid Build Coastguard Worker StretchEffect& mutableStretchEffect() { return mStretchEffect; } 106*d57664e9SAndroid Build Coastguard Worker 107*d57664e9SAndroid Build Coastguard Worker // Sets alpha, xfermode, and colorfilter from an SkPaint 108*d57664e9SAndroid Build Coastguard Worker // paint may be NULL, in which case defaults will be set 109*d57664e9SAndroid Build Coastguard Worker bool setFromPaint(const SkPaint* paint); 110*d57664e9SAndroid Build Coastguard Worker needsBlending()111*d57664e9SAndroid Build Coastguard Worker bool needsBlending() const { return !opaque() || alpha() < 255; } 112*d57664e9SAndroid Build Coastguard Worker 113*d57664e9SAndroid Build Coastguard Worker LayerProperties& operator=(const LayerProperties& other); 114*d57664e9SAndroid Build Coastguard Worker 115*d57664e9SAndroid Build Coastguard Worker // Strongly recommend using effectiveLayerType instead type()116*d57664e9SAndroid Build Coastguard Worker LayerType type() const { return mType; } 117*d57664e9SAndroid Build Coastguard Worker 118*d57664e9SAndroid Build Coastguard Worker private: 119*d57664e9SAndroid Build Coastguard Worker LayerProperties(); 120*d57664e9SAndroid Build Coastguard Worker ~LayerProperties(); 121*d57664e9SAndroid Build Coastguard Worker void reset(); 122*d57664e9SAndroid Build Coastguard Worker bool setColorFilter(SkColorFilter* filter); 123*d57664e9SAndroid Build Coastguard Worker 124*d57664e9SAndroid Build Coastguard Worker friend class RenderProperties; 125*d57664e9SAndroid Build Coastguard Worker 126*d57664e9SAndroid Build Coastguard Worker LayerType mType = LayerType::None; 127*d57664e9SAndroid Build Coastguard Worker // Whether or not that Layer's content is opaque, doesn't include alpha 128*d57664e9SAndroid Build Coastguard Worker bool mOpaque; 129*d57664e9SAndroid Build Coastguard Worker uint8_t mAlpha; 130*d57664e9SAndroid Build Coastguard Worker SkBlendMode mMode; 131*d57664e9SAndroid Build Coastguard Worker sk_sp<SkColorFilter> mColorFilter; 132*d57664e9SAndroid Build Coastguard Worker sk_sp<SkImageFilter> mImageFilter; 133*d57664e9SAndroid Build Coastguard Worker sk_sp<SkImageFilter> mBackdropImageFilter; 134*d57664e9SAndroid Build Coastguard Worker StretchEffect mStretchEffect; 135*d57664e9SAndroid Build Coastguard Worker }; 136*d57664e9SAndroid Build Coastguard Worker 137*d57664e9SAndroid Build Coastguard Worker /* 138*d57664e9SAndroid Build Coastguard Worker * Data structure that holds the properties for a RenderNode 139*d57664e9SAndroid Build Coastguard Worker */ 140*d57664e9SAndroid Build Coastguard Worker class RenderProperties { 141*d57664e9SAndroid Build Coastguard Worker public: 142*d57664e9SAndroid Build Coastguard Worker RenderProperties(); 143*d57664e9SAndroid Build Coastguard Worker virtual ~RenderProperties(); 144*d57664e9SAndroid Build Coastguard Worker setFlag(int flag,bool newValue,int * outFlags)145*d57664e9SAndroid Build Coastguard Worker static bool setFlag(int flag, bool newValue, int* outFlags) { 146*d57664e9SAndroid Build Coastguard Worker if (newValue) { 147*d57664e9SAndroid Build Coastguard Worker if (!(flag & *outFlags)) { 148*d57664e9SAndroid Build Coastguard Worker *outFlags |= flag; 149*d57664e9SAndroid Build Coastguard Worker return true; 150*d57664e9SAndroid Build Coastguard Worker } 151*d57664e9SAndroid Build Coastguard Worker return false; 152*d57664e9SAndroid Build Coastguard Worker } else { 153*d57664e9SAndroid Build Coastguard Worker if (flag & *outFlags) { 154*d57664e9SAndroid Build Coastguard Worker *outFlags &= ~flag; 155*d57664e9SAndroid Build Coastguard Worker return true; 156*d57664e9SAndroid Build Coastguard Worker } 157*d57664e9SAndroid Build Coastguard Worker return false; 158*d57664e9SAndroid Build Coastguard Worker } 159*d57664e9SAndroid Build Coastguard Worker } 160*d57664e9SAndroid Build Coastguard Worker 161*d57664e9SAndroid Build Coastguard Worker /** 162*d57664e9SAndroid Build Coastguard Worker * Set internal layer state based on whether this layer 163*d57664e9SAndroid Build Coastguard Worker * 164*d57664e9SAndroid Build Coastguard Worker * Additionally, returns true if child RenderNodes with functors will need to use a layer 165*d57664e9SAndroid Build Coastguard Worker * to support clipping. 166*d57664e9SAndroid Build Coastguard Worker */ prepareForFunctorPresence(bool willHaveFunctor,bool ancestorDictatesFunctorsNeedLayer)167*d57664e9SAndroid Build Coastguard Worker bool prepareForFunctorPresence(bool willHaveFunctor, bool ancestorDictatesFunctorsNeedLayer) { 168*d57664e9SAndroid Build Coastguard Worker // parent may have already dictated that a descendant layer is needed 169*d57664e9SAndroid Build Coastguard Worker bool functorsNeedLayer = 170*d57664e9SAndroid Build Coastguard Worker ancestorDictatesFunctorsNeedLayer || 171*d57664e9SAndroid Build Coastguard Worker CC_UNLIKELY(isClipMayBeComplex()) 172*d57664e9SAndroid Build Coastguard Worker 173*d57664e9SAndroid Build Coastguard Worker // Round rect clipping forces layer for functors 174*d57664e9SAndroid Build Coastguard Worker || CC_UNLIKELY(getOutline().willComplexClip()) || 175*d57664e9SAndroid Build Coastguard Worker CC_UNLIKELY(getRevealClip().willClip()) 176*d57664e9SAndroid Build Coastguard Worker 177*d57664e9SAndroid Build Coastguard Worker // Complex matrices forces layer, due to stencil clipping 178*d57664e9SAndroid Build Coastguard Worker || CC_UNLIKELY(getTransformMatrix() && !getTransformMatrix()->isScaleTranslate()) || 179*d57664e9SAndroid Build Coastguard Worker CC_UNLIKELY(getAnimationMatrix() && !getAnimationMatrix()->isScaleTranslate()) || 180*d57664e9SAndroid Build Coastguard Worker CC_UNLIKELY(getStaticMatrix() && !getStaticMatrix()->isScaleTranslate()); 181*d57664e9SAndroid Build Coastguard Worker 182*d57664e9SAndroid Build Coastguard Worker mComputedFields.mNeedLayerForFunctors = (willHaveFunctor && functorsNeedLayer); 183*d57664e9SAndroid Build Coastguard Worker 184*d57664e9SAndroid Build Coastguard Worker // If on a layer, will have consumed the need for isolating functors from stencil. 185*d57664e9SAndroid Build Coastguard Worker // Thus, it's safe to reset the flag until some descendent sets it. 186*d57664e9SAndroid Build Coastguard Worker return CC_LIKELY(effectiveLayerType() == LayerType::None) && functorsNeedLayer; 187*d57664e9SAndroid Build Coastguard Worker } 188*d57664e9SAndroid Build Coastguard Worker 189*d57664e9SAndroid Build Coastguard Worker RenderProperties& operator=(const RenderProperties& other); 190*d57664e9SAndroid Build Coastguard Worker setClipToBounds(bool clipToBounds)191*d57664e9SAndroid Build Coastguard Worker bool setClipToBounds(bool clipToBounds) { 192*d57664e9SAndroid Build Coastguard Worker return setFlag(CLIP_TO_BOUNDS, clipToBounds, &mPrimitiveFields.mClippingFlags); 193*d57664e9SAndroid Build Coastguard Worker } 194*d57664e9SAndroid Build Coastguard Worker setClipBounds(const Rect & clipBounds)195*d57664e9SAndroid Build Coastguard Worker bool setClipBounds(const Rect& clipBounds) { 196*d57664e9SAndroid Build Coastguard Worker bool ret = setFlag(CLIP_TO_CLIP_BOUNDS, true, &mPrimitiveFields.mClippingFlags); 197*d57664e9SAndroid Build Coastguard Worker return RP_SET(mPrimitiveFields.mClipBounds, clipBounds) || ret; 198*d57664e9SAndroid Build Coastguard Worker } 199*d57664e9SAndroid Build Coastguard Worker setClipBoundsEmpty()200*d57664e9SAndroid Build Coastguard Worker bool setClipBoundsEmpty() { 201*d57664e9SAndroid Build Coastguard Worker return setFlag(CLIP_TO_CLIP_BOUNDS, false, &mPrimitiveFields.mClippingFlags); 202*d57664e9SAndroid Build Coastguard Worker } 203*d57664e9SAndroid Build Coastguard Worker setProjectBackwards(bool shouldProject)204*d57664e9SAndroid Build Coastguard Worker bool setProjectBackwards(bool shouldProject) { 205*d57664e9SAndroid Build Coastguard Worker return RP_SET(mPrimitiveFields.mProjectBackwards, shouldProject); 206*d57664e9SAndroid Build Coastguard Worker } 207*d57664e9SAndroid Build Coastguard Worker setProjectionReceiver(bool shouldReceive)208*d57664e9SAndroid Build Coastguard Worker bool setProjectionReceiver(bool shouldReceive) { 209*d57664e9SAndroid Build Coastguard Worker return RP_SET(mPrimitiveFields.mProjectionReceiver, shouldReceive); 210*d57664e9SAndroid Build Coastguard Worker } 211*d57664e9SAndroid Build Coastguard Worker isProjectionReceiver()212*d57664e9SAndroid Build Coastguard Worker bool isProjectionReceiver() const { return mPrimitiveFields.mProjectionReceiver; } 213*d57664e9SAndroid Build Coastguard Worker setClipMayBeComplex(bool isClipMayBeComplex)214*d57664e9SAndroid Build Coastguard Worker bool setClipMayBeComplex(bool isClipMayBeComplex) { 215*d57664e9SAndroid Build Coastguard Worker return RP_SET(mPrimitiveFields.mClipMayBeComplex, isClipMayBeComplex); 216*d57664e9SAndroid Build Coastguard Worker } 217*d57664e9SAndroid Build Coastguard Worker isClipMayBeComplex()218*d57664e9SAndroid Build Coastguard Worker bool isClipMayBeComplex() const { return mPrimitiveFields.mClipMayBeComplex; } 219*d57664e9SAndroid Build Coastguard Worker setStaticMatrix(const SkMatrix * matrix)220*d57664e9SAndroid Build Coastguard Worker bool setStaticMatrix(const SkMatrix* matrix) { 221*d57664e9SAndroid Build Coastguard Worker delete mStaticMatrix; 222*d57664e9SAndroid Build Coastguard Worker if (matrix) { 223*d57664e9SAndroid Build Coastguard Worker mStaticMatrix = new SkMatrix(*matrix); 224*d57664e9SAndroid Build Coastguard Worker } else { 225*d57664e9SAndroid Build Coastguard Worker mStaticMatrix = nullptr; 226*d57664e9SAndroid Build Coastguard Worker } 227*d57664e9SAndroid Build Coastguard Worker return true; 228*d57664e9SAndroid Build Coastguard Worker } 229*d57664e9SAndroid Build Coastguard Worker 230*d57664e9SAndroid Build Coastguard Worker // Can return NULL getStaticMatrix()231*d57664e9SAndroid Build Coastguard Worker const SkMatrix* getStaticMatrix() const { return mStaticMatrix; } 232*d57664e9SAndroid Build Coastguard Worker setAnimationMatrix(const SkMatrix * matrix)233*d57664e9SAndroid Build Coastguard Worker bool setAnimationMatrix(const SkMatrix* matrix) { 234*d57664e9SAndroid Build Coastguard Worker delete mAnimationMatrix; 235*d57664e9SAndroid Build Coastguard Worker if (matrix) { 236*d57664e9SAndroid Build Coastguard Worker mAnimationMatrix = new SkMatrix(*matrix); 237*d57664e9SAndroid Build Coastguard Worker } else { 238*d57664e9SAndroid Build Coastguard Worker mAnimationMatrix = nullptr; 239*d57664e9SAndroid Build Coastguard Worker } 240*d57664e9SAndroid Build Coastguard Worker return true; 241*d57664e9SAndroid Build Coastguard Worker } 242*d57664e9SAndroid Build Coastguard Worker setAlpha(float alpha)243*d57664e9SAndroid Build Coastguard Worker bool setAlpha(float alpha) { 244*d57664e9SAndroid Build Coastguard Worker alpha = MathUtils::clampAlpha(alpha); 245*d57664e9SAndroid Build Coastguard Worker return RP_SET(mPrimitiveFields.mAlpha, alpha); 246*d57664e9SAndroid Build Coastguard Worker } 247*d57664e9SAndroid Build Coastguard Worker getAlpha()248*d57664e9SAndroid Build Coastguard Worker float getAlpha() const { return mPrimitiveFields.mAlpha; } 249*d57664e9SAndroid Build Coastguard Worker setHasOverlappingRendering(bool hasOverlappingRendering)250*d57664e9SAndroid Build Coastguard Worker bool setHasOverlappingRendering(bool hasOverlappingRendering) { 251*d57664e9SAndroid Build Coastguard Worker return RP_SET(mPrimitiveFields.mHasOverlappingRendering, hasOverlappingRendering); 252*d57664e9SAndroid Build Coastguard Worker } 253*d57664e9SAndroid Build Coastguard Worker hasOverlappingRendering()254*d57664e9SAndroid Build Coastguard Worker bool hasOverlappingRendering() const { return mPrimitiveFields.mHasOverlappingRendering; } 255*d57664e9SAndroid Build Coastguard Worker setElevation(float elevation)256*d57664e9SAndroid Build Coastguard Worker bool setElevation(float elevation) { 257*d57664e9SAndroid Build Coastguard Worker return RP_SET(mPrimitiveFields.mElevation, elevation); 258*d57664e9SAndroid Build Coastguard Worker // Don't dirty matrix/pivot, since they don't respect Z 259*d57664e9SAndroid Build Coastguard Worker } 260*d57664e9SAndroid Build Coastguard Worker getElevation()261*d57664e9SAndroid Build Coastguard Worker float getElevation() const { return mPrimitiveFields.mElevation; } 262*d57664e9SAndroid Build Coastguard Worker setTranslationX(float translationX)263*d57664e9SAndroid Build Coastguard Worker bool setTranslationX(float translationX) { 264*d57664e9SAndroid Build Coastguard Worker return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationX, translationX); 265*d57664e9SAndroid Build Coastguard Worker } 266*d57664e9SAndroid Build Coastguard Worker getTranslationX()267*d57664e9SAndroid Build Coastguard Worker float getTranslationX() const { return mPrimitiveFields.mTranslationX; } 268*d57664e9SAndroid Build Coastguard Worker setTranslationY(float translationY)269*d57664e9SAndroid Build Coastguard Worker bool setTranslationY(float translationY) { 270*d57664e9SAndroid Build Coastguard Worker return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationY, translationY); 271*d57664e9SAndroid Build Coastguard Worker } 272*d57664e9SAndroid Build Coastguard Worker getTranslationY()273*d57664e9SAndroid Build Coastguard Worker float getTranslationY() const { return mPrimitiveFields.mTranslationY; } 274*d57664e9SAndroid Build Coastguard Worker setTranslationZ(float translationZ)275*d57664e9SAndroid Build Coastguard Worker bool setTranslationZ(float translationZ) { 276*d57664e9SAndroid Build Coastguard Worker return RP_SET(mPrimitiveFields.mTranslationZ, translationZ); 277*d57664e9SAndroid Build Coastguard Worker // mMatrixOrPivotDirty not set, since matrix doesn't respect Z 278*d57664e9SAndroid Build Coastguard Worker } 279*d57664e9SAndroid Build Coastguard Worker getTranslationZ()280*d57664e9SAndroid Build Coastguard Worker float getTranslationZ() const { return mPrimitiveFields.mTranslationZ; } 281*d57664e9SAndroid Build Coastguard Worker 282*d57664e9SAndroid Build Coastguard Worker // Animation helper setX(float value)283*d57664e9SAndroid Build Coastguard Worker bool setX(float value) { return setTranslationX(value - getLeft()); } 284*d57664e9SAndroid Build Coastguard Worker 285*d57664e9SAndroid Build Coastguard Worker // Animation helper getX()286*d57664e9SAndroid Build Coastguard Worker float getX() const { return getLeft() + getTranslationX(); } 287*d57664e9SAndroid Build Coastguard Worker 288*d57664e9SAndroid Build Coastguard Worker // Animation helper setY(float value)289*d57664e9SAndroid Build Coastguard Worker bool setY(float value) { return setTranslationY(value - getTop()); } 290*d57664e9SAndroid Build Coastguard Worker 291*d57664e9SAndroid Build Coastguard Worker // Animation helper getY()292*d57664e9SAndroid Build Coastguard Worker float getY() const { return getTop() + getTranslationY(); } 293*d57664e9SAndroid Build Coastguard Worker 294*d57664e9SAndroid Build Coastguard Worker // Animation helper setZ(float value)295*d57664e9SAndroid Build Coastguard Worker bool setZ(float value) { return setTranslationZ(value - getElevation()); } 296*d57664e9SAndroid Build Coastguard Worker getZ()297*d57664e9SAndroid Build Coastguard Worker float getZ() const { return getElevation() + getTranslationZ(); } 298*d57664e9SAndroid Build Coastguard Worker setRotation(float rotation)299*d57664e9SAndroid Build Coastguard Worker bool setRotation(float rotation) { 300*d57664e9SAndroid Build Coastguard Worker return RP_SET_AND_DIRTY(mPrimitiveFields.mRotation, rotation); 301*d57664e9SAndroid Build Coastguard Worker } 302*d57664e9SAndroid Build Coastguard Worker getRotation()303*d57664e9SAndroid Build Coastguard Worker float getRotation() const { return mPrimitiveFields.mRotation; } 304*d57664e9SAndroid Build Coastguard Worker setRotationX(float rotationX)305*d57664e9SAndroid Build Coastguard Worker bool setRotationX(float rotationX) { 306*d57664e9SAndroid Build Coastguard Worker return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationX, rotationX); 307*d57664e9SAndroid Build Coastguard Worker } 308*d57664e9SAndroid Build Coastguard Worker getRotationX()309*d57664e9SAndroid Build Coastguard Worker float getRotationX() const { return mPrimitiveFields.mRotationX; } 310*d57664e9SAndroid Build Coastguard Worker setRotationY(float rotationY)311*d57664e9SAndroid Build Coastguard Worker bool setRotationY(float rotationY) { 312*d57664e9SAndroid Build Coastguard Worker return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationY, rotationY); 313*d57664e9SAndroid Build Coastguard Worker } 314*d57664e9SAndroid Build Coastguard Worker getRotationY()315*d57664e9SAndroid Build Coastguard Worker float getRotationY() const { return mPrimitiveFields.mRotationY; } 316*d57664e9SAndroid Build Coastguard Worker setScaleX(float scaleX)317*d57664e9SAndroid Build Coastguard Worker bool setScaleX(float scaleX) { return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleX, scaleX); } 318*d57664e9SAndroid Build Coastguard Worker getScaleX()319*d57664e9SAndroid Build Coastguard Worker float getScaleX() const { return mPrimitiveFields.mScaleX; } 320*d57664e9SAndroid Build Coastguard Worker setScaleY(float scaleY)321*d57664e9SAndroid Build Coastguard Worker bool setScaleY(float scaleY) { return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleY, scaleY); } 322*d57664e9SAndroid Build Coastguard Worker getScaleY()323*d57664e9SAndroid Build Coastguard Worker float getScaleY() const { return mPrimitiveFields.mScaleY; } 324*d57664e9SAndroid Build Coastguard Worker setPivotX(float pivotX)325*d57664e9SAndroid Build Coastguard Worker bool setPivotX(float pivotX) { 326*d57664e9SAndroid Build Coastguard Worker if (RP_SET(mPrimitiveFields.mPivotX, pivotX) || !mPrimitiveFields.mPivotExplicitlySet) { 327*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mMatrixOrPivotDirty = true; 328*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mPivotExplicitlySet = true; 329*d57664e9SAndroid Build Coastguard Worker return true; 330*d57664e9SAndroid Build Coastguard Worker } 331*d57664e9SAndroid Build Coastguard Worker return false; 332*d57664e9SAndroid Build Coastguard Worker } 333*d57664e9SAndroid Build Coastguard Worker 334*d57664e9SAndroid Build Coastguard Worker /* Note that getPivotX and getPivotY are adjusted by updateMatrix(), 335*d57664e9SAndroid Build Coastguard Worker * so the value returned may be stale if the RenderProperties has been 336*d57664e9SAndroid Build Coastguard Worker * modified since the last call to updateMatrix() 337*d57664e9SAndroid Build Coastguard Worker */ getPivotX()338*d57664e9SAndroid Build Coastguard Worker float getPivotX() const { return mPrimitiveFields.mPivotX; } 339*d57664e9SAndroid Build Coastguard Worker setPivotY(float pivotY)340*d57664e9SAndroid Build Coastguard Worker bool setPivotY(float pivotY) { 341*d57664e9SAndroid Build Coastguard Worker if (RP_SET(mPrimitiveFields.mPivotY, pivotY) || !mPrimitiveFields.mPivotExplicitlySet) { 342*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mMatrixOrPivotDirty = true; 343*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mPivotExplicitlySet = true; 344*d57664e9SAndroid Build Coastguard Worker return true; 345*d57664e9SAndroid Build Coastguard Worker } 346*d57664e9SAndroid Build Coastguard Worker return false; 347*d57664e9SAndroid Build Coastguard Worker } 348*d57664e9SAndroid Build Coastguard Worker getPivotY()349*d57664e9SAndroid Build Coastguard Worker float getPivotY() const { return mPrimitiveFields.mPivotY; } 350*d57664e9SAndroid Build Coastguard Worker isPivotExplicitlySet()351*d57664e9SAndroid Build Coastguard Worker bool isPivotExplicitlySet() const { return mPrimitiveFields.mPivotExplicitlySet; } 352*d57664e9SAndroid Build Coastguard Worker resetPivot()353*d57664e9SAndroid Build Coastguard Worker bool resetPivot() { return RP_SET_AND_DIRTY(mPrimitiveFields.mPivotExplicitlySet, false); } 354*d57664e9SAndroid Build Coastguard Worker setCameraDistance(float distance)355*d57664e9SAndroid Build Coastguard Worker bool setCameraDistance(float distance) { 356*d57664e9SAndroid Build Coastguard Worker if (distance != getCameraDistance()) { 357*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mMatrixOrPivotDirty = true; 358*d57664e9SAndroid Build Coastguard Worker mComputedFields.mTransformCamera.setCameraLocation(0, 0, distance); 359*d57664e9SAndroid Build Coastguard Worker return true; 360*d57664e9SAndroid Build Coastguard Worker } 361*d57664e9SAndroid Build Coastguard Worker return false; 362*d57664e9SAndroid Build Coastguard Worker } 363*d57664e9SAndroid Build Coastguard Worker getCameraDistance()364*d57664e9SAndroid Build Coastguard Worker float getCameraDistance() const { 365*d57664e9SAndroid Build Coastguard Worker // TODO: update getCameraLocationZ() to be const 366*d57664e9SAndroid Build Coastguard Worker return const_cast<Sk3DView*>(&mComputedFields.mTransformCamera)->getCameraLocationZ(); 367*d57664e9SAndroid Build Coastguard Worker } 368*d57664e9SAndroid Build Coastguard Worker setLeft(int left)369*d57664e9SAndroid Build Coastguard Worker bool setLeft(int left) { 370*d57664e9SAndroid Build Coastguard Worker if (RP_SET(mPrimitiveFields.mLeft, left)) { 371*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft; 372*d57664e9SAndroid Build Coastguard Worker if (!mPrimitiveFields.mPivotExplicitlySet) { 373*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mMatrixOrPivotDirty = true; 374*d57664e9SAndroid Build Coastguard Worker } 375*d57664e9SAndroid Build Coastguard Worker return true; 376*d57664e9SAndroid Build Coastguard Worker } 377*d57664e9SAndroid Build Coastguard Worker return false; 378*d57664e9SAndroid Build Coastguard Worker } 379*d57664e9SAndroid Build Coastguard Worker getLeft()380*d57664e9SAndroid Build Coastguard Worker int getLeft() const { return mPrimitiveFields.mLeft; } 381*d57664e9SAndroid Build Coastguard Worker setTop(int top)382*d57664e9SAndroid Build Coastguard Worker bool setTop(int top) { 383*d57664e9SAndroid Build Coastguard Worker if (RP_SET(mPrimitiveFields.mTop, top)) { 384*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop; 385*d57664e9SAndroid Build Coastguard Worker if (!mPrimitiveFields.mPivotExplicitlySet) { 386*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mMatrixOrPivotDirty = true; 387*d57664e9SAndroid Build Coastguard Worker } 388*d57664e9SAndroid Build Coastguard Worker return true; 389*d57664e9SAndroid Build Coastguard Worker } 390*d57664e9SAndroid Build Coastguard Worker return false; 391*d57664e9SAndroid Build Coastguard Worker } 392*d57664e9SAndroid Build Coastguard Worker getTop()393*d57664e9SAndroid Build Coastguard Worker int getTop() const { return mPrimitiveFields.mTop; } 394*d57664e9SAndroid Build Coastguard Worker setRight(int right)395*d57664e9SAndroid Build Coastguard Worker bool setRight(int right) { 396*d57664e9SAndroid Build Coastguard Worker if (RP_SET(mPrimitiveFields.mRight, right)) { 397*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft; 398*d57664e9SAndroid Build Coastguard Worker if (!mPrimitiveFields.mPivotExplicitlySet) { 399*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mMatrixOrPivotDirty = true; 400*d57664e9SAndroid Build Coastguard Worker } 401*d57664e9SAndroid Build Coastguard Worker return true; 402*d57664e9SAndroid Build Coastguard Worker } 403*d57664e9SAndroid Build Coastguard Worker return false; 404*d57664e9SAndroid Build Coastguard Worker } 405*d57664e9SAndroid Build Coastguard Worker getRight()406*d57664e9SAndroid Build Coastguard Worker int getRight() const { return mPrimitiveFields.mRight; } 407*d57664e9SAndroid Build Coastguard Worker setBottom(int bottom)408*d57664e9SAndroid Build Coastguard Worker bool setBottom(int bottom) { 409*d57664e9SAndroid Build Coastguard Worker if (RP_SET(mPrimitiveFields.mBottom, bottom)) { 410*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop; 411*d57664e9SAndroid Build Coastguard Worker if (!mPrimitiveFields.mPivotExplicitlySet) { 412*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mMatrixOrPivotDirty = true; 413*d57664e9SAndroid Build Coastguard Worker } 414*d57664e9SAndroid Build Coastguard Worker return true; 415*d57664e9SAndroid Build Coastguard Worker } 416*d57664e9SAndroid Build Coastguard Worker return false; 417*d57664e9SAndroid Build Coastguard Worker } 418*d57664e9SAndroid Build Coastguard Worker getBottom()419*d57664e9SAndroid Build Coastguard Worker int getBottom() const { return mPrimitiveFields.mBottom; } 420*d57664e9SAndroid Build Coastguard Worker setLeftTop(int left,int top)421*d57664e9SAndroid Build Coastguard Worker bool setLeftTop(int left, int top) { 422*d57664e9SAndroid Build Coastguard Worker bool leftResult = setLeft(left); 423*d57664e9SAndroid Build Coastguard Worker bool topResult = setTop(top); 424*d57664e9SAndroid Build Coastguard Worker return leftResult || topResult; 425*d57664e9SAndroid Build Coastguard Worker } 426*d57664e9SAndroid Build Coastguard Worker setLeftTopRightBottom(int left,int top,int right,int bottom)427*d57664e9SAndroid Build Coastguard Worker bool setLeftTopRightBottom(int left, int top, int right, int bottom) { 428*d57664e9SAndroid Build Coastguard Worker if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop || 429*d57664e9SAndroid Build Coastguard Worker right != mPrimitiveFields.mRight || bottom != mPrimitiveFields.mBottom) { 430*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mLeft = left; 431*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mTop = top; 432*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mRight = right; 433*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mBottom = bottom; 434*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft; 435*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop; 436*d57664e9SAndroid Build Coastguard Worker if (!mPrimitiveFields.mPivotExplicitlySet) { 437*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mMatrixOrPivotDirty = true; 438*d57664e9SAndroid Build Coastguard Worker } 439*d57664e9SAndroid Build Coastguard Worker return true; 440*d57664e9SAndroid Build Coastguard Worker } 441*d57664e9SAndroid Build Coastguard Worker return false; 442*d57664e9SAndroid Build Coastguard Worker } 443*d57664e9SAndroid Build Coastguard Worker offsetLeftRight(int offset)444*d57664e9SAndroid Build Coastguard Worker bool offsetLeftRight(int offset) { 445*d57664e9SAndroid Build Coastguard Worker if (offset != 0) { 446*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mLeft += offset; 447*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mRight += offset; 448*d57664e9SAndroid Build Coastguard Worker return true; 449*d57664e9SAndroid Build Coastguard Worker } 450*d57664e9SAndroid Build Coastguard Worker return false; 451*d57664e9SAndroid Build Coastguard Worker } 452*d57664e9SAndroid Build Coastguard Worker offsetTopBottom(int offset)453*d57664e9SAndroid Build Coastguard Worker bool offsetTopBottom(int offset) { 454*d57664e9SAndroid Build Coastguard Worker if (offset != 0) { 455*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mTop += offset; 456*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mBottom += offset; 457*d57664e9SAndroid Build Coastguard Worker return true; 458*d57664e9SAndroid Build Coastguard Worker } 459*d57664e9SAndroid Build Coastguard Worker return false; 460*d57664e9SAndroid Build Coastguard Worker } 461*d57664e9SAndroid Build Coastguard Worker getWidth()462*d57664e9SAndroid Build Coastguard Worker int getWidth() const { return mPrimitiveFields.mWidth; } 463*d57664e9SAndroid Build Coastguard Worker getHeight()464*d57664e9SAndroid Build Coastguard Worker int getHeight() const { return mPrimitiveFields.mHeight; } 465*d57664e9SAndroid Build Coastguard Worker getAnimationMatrix()466*d57664e9SAndroid Build Coastguard Worker const SkMatrix* getAnimationMatrix() const { return mAnimationMatrix; } 467*d57664e9SAndroid Build Coastguard Worker hasTransformMatrix()468*d57664e9SAndroid Build Coastguard Worker bool hasTransformMatrix() const { 469*d57664e9SAndroid Build Coastguard Worker return getTransformMatrix() && !getTransformMatrix()->isIdentity(); 470*d57664e9SAndroid Build Coastguard Worker } 471*d57664e9SAndroid Build Coastguard Worker 472*d57664e9SAndroid Build Coastguard Worker // May only call this if hasTransformMatrix() is true isTransformTranslateOnly()473*d57664e9SAndroid Build Coastguard Worker bool isTransformTranslateOnly() const { 474*d57664e9SAndroid Build Coastguard Worker return getTransformMatrix()->getType() == SkMatrix::kTranslate_Mask; 475*d57664e9SAndroid Build Coastguard Worker } 476*d57664e9SAndroid Build Coastguard Worker getTransformMatrix()477*d57664e9SAndroid Build Coastguard Worker const SkMatrix* getTransformMatrix() const { 478*d57664e9SAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mPrimitiveFields.mMatrixOrPivotDirty, "Cannot get a dirty matrix!"); 479*d57664e9SAndroid Build Coastguard Worker return mComputedFields.mTransformMatrix; 480*d57664e9SAndroid Build Coastguard Worker } 481*d57664e9SAndroid Build Coastguard Worker getClippingFlags()482*d57664e9SAndroid Build Coastguard Worker int getClippingFlags() const { return mPrimitiveFields.mClippingFlags; } 483*d57664e9SAndroid Build Coastguard Worker getClipToBounds()484*d57664e9SAndroid Build Coastguard Worker bool getClipToBounds() const { return mPrimitiveFields.mClippingFlags & CLIP_TO_BOUNDS; } 485*d57664e9SAndroid Build Coastguard Worker getClipBounds()486*d57664e9SAndroid Build Coastguard Worker const Rect& getClipBounds() const { return mPrimitiveFields.mClipBounds; } 487*d57664e9SAndroid Build Coastguard Worker getClippingRectForFlags(uint32_t flags,Rect * outRect)488*d57664e9SAndroid Build Coastguard Worker void getClippingRectForFlags(uint32_t flags, Rect* outRect) const { 489*d57664e9SAndroid Build Coastguard Worker if (flags & CLIP_TO_BOUNDS) { 490*d57664e9SAndroid Build Coastguard Worker outRect->set(0, 0, getWidth(), getHeight()); 491*d57664e9SAndroid Build Coastguard Worker if (flags & CLIP_TO_CLIP_BOUNDS) { 492*d57664e9SAndroid Build Coastguard Worker outRect->doIntersect(mPrimitiveFields.mClipBounds); 493*d57664e9SAndroid Build Coastguard Worker } 494*d57664e9SAndroid Build Coastguard Worker } else { 495*d57664e9SAndroid Build Coastguard Worker outRect->set(mPrimitiveFields.mClipBounds); 496*d57664e9SAndroid Build Coastguard Worker } 497*d57664e9SAndroid Build Coastguard Worker } 498*d57664e9SAndroid Build Coastguard Worker getHasOverlappingRendering()499*d57664e9SAndroid Build Coastguard Worker bool getHasOverlappingRendering() const { return mPrimitiveFields.mHasOverlappingRendering; } 500*d57664e9SAndroid Build Coastguard Worker getOutline()501*d57664e9SAndroid Build Coastguard Worker const Outline& getOutline() const { return mPrimitiveFields.mOutline; } 502*d57664e9SAndroid Build Coastguard Worker getRevealClip()503*d57664e9SAndroid Build Coastguard Worker const RevealClip& getRevealClip() const { return mPrimitiveFields.mRevealClip; } 504*d57664e9SAndroid Build Coastguard Worker getProjectBackwards()505*d57664e9SAndroid Build Coastguard Worker bool getProjectBackwards() const { return mPrimitiveFields.mProjectBackwards; } 506*d57664e9SAndroid Build Coastguard Worker 507*d57664e9SAndroid Build Coastguard Worker void debugOutputProperties(std::ostream& output, const int level) const; 508*d57664e9SAndroid Build Coastguard Worker 509*d57664e9SAndroid Build Coastguard Worker void updateMatrix(); 510*d57664e9SAndroid Build Coastguard Worker mutableOutline()511*d57664e9SAndroid Build Coastguard Worker Outline& mutableOutline() { return mPrimitiveFields.mOutline; } 512*d57664e9SAndroid Build Coastguard Worker mutableRevealClip()513*d57664e9SAndroid Build Coastguard Worker RevealClip& mutableRevealClip() { return mPrimitiveFields.mRevealClip; } 514*d57664e9SAndroid Build Coastguard Worker layerProperties()515*d57664e9SAndroid Build Coastguard Worker const LayerProperties& layerProperties() const { return mLayerProperties; } 516*d57664e9SAndroid Build Coastguard Worker mutateLayerProperties()517*d57664e9SAndroid Build Coastguard Worker LayerProperties& mutateLayerProperties() { return mLayerProperties; } 518*d57664e9SAndroid Build Coastguard Worker 519*d57664e9SAndroid Build Coastguard Worker // Returns true if damage calculations should be clipped to bounds 520*d57664e9SAndroid Build Coastguard Worker // TODO: Figure out something better for getZ(), as children should still be 521*d57664e9SAndroid Build Coastguard Worker // clipped to this RP's bounds. But as we will damage -INT_MAX to INT_MAX 522*d57664e9SAndroid Build Coastguard Worker // for this RP's getZ() anyway, this can be optimized when we have a 523*d57664e9SAndroid Build Coastguard Worker // Z damage estimate instead of INT_MAX getClipDamageToBounds()524*d57664e9SAndroid Build Coastguard Worker bool getClipDamageToBounds() const { 525*d57664e9SAndroid Build Coastguard Worker return getClipToBounds() && (getZ() <= 0 || getOutline().isEmpty()); 526*d57664e9SAndroid Build Coastguard Worker } 527*d57664e9SAndroid Build Coastguard Worker hasShadow()528*d57664e9SAndroid Build Coastguard Worker bool hasShadow() const { 529*d57664e9SAndroid Build Coastguard Worker return getZ() > 0.0f && getOutline().getPath() != nullptr && 530*d57664e9SAndroid Build Coastguard Worker getOutline().getAlpha() != 0.0f; 531*d57664e9SAndroid Build Coastguard Worker } 532*d57664e9SAndroid Build Coastguard Worker getSpotShadowColor()533*d57664e9SAndroid Build Coastguard Worker SkColor getSpotShadowColor() const { return mPrimitiveFields.mSpotShadowColor; } 534*d57664e9SAndroid Build Coastguard Worker setSpotShadowColor(SkColor shadowColor)535*d57664e9SAndroid Build Coastguard Worker bool setSpotShadowColor(SkColor shadowColor) { 536*d57664e9SAndroid Build Coastguard Worker return RP_SET(mPrimitiveFields.mSpotShadowColor, shadowColor); 537*d57664e9SAndroid Build Coastguard Worker } 538*d57664e9SAndroid Build Coastguard Worker getAmbientShadowColor()539*d57664e9SAndroid Build Coastguard Worker SkColor getAmbientShadowColor() const { return mPrimitiveFields.mAmbientShadowColor; } 540*d57664e9SAndroid Build Coastguard Worker setAmbientShadowColor(SkColor shadowColor)541*d57664e9SAndroid Build Coastguard Worker bool setAmbientShadowColor(SkColor shadowColor) { 542*d57664e9SAndroid Build Coastguard Worker return RP_SET(mPrimitiveFields.mAmbientShadowColor, shadowColor); 543*d57664e9SAndroid Build Coastguard Worker } 544*d57664e9SAndroid Build Coastguard Worker fitsOnLayer()545*d57664e9SAndroid Build Coastguard Worker bool fitsOnLayer() const { 546*d57664e9SAndroid Build Coastguard Worker const DeviceInfo* deviceInfo = DeviceInfo::get(); 547*d57664e9SAndroid Build Coastguard Worker return mPrimitiveFields.mWidth <= deviceInfo->maxTextureSize() && 548*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mHeight <= deviceInfo->maxTextureSize() && 549*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mWidth > 0 && mPrimitiveFields.mHeight > 0; 550*d57664e9SAndroid Build Coastguard Worker } 551*d57664e9SAndroid Build Coastguard Worker promotedToLayer()552*d57664e9SAndroid Build Coastguard Worker bool promotedToLayer() const { 553*d57664e9SAndroid Build Coastguard Worker return mLayerProperties.mType == LayerType::None && fitsOnLayer() && 554*d57664e9SAndroid Build Coastguard Worker (mComputedFields.mNeedLayerForFunctors || mLayerProperties.mImageFilter != nullptr || 555*d57664e9SAndroid Build Coastguard Worker mLayerProperties.getStretchEffect().requiresLayer() || 556*d57664e9SAndroid Build Coastguard Worker (!MathUtils::isZero(mPrimitiveFields.mAlpha) && mPrimitiveFields.mAlpha < 1 && 557*d57664e9SAndroid Build Coastguard Worker mPrimitiveFields.mHasOverlappingRendering)); 558*d57664e9SAndroid Build Coastguard Worker } 559*d57664e9SAndroid Build Coastguard Worker effectiveLayerType()560*d57664e9SAndroid Build Coastguard Worker LayerType effectiveLayerType() const { 561*d57664e9SAndroid Build Coastguard Worker return CC_UNLIKELY(promotedToLayer()) ? LayerType::RenderLayer : mLayerProperties.mType; 562*d57664e9SAndroid Build Coastguard Worker } 563*d57664e9SAndroid Build Coastguard Worker setAllowForceDark(bool allow)564*d57664e9SAndroid Build Coastguard Worker bool setAllowForceDark(bool allow) { 565*d57664e9SAndroid Build Coastguard Worker return RP_SET(mPrimitiveFields.mAllowForceDark, allow); 566*d57664e9SAndroid Build Coastguard Worker } 567*d57664e9SAndroid Build Coastguard Worker getAllowForceDark()568*d57664e9SAndroid Build Coastguard Worker bool getAllowForceDark() const { 569*d57664e9SAndroid Build Coastguard Worker return mPrimitiveFields.mAllowForceDark; 570*d57664e9SAndroid Build Coastguard Worker } 571*d57664e9SAndroid Build Coastguard Worker 572*d57664e9SAndroid Build Coastguard Worker private: 573*d57664e9SAndroid Build Coastguard Worker // Rendering properties 574*d57664e9SAndroid Build Coastguard Worker struct PrimitiveFields { 575*d57664e9SAndroid Build Coastguard Worker int mLeft = 0, mTop = 0, mRight = 0, mBottom = 0; 576*d57664e9SAndroid Build Coastguard Worker int mWidth = 0, mHeight = 0; 577*d57664e9SAndroid Build Coastguard Worker int mClippingFlags = CLIP_TO_BOUNDS; 578*d57664e9SAndroid Build Coastguard Worker SkColor mSpotShadowColor = SK_ColorBLACK; 579*d57664e9SAndroid Build Coastguard Worker SkColor mAmbientShadowColor = SK_ColorBLACK; 580*d57664e9SAndroid Build Coastguard Worker float mAlpha = 1; 581*d57664e9SAndroid Build Coastguard Worker float mTranslationX = 0, mTranslationY = 0, mTranslationZ = 0; 582*d57664e9SAndroid Build Coastguard Worker float mElevation = 0; 583*d57664e9SAndroid Build Coastguard Worker float mRotation = 0, mRotationX = 0, mRotationY = 0; 584*d57664e9SAndroid Build Coastguard Worker float mScaleX = 1, mScaleY = 1; 585*d57664e9SAndroid Build Coastguard Worker float mPivotX = 0, mPivotY = 0; 586*d57664e9SAndroid Build Coastguard Worker bool mHasOverlappingRendering = false; 587*d57664e9SAndroid Build Coastguard Worker bool mPivotExplicitlySet = false; 588*d57664e9SAndroid Build Coastguard Worker bool mMatrixOrPivotDirty = false; 589*d57664e9SAndroid Build Coastguard Worker bool mProjectBackwards = false; 590*d57664e9SAndroid Build Coastguard Worker bool mProjectionReceiver = false; 591*d57664e9SAndroid Build Coastguard Worker bool mAllowForceDark = true; 592*d57664e9SAndroid Build Coastguard Worker bool mClipMayBeComplex = false; 593*d57664e9SAndroid Build Coastguard Worker Rect mClipBounds; 594*d57664e9SAndroid Build Coastguard Worker Outline mOutline; 595*d57664e9SAndroid Build Coastguard Worker RevealClip mRevealClip; 596*d57664e9SAndroid Build Coastguard Worker } mPrimitiveFields; 597*d57664e9SAndroid Build Coastguard Worker 598*d57664e9SAndroid Build Coastguard Worker SkMatrix* mStaticMatrix; 599*d57664e9SAndroid Build Coastguard Worker SkMatrix* mAnimationMatrix; 600*d57664e9SAndroid Build Coastguard Worker LayerProperties mLayerProperties; 601*d57664e9SAndroid Build Coastguard Worker 602*d57664e9SAndroid Build Coastguard Worker /** 603*d57664e9SAndroid Build Coastguard Worker * These fields are all generated from other properties and are not set directly. 604*d57664e9SAndroid Build Coastguard Worker */ 605*d57664e9SAndroid Build Coastguard Worker struct ComputedFields { 606*d57664e9SAndroid Build Coastguard Worker ComputedFields(); 607*d57664e9SAndroid Build Coastguard Worker ~ComputedFields(); 608*d57664e9SAndroid Build Coastguard Worker 609*d57664e9SAndroid Build Coastguard Worker /** 610*d57664e9SAndroid Build Coastguard Worker * Stores the total transformation of the DisplayList based upon its scalar 611*d57664e9SAndroid Build Coastguard Worker * translate/rotate/scale properties. 612*d57664e9SAndroid Build Coastguard Worker * 613*d57664e9SAndroid Build Coastguard Worker * In the common translation-only case, the matrix isn't necessarily allocated, 614*d57664e9SAndroid Build Coastguard Worker * and the mTranslation properties are used directly. 615*d57664e9SAndroid Build Coastguard Worker */ 616*d57664e9SAndroid Build Coastguard Worker SkMatrix* mTransformMatrix; 617*d57664e9SAndroid Build Coastguard Worker 618*d57664e9SAndroid Build Coastguard Worker Sk3DView mTransformCamera; 619*d57664e9SAndroid Build Coastguard Worker 620*d57664e9SAndroid Build Coastguard Worker // Force layer on for functors to enable render features they don't yet support (clipping) 621*d57664e9SAndroid Build Coastguard Worker bool mNeedLayerForFunctors = false; 622*d57664e9SAndroid Build Coastguard Worker } mComputedFields; 623*d57664e9SAndroid Build Coastguard Worker }; 624*d57664e9SAndroid Build Coastguard Worker 625*d57664e9SAndroid Build Coastguard Worker } /* namespace uirenderer */ 626*d57664e9SAndroid Build Coastguard Worker } /* namespace android */ 627