blob: 65c1c4a17412304dac28bb04bc95f21e12aeaf19 [file] [log] [blame]
John Reckacb6f072014-03-12 16:11:23 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Chris Craikb49f4462014-03-20 12:44:20 -070016#ifndef RENDERNODEPROPERTIES_H
17#define RENDERNODEPROPERTIES_H
John Reckacb6f072014-03-12 16:11:23 -070018
John Recke45b1fd2014-04-15 09:50:16 -070019#include <algorithm>
John Reckacb6f072014-03-12 16:11:23 -070020#include <stddef.h>
John Recke45b1fd2014-04-15 09:50:16 -070021#include <vector>
John Reckacb6f072014-03-12 16:11:23 -070022#include <cutils/compiler.h>
23#include <androidfw/ResourceTypes.h>
Chris Craikfe02b4b2014-06-16 16:34:29 -070024#include <utils/Log.h>
John Reckacb6f072014-03-12 16:11:23 -070025
26#include <SkCamera.h>
27#include <SkMatrix.h>
Chris Craik8c271ca2014-03-25 10:33:01 -070028#include <SkRegion.h>
Tom Hudson2dc236b2014-10-15 15:46:42 -040029#include <SkXfermode.h>
Chris Craikb49f4462014-03-20 12:44:20 -070030
Chris Craik4e9d9b22015-06-12 11:07:23 -070031#include "Caches.h"
Chris Craikb49f4462014-03-20 12:44:20 -070032#include "Rect.h"
Chris Craik8c271ca2014-03-25 10:33:01 -070033#include "RevealClip.h"
Chris Craikb49f4462014-03-20 12:44:20 -070034#include "Outline.h"
John Reck293e8682014-06-17 10:34:02 -070035#include "utils/MathUtils.h"
John Reckacb6f072014-03-12 16:11:23 -070036
John Reckacb6f072014-03-12 16:11:23 -070037class SkBitmap;
John Reck25fbb3f2014-06-12 13:46:45 -070038class SkColorFilter;
John Reckacb6f072014-03-12 16:11:23 -070039class SkPaint;
John Reckacb6f072014-03-12 16:11:23 -070040
41namespace android {
42namespace uirenderer {
43
44class Matrix4;
45class RenderNode;
John Reck25fbb3f2014-06-12 13:46:45 -070046class RenderProperties;
John Reckacb6f072014-03-12 16:11:23 -070047
John Reck79c7de72014-05-23 10:33:31 -070048// The __VA_ARGS__ will be executed if a & b are not equal
49#define RP_SET(a, b, ...) (a != b ? (a = b, ##__VA_ARGS__, true) : false)
50#define RP_SET_AND_DIRTY(a, b) RP_SET(a, b, mPrimitiveFields.mMatrixOrPivotDirty = true)
51
John Reck25fbb3f2014-06-12 13:46:45 -070052// Keep in sync with View.java:LAYER_TYPE_*
Chris Craik182952f2015-03-09 14:17:29 -070053enum class LayerType {
54 None = 0,
John Reck25fbb3f2014-06-12 13:46:45 -070055 // Although we cannot build the software layer directly (must be done at
56 // record time), this information is used when applying alpha.
Chris Craik182952f2015-03-09 14:17:29 -070057 Software = 1,
58 RenderLayer = 2,
John Reck25fbb3f2014-06-12 13:46:45 -070059 // TODO: LayerTypeSurfaceTexture? Maybe?
60};
61
Chris Craika753f4c2014-07-24 12:39:17 -070062enum ClippingFlags {
63 CLIP_TO_BOUNDS = 0x1 << 0,
64 CLIP_TO_CLIP_BOUNDS = 0x1 << 1,
65};
66
John Reck25fbb3f2014-06-12 13:46:45 -070067class ANDROID_API LayerProperties {
68public:
69 bool setType(LayerType type) {
70 if (RP_SET(mType, type)) {
71 reset();
72 return true;
73 }
74 return false;
75 }
76
John Reck25fbb3f2014-06-12 13:46:45 -070077 bool setOpaque(bool opaque) {
78 return RP_SET(mOpaque, opaque);
79 }
80
81 bool opaque() const {
82 return mOpaque;
83 }
84
85 bool setAlpha(uint8_t alpha) {
86 return RP_SET(mAlpha, alpha);
87 }
88
89 uint8_t alpha() const {
90 return mAlpha;
91 }
92
93 bool setXferMode(SkXfermode::Mode mode) {
94 return RP_SET(mMode, mode);
95 }
96
97 SkXfermode::Mode xferMode() const {
98 return mMode;
99 }
100
101 bool setColorFilter(SkColorFilter* filter);
102
103 SkColorFilter* colorFilter() const {
104 return mColorFilter;
105 }
106
107 // Sets alpha, xfermode, and colorfilter from an SkPaint
108 // paint may be NULL, in which case defaults will be set
109 bool setFromPaint(const SkPaint* paint);
110
111 bool needsBlending() const {
112 return !opaque() || alpha() < 255;
113 }
114
115 LayerProperties& operator=(const LayerProperties& other);
116
117private:
118 LayerProperties();
119 ~LayerProperties();
120 void reset();
121
Chris Craik856f0cc2015-04-21 15:13:29 -0700122 // Private since external users should go through properties().effectiveLayerType()
123 LayerType type() const {
124 return mType;
125 }
126
John Reck25fbb3f2014-06-12 13:46:45 -0700127 friend class RenderProperties;
128
Chris Craik182952f2015-03-09 14:17:29 -0700129 LayerType mType = LayerType::None;
John Reck25fbb3f2014-06-12 13:46:45 -0700130 // Whether or not that Layer's content is opaque, doesn't include alpha
131 bool mOpaque;
132 uint8_t mAlpha;
133 SkXfermode::Mode mMode;
Chris Craik182952f2015-03-09 14:17:29 -0700134 SkColorFilter* mColorFilter = nullptr;
John Reck25fbb3f2014-06-12 13:46:45 -0700135};
136
John Reckacb6f072014-03-12 16:11:23 -0700137/*
138 * Data structure that holds the properties for a RenderNode
139 */
John Reck25fbb3f2014-06-12 13:46:45 -0700140class ANDROID_API RenderProperties {
John Reckacb6f072014-03-12 16:11:23 -0700141public:
142 RenderProperties();
143 virtual ~RenderProperties();
144
Chris Craika753f4c2014-07-24 12:39:17 -0700145 static bool setFlag(int flag, bool newValue, int* outFlags) {
146 if (newValue) {
147 if (!(flag & *outFlags)) {
148 *outFlags |= flag;
149 return true;
150 }
151 return false;
152 } else {
153 if (flag & *outFlags) {
154 *outFlags &= ~flag;
155 return true;
156 }
157 return false;
158 }
159 }
160
John Reckd0a0b2a2014-03-20 16:28:56 -0700161 RenderProperties& operator=(const RenderProperties& other);
162
John Reck79c7de72014-05-23 10:33:31 -0700163 bool setClipToBounds(bool clipToBounds) {
Chris Craika753f4c2014-07-24 12:39:17 -0700164 return setFlag(CLIP_TO_BOUNDS, clipToBounds, &mPrimitiveFields.mClippingFlags);
165 }
166
167 bool setClipBounds(const Rect& clipBounds) {
168 bool ret = setFlag(CLIP_TO_CLIP_BOUNDS, true, &mPrimitiveFields.mClippingFlags);
169 return RP_SET(mPrimitiveFields.mClipBounds, clipBounds) || ret;
170 }
171
172 bool setClipBoundsEmpty() {
173 return setFlag(CLIP_TO_CLIP_BOUNDS, false, &mPrimitiveFields.mClippingFlags);
John Reckacb6f072014-03-12 16:11:23 -0700174 }
175
John Reck79c7de72014-05-23 10:33:31 -0700176 bool setProjectBackwards(bool shouldProject) {
177 return RP_SET(mPrimitiveFields.mProjectBackwards, shouldProject);
John Reckacb6f072014-03-12 16:11:23 -0700178 }
179
John Reck79c7de72014-05-23 10:33:31 -0700180 bool setProjectionReceiver(bool shouldRecieve) {
181 return RP_SET(mPrimitiveFields.mProjectionReceiver, shouldRecieve);
John Reckacb6f072014-03-12 16:11:23 -0700182 }
183
John Reckd0a0b2a2014-03-20 16:28:56 -0700184 bool isProjectionReceiver() const {
185 return mPrimitiveFields.mProjectionReceiver;
John Reckacb6f072014-03-12 16:11:23 -0700186 }
187
John Reck79c7de72014-05-23 10:33:31 -0700188 bool setStaticMatrix(const SkMatrix* matrix) {
John Reckacb6f072014-03-12 16:11:23 -0700189 delete mStaticMatrix;
John Reckd0a0b2a2014-03-20 16:28:56 -0700190 if (matrix) {
191 mStaticMatrix = new SkMatrix(*matrix);
192 } else {
Chris Craike84a2082014-12-22 14:28:49 -0800193 mStaticMatrix = nullptr;
John Reckd0a0b2a2014-03-20 16:28:56 -0700194 }
John Reck79c7de72014-05-23 10:33:31 -0700195 return true;
John Reckacb6f072014-03-12 16:11:23 -0700196 }
197
198 // Can return NULL
John Reckd0a0b2a2014-03-20 16:28:56 -0700199 const SkMatrix* getStaticMatrix() const {
John Reckacb6f072014-03-12 16:11:23 -0700200 return mStaticMatrix;
201 }
202
John Reck79c7de72014-05-23 10:33:31 -0700203 bool setAnimationMatrix(const SkMatrix* matrix) {
John Reckacb6f072014-03-12 16:11:23 -0700204 delete mAnimationMatrix;
205 if (matrix) {
206 mAnimationMatrix = new SkMatrix(*matrix);
207 } else {
Chris Craike84a2082014-12-22 14:28:49 -0800208 mAnimationMatrix = nullptr;
John Reckacb6f072014-03-12 16:11:23 -0700209 }
John Reck79c7de72014-05-23 10:33:31 -0700210 return true;
John Reckacb6f072014-03-12 16:11:23 -0700211 }
212
John Reck79c7de72014-05-23 10:33:31 -0700213 bool setAlpha(float alpha) {
John Reck3b52c032014-08-06 10:19:32 -0700214 alpha = MathUtils::clampAlpha(alpha);
John Reck79c7de72014-05-23 10:33:31 -0700215 return RP_SET(mPrimitiveFields.mAlpha, alpha);
John Reckacb6f072014-03-12 16:11:23 -0700216 }
217
218 float getAlpha() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700219 return mPrimitiveFields.mAlpha;
John Reckacb6f072014-03-12 16:11:23 -0700220 }
221
John Reck79c7de72014-05-23 10:33:31 -0700222 bool setHasOverlappingRendering(bool hasOverlappingRendering) {
223 return RP_SET(mPrimitiveFields.mHasOverlappingRendering, hasOverlappingRendering);
John Reckacb6f072014-03-12 16:11:23 -0700224 }
225
226 bool hasOverlappingRendering() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700227 return mPrimitiveFields.mHasOverlappingRendering;
John Reckacb6f072014-03-12 16:11:23 -0700228 }
229
John Reck79c7de72014-05-23 10:33:31 -0700230 bool setElevation(float elevation) {
231 return RP_SET(mPrimitiveFields.mElevation, elevation);
232 // Don't dirty matrix/pivot, since they don't respect Z
Chris Craikcc39e162014-04-25 18:34:11 -0700233 }
234
235 float getElevation() const {
236 return mPrimitiveFields.mElevation;
237 }
238
John Reck79c7de72014-05-23 10:33:31 -0700239 bool setTranslationX(float translationX) {
240 return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationX, translationX);
John Reckacb6f072014-03-12 16:11:23 -0700241 }
242
243 float getTranslationX() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700244 return mPrimitiveFields.mTranslationX;
John Reckacb6f072014-03-12 16:11:23 -0700245 }
246
John Reck79c7de72014-05-23 10:33:31 -0700247 bool setTranslationY(float translationY) {
248 return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationY, translationY);
John Reckacb6f072014-03-12 16:11:23 -0700249 }
250
251 float getTranslationY() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700252 return mPrimitiveFields.mTranslationY;
John Reckacb6f072014-03-12 16:11:23 -0700253 }
254
John Reck79c7de72014-05-23 10:33:31 -0700255 bool setTranslationZ(float translationZ) {
256 return RP_SET(mPrimitiveFields.mTranslationZ, translationZ);
257 // mMatrixOrPivotDirty not set, since matrix doesn't respect Z
John Reckacb6f072014-03-12 16:11:23 -0700258 }
259
260 float getTranslationZ() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700261 return mPrimitiveFields.mTranslationZ;
John Reckacb6f072014-03-12 16:11:23 -0700262 }
263
John Recke45b1fd2014-04-15 09:50:16 -0700264 // Animation helper
John Reck79c7de72014-05-23 10:33:31 -0700265 bool setX(float value) {
266 return setTranslationX(value - getLeft());
John Recke45b1fd2014-04-15 09:50:16 -0700267 }
268
269 // Animation helper
270 float getX() const {
271 return getLeft() + getTranslationX();
272 }
273
274 // Animation helper
John Reck79c7de72014-05-23 10:33:31 -0700275 bool setY(float value) {
276 return setTranslationY(value - getTop());
John Recke45b1fd2014-04-15 09:50:16 -0700277 }
278
279 // Animation helper
280 float getY() const {
281 return getTop() + getTranslationY();
282 }
283
284 // Animation helper
John Reck79c7de72014-05-23 10:33:31 -0700285 bool setZ(float value) {
286 return setTranslationZ(value - getElevation());
John Recke45b1fd2014-04-15 09:50:16 -0700287 }
288
Chris Craikcc39e162014-04-25 18:34:11 -0700289 float getZ() const {
290 return getElevation() + getTranslationZ();
291 }
292
John Reck79c7de72014-05-23 10:33:31 -0700293 bool setRotation(float rotation) {
294 return RP_SET_AND_DIRTY(mPrimitiveFields.mRotation, rotation);
John Reckacb6f072014-03-12 16:11:23 -0700295 }
296
297 float getRotation() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700298 return mPrimitiveFields.mRotation;
John Reckacb6f072014-03-12 16:11:23 -0700299 }
300
John Reck79c7de72014-05-23 10:33:31 -0700301 bool setRotationX(float rotationX) {
302 return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationX, rotationX);
John Reckacb6f072014-03-12 16:11:23 -0700303 }
304
305 float getRotationX() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700306 return mPrimitiveFields.mRotationX;
John Reckacb6f072014-03-12 16:11:23 -0700307 }
308
John Reck79c7de72014-05-23 10:33:31 -0700309 bool setRotationY(float rotationY) {
310 return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationY, rotationY);
John Reckacb6f072014-03-12 16:11:23 -0700311 }
312
313 float getRotationY() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700314 return mPrimitiveFields.mRotationY;
John Reckacb6f072014-03-12 16:11:23 -0700315 }
316
John Reck79c7de72014-05-23 10:33:31 -0700317 bool setScaleX(float scaleX) {
318 return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleX, scaleX);
John Reckacb6f072014-03-12 16:11:23 -0700319 }
320
321 float getScaleX() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700322 return mPrimitiveFields.mScaleX;
John Reckacb6f072014-03-12 16:11:23 -0700323 }
324
John Reck79c7de72014-05-23 10:33:31 -0700325 bool setScaleY(float scaleY) {
326 return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleY, scaleY);
John Reckacb6f072014-03-12 16:11:23 -0700327 }
328
329 float getScaleY() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700330 return mPrimitiveFields.mScaleY;
John Reckacb6f072014-03-12 16:11:23 -0700331 }
332
John Reck79c7de72014-05-23 10:33:31 -0700333 bool setPivotX(float pivotX) {
334 if (RP_SET(mPrimitiveFields.mPivotX, pivotX)
335 || !mPrimitiveFields.mPivotExplicitlySet) {
336 mPrimitiveFields.mMatrixOrPivotDirty = true;
337 mPrimitiveFields.mPivotExplicitlySet = true;
338 return true;
339 }
340 return false;
John Reckacb6f072014-03-12 16:11:23 -0700341 }
342
John Reckd0a0b2a2014-03-20 16:28:56 -0700343 /* Note that getPivotX and getPivotY are adjusted by updateMatrix(),
John Reck79c7de72014-05-23 10:33:31 -0700344 * so the value returned may be stale if the RenderProperties has been
345 * modified since the last call to updateMatrix()
John Reckd0a0b2a2014-03-20 16:28:56 -0700346 */
347 float getPivotX() const {
348 return mPrimitiveFields.mPivotX;
349 }
John Reckacb6f072014-03-12 16:11:23 -0700350
John Reck79c7de72014-05-23 10:33:31 -0700351 bool setPivotY(float pivotY) {
352 if (RP_SET(mPrimitiveFields.mPivotY, pivotY)
353 || !mPrimitiveFields.mPivotExplicitlySet) {
354 mPrimitiveFields.mMatrixOrPivotDirty = true;
355 mPrimitiveFields.mPivotExplicitlySet = true;
356 return true;
357 }
358 return false;
John Reckacb6f072014-03-12 16:11:23 -0700359 }
360
John Reckd0a0b2a2014-03-20 16:28:56 -0700361 float getPivotY() const {
362 return mPrimitiveFields.mPivotY;
363 }
John Reckacb6f072014-03-12 16:11:23 -0700364
Chris Craik49e6c7392014-03-31 12:34:11 -0700365 bool isPivotExplicitlySet() const {
366 return mPrimitiveFields.mPivotExplicitlySet;
367 }
368
John Reck79c7de72014-05-23 10:33:31 -0700369 bool setCameraDistance(float distance) {
Chris Craik49e6c7392014-03-31 12:34:11 -0700370 if (distance != getCameraDistance()) {
John Reckf7483e32014-04-11 08:54:47 -0700371 mPrimitiveFields.mMatrixOrPivotDirty = true;
Chris Craik49e6c7392014-03-31 12:34:11 -0700372 mComputedFields.mTransformCamera.setCameraLocation(0, 0, distance);
John Reck79c7de72014-05-23 10:33:31 -0700373 return true;
John Reckacb6f072014-03-12 16:11:23 -0700374 }
John Reck79c7de72014-05-23 10:33:31 -0700375 return false;
John Reckacb6f072014-03-12 16:11:23 -0700376 }
377
378 float getCameraDistance() const {
Chris Craik49e6c7392014-03-31 12:34:11 -0700379 // TODO: update getCameraLocationZ() to be const
380 return const_cast<Sk3DView*>(&mComputedFields.mTransformCamera)->getCameraLocationZ();
John Reckacb6f072014-03-12 16:11:23 -0700381 }
382
John Reck79c7de72014-05-23 10:33:31 -0700383 bool setLeft(int left) {
384 if (RP_SET(mPrimitiveFields.mLeft, left)) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700385 mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
John Reckf7483e32014-04-11 08:54:47 -0700386 if (!mPrimitiveFields.mPivotExplicitlySet) {
387 mPrimitiveFields.mMatrixOrPivotDirty = true;
John Reckacb6f072014-03-12 16:11:23 -0700388 }
John Reck79c7de72014-05-23 10:33:31 -0700389 return true;
John Reckacb6f072014-03-12 16:11:23 -0700390 }
John Reck79c7de72014-05-23 10:33:31 -0700391 return false;
John Reckacb6f072014-03-12 16:11:23 -0700392 }
393
394 float getLeft() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700395 return mPrimitiveFields.mLeft;
John Reckacb6f072014-03-12 16:11:23 -0700396 }
397
John Reck79c7de72014-05-23 10:33:31 -0700398 bool setTop(int top) {
399 if (RP_SET(mPrimitiveFields.mTop, top)) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700400 mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
John Reckf7483e32014-04-11 08:54:47 -0700401 if (!mPrimitiveFields.mPivotExplicitlySet) {
402 mPrimitiveFields.mMatrixOrPivotDirty = true;
John Reckacb6f072014-03-12 16:11:23 -0700403 }
John Reck79c7de72014-05-23 10:33:31 -0700404 return true;
John Reckacb6f072014-03-12 16:11:23 -0700405 }
John Reck79c7de72014-05-23 10:33:31 -0700406 return false;
John Reckacb6f072014-03-12 16:11:23 -0700407 }
408
409 float getTop() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700410 return mPrimitiveFields.mTop;
John Reckacb6f072014-03-12 16:11:23 -0700411 }
412
John Reck79c7de72014-05-23 10:33:31 -0700413 bool setRight(int right) {
414 if (RP_SET(mPrimitiveFields.mRight, right)) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700415 mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
John Reckf7483e32014-04-11 08:54:47 -0700416 if (!mPrimitiveFields.mPivotExplicitlySet) {
417 mPrimitiveFields.mMatrixOrPivotDirty = true;
John Reckacb6f072014-03-12 16:11:23 -0700418 }
John Reck79c7de72014-05-23 10:33:31 -0700419 return true;
John Reckacb6f072014-03-12 16:11:23 -0700420 }
John Reck79c7de72014-05-23 10:33:31 -0700421 return false;
John Reckacb6f072014-03-12 16:11:23 -0700422 }
423
424 float getRight() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700425 return mPrimitiveFields.mRight;
John Reckacb6f072014-03-12 16:11:23 -0700426 }
427
John Reck79c7de72014-05-23 10:33:31 -0700428 bool setBottom(int bottom) {
429 if (RP_SET(mPrimitiveFields.mBottom, bottom)) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700430 mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
John Reckf7483e32014-04-11 08:54:47 -0700431 if (!mPrimitiveFields.mPivotExplicitlySet) {
432 mPrimitiveFields.mMatrixOrPivotDirty = true;
John Reckacb6f072014-03-12 16:11:23 -0700433 }
John Reck79c7de72014-05-23 10:33:31 -0700434 return true;
John Reckacb6f072014-03-12 16:11:23 -0700435 }
John Reck79c7de72014-05-23 10:33:31 -0700436 return false;
John Reckacb6f072014-03-12 16:11:23 -0700437 }
438
439 float getBottom() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700440 return mPrimitiveFields.mBottom;
John Reckacb6f072014-03-12 16:11:23 -0700441 }
442
John Reck79c7de72014-05-23 10:33:31 -0700443 bool setLeftTop(int left, int top) {
444 bool leftResult = setLeft(left);
445 bool topResult = setTop(top);
446 return leftResult || topResult;
John Reckacb6f072014-03-12 16:11:23 -0700447 }
448
John Reck79c7de72014-05-23 10:33:31 -0700449 bool setLeftTopRightBottom(int left, int top, int right, int bottom) {
Chris Craikcc39e162014-04-25 18:34:11 -0700450 if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop
451 || right != mPrimitiveFields.mRight || bottom != mPrimitiveFields.mBottom) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700452 mPrimitiveFields.mLeft = left;
453 mPrimitiveFields.mTop = top;
454 mPrimitiveFields.mRight = right;
455 mPrimitiveFields.mBottom = bottom;
456 mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
457 mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
John Reckf7483e32014-04-11 08:54:47 -0700458 if (!mPrimitiveFields.mPivotExplicitlySet) {
459 mPrimitiveFields.mMatrixOrPivotDirty = true;
John Reckacb6f072014-03-12 16:11:23 -0700460 }
John Reck79c7de72014-05-23 10:33:31 -0700461 return true;
John Reckacb6f072014-03-12 16:11:23 -0700462 }
John Reck79c7de72014-05-23 10:33:31 -0700463 return false;
John Reckacb6f072014-03-12 16:11:23 -0700464 }
465
Chris Craika753f4c2014-07-24 12:39:17 -0700466 bool offsetLeftRight(int offset) {
John Reckacb6f072014-03-12 16:11:23 -0700467 if (offset != 0) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700468 mPrimitiveFields.mLeft += offset;
469 mPrimitiveFields.mRight += offset;
John Reck79c7de72014-05-23 10:33:31 -0700470 return true;
John Reckacb6f072014-03-12 16:11:23 -0700471 }
John Reck79c7de72014-05-23 10:33:31 -0700472 return false;
John Reckacb6f072014-03-12 16:11:23 -0700473 }
474
Chris Craika753f4c2014-07-24 12:39:17 -0700475 bool offsetTopBottom(int offset) {
John Reckacb6f072014-03-12 16:11:23 -0700476 if (offset != 0) {
John Reckd0a0b2a2014-03-20 16:28:56 -0700477 mPrimitiveFields.mTop += offset;
478 mPrimitiveFields.mBottom += offset;
John Reck79c7de72014-05-23 10:33:31 -0700479 return true;
John Reckacb6f072014-03-12 16:11:23 -0700480 }
John Reck79c7de72014-05-23 10:33:31 -0700481 return false;
John Reckacb6f072014-03-12 16:11:23 -0700482 }
483
Chris Craikb49f4462014-03-20 12:44:20 -0700484 int getWidth() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700485 return mPrimitiveFields.mWidth;
John Reckacb6f072014-03-12 16:11:23 -0700486 }
487
Chris Craikb49f4462014-03-20 12:44:20 -0700488 int getHeight() const {
John Reckd0a0b2a2014-03-20 16:28:56 -0700489 return mPrimitiveFields.mHeight;
John Reckacb6f072014-03-12 16:11:23 -0700490 }
491
John Reckd0a0b2a2014-03-20 16:28:56 -0700492 const SkMatrix* getAnimationMatrix() const {
493 return mAnimationMatrix;
494 }
495
John Reckf7483e32014-04-11 08:54:47 -0700496 bool hasTransformMatrix() const {
497 return getTransformMatrix() && !getTransformMatrix()->isIdentity();
498 }
499
500 // May only call this if hasTransformMatrix() is true
501 bool isTransformTranslateOnly() const {
502 return getTransformMatrix()->getType() == SkMatrix::kTranslate_Mask;
John Reckd0a0b2a2014-03-20 16:28:56 -0700503 }
504
Chris Craik49e6c7392014-03-31 12:34:11 -0700505 const SkMatrix* getTransformMatrix() const {
John Reckf7483e32014-04-11 08:54:47 -0700506 LOG_ALWAYS_FATAL_IF(mPrimitiveFields.mMatrixOrPivotDirty, "Cannot get a dirty matrix!");
John Reckd0a0b2a2014-03-20 16:28:56 -0700507 return mComputedFields.mTransformMatrix;
508 }
509
Chris Craika753f4c2014-07-24 12:39:17 -0700510 int getClippingFlags() const {
511 return mPrimitiveFields.mClippingFlags;
512 }
513
John Reckd0a0b2a2014-03-20 16:28:56 -0700514 bool getClipToBounds() const {
Chris Craika753f4c2014-07-24 12:39:17 -0700515 return mPrimitiveFields.mClippingFlags & CLIP_TO_BOUNDS;
516 }
517
518 void getClippingRectForFlags(uint32_t flags, Rect* outRect) const {
519 if (flags & CLIP_TO_BOUNDS) {
520 outRect->set(0, 0, getWidth(), getHeight());
521 if (flags & CLIP_TO_CLIP_BOUNDS) {
522 outRect->intersect(mPrimitiveFields.mClipBounds);
523 }
524 } else {
525 outRect->set(mPrimitiveFields.mClipBounds);
526 }
John Reckd0a0b2a2014-03-20 16:28:56 -0700527 }
528
529 bool getHasOverlappingRendering() const {
530 return mPrimitiveFields.mHasOverlappingRendering;
531 }
532
533 const Outline& getOutline() const {
534 return mPrimitiveFields.mOutline;
535 }
536
Chris Craik8c271ca2014-03-25 10:33:01 -0700537 const RevealClip& getRevealClip() const {
538 return mPrimitiveFields.mRevealClip;
539 }
540
John Reckd0a0b2a2014-03-20 16:28:56 -0700541 bool getProjectBackwards() const {
542 return mPrimitiveFields.mProjectBackwards;
543 }
544
545 void debugOutputProperties(const int level) const;
546
John Reck25fbb3f2014-06-12 13:46:45 -0700547 void updateMatrix();
John Reckd0a0b2a2014-03-20 16:28:56 -0700548
549 Outline& mutableOutline() {
550 return mPrimitiveFields.mOutline;
Chris Craikb49f4462014-03-20 12:44:20 -0700551 }
552
Chris Craik8c271ca2014-03-25 10:33:01 -0700553 RevealClip& mutableRevealClip() {
554 return mPrimitiveFields.mRevealClip;
555 }
556
John Reck25fbb3f2014-06-12 13:46:45 -0700557 const LayerProperties& layerProperties() const {
558 return mLayerProperties;
559 }
560
561 LayerProperties& mutateLayerProperties() {
562 return mLayerProperties;
563 }
564
John Reck293e8682014-06-17 10:34:02 -0700565 // Returns true if damage calculations should be clipped to bounds
566 // TODO: Figure out something better for getZ(), as children should still be
567 // clipped to this RP's bounds. But as we will damage -INT_MAX to INT_MAX
568 // for this RP's getZ() anyway, this can be optimized when we have a
569 // Z damage estimate instead of INT_MAX
570 bool getClipDamageToBounds() const {
571 return getClipToBounds() && (getZ() <= 0 || getOutline().isEmpty());
572 }
573
Chris Craik5c75c522014-09-05 14:08:08 -0700574 bool hasShadow() const {
Chris Craikb5a54352014-11-21 14:54:35 -0800575 return getZ() > 0.0f
Chris Craike84a2082014-12-22 14:28:49 -0800576 && getOutline().getPath() != nullptr
Chris Craik9fa364d2014-09-19 16:04:45 -0700577 && getOutline().getAlpha() != 0.0f;
Chris Craik5c75c522014-09-05 14:08:08 -0700578 }
579
Chris Craik1a0808e2015-05-13 16:33:04 -0700580 bool promotedToLayer() const {
Chris Craik4e9d9b22015-06-12 11:07:23 -0700581 const int maxTextureSize = Caches::getInstance().maxTextureSize;
Chris Craik1a0808e2015-05-13 16:33:04 -0700582 return mLayerProperties.mType == LayerType::None
Chris Craik856f0cc2015-04-21 15:13:29 -0700583 && !MathUtils::isZero(mPrimitiveFields.mAlpha)
584 && mPrimitiveFields.mAlpha < 1
Chris Craik4e9d9b22015-06-12 11:07:23 -0700585 && mPrimitiveFields.mHasOverlappingRendering
586 && mPrimitiveFields.mWidth <= maxTextureSize
587 && mPrimitiveFields.mHeight <= maxTextureSize;
Chris Craik1a0808e2015-05-13 16:33:04 -0700588 }
589
590 LayerType effectiveLayerType() const {
591 return promotedToLayer() ? LayerType::RenderLayer : mLayerProperties.mType;
Chris Craik856f0cc2015-04-21 15:13:29 -0700592 }
593
John Reckacb6f072014-03-12 16:11:23 -0700594private:
John Reckacb6f072014-03-12 16:11:23 -0700595 // Rendering properties
John Reckd0a0b2a2014-03-20 16:28:56 -0700596 struct PrimitiveFields {
597 PrimitiveFields();
John Reckacb6f072014-03-12 16:11:23 -0700598
John Reckd0a0b2a2014-03-20 16:28:56 -0700599 Outline mOutline;
Chris Craik8c271ca2014-03-25 10:33:01 -0700600 RevealClip mRevealClip;
Chris Craika753f4c2014-07-24 12:39:17 -0700601 int mClippingFlags;
John Reckd0a0b2a2014-03-20 16:28:56 -0700602 bool mProjectBackwards;
603 bool mProjectionReceiver;
604 float mAlpha;
605 bool mHasOverlappingRendering;
Chris Craikcc39e162014-04-25 18:34:11 -0700606 float mElevation;
John Reckd0a0b2a2014-03-20 16:28:56 -0700607 float mTranslationX, mTranslationY, mTranslationZ;
608 float mRotation, mRotationX, mRotationY;
609 float mScaleX, mScaleY;
610 float mPivotX, mPivotY;
611 int mLeft, mTop, mRight, mBottom;
612 int mWidth, mHeight;
John Reckd0a0b2a2014-03-20 16:28:56 -0700613 bool mPivotExplicitlySet;
John Reckf7483e32014-04-11 08:54:47 -0700614 bool mMatrixOrPivotDirty;
Chris Craika753f4c2014-07-24 12:39:17 -0700615 Rect mClipBounds;
John Reckd0a0b2a2014-03-20 16:28:56 -0700616 } mPrimitiveFields;
617
John Reckacb6f072014-03-12 16:11:23 -0700618 SkMatrix* mStaticMatrix;
619 SkMatrix* mAnimationMatrix;
John Reck25fbb3f2014-06-12 13:46:45 -0700620 LayerProperties mLayerProperties;
John Reckacb6f072014-03-12 16:11:23 -0700621
John Reckd0a0b2a2014-03-20 16:28:56 -0700622 /**
623 * These fields are all generated from other properties and are not set directly.
624 */
625 struct ComputedFields {
626 ComputedFields();
627 ~ComputedFields();
628
629 /**
630 * Stores the total transformation of the DisplayList based upon its scalar
631 * translate/rotate/scale properties.
632 *
Chris Craik49e6c7392014-03-31 12:34:11 -0700633 * In the common translation-only case, the matrix isn't necessarily allocated,
634 * and the mTranslation properties are used directly.
John Reckd0a0b2a2014-03-20 16:28:56 -0700635 */
Chris Craik49e6c7392014-03-31 12:34:11 -0700636 SkMatrix* mTransformMatrix;
637
638 Sk3DView mTransformCamera;
John Reckd0a0b2a2014-03-20 16:28:56 -0700639 } mComputedFields;
John Reckacb6f072014-03-12 16:11:23 -0700640};
641
642} /* namespace uirenderer */
643} /* namespace android */
644
Chris Craikb49f4462014-03-20 12:44:20 -0700645#endif /* RENDERNODEPROPERTIES_H */