RenderProperties.h revision 25fbb3fa1138675379102a44405852555cefccbd
1/* 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 */ 16#ifndef RENDERNODEPROPERTIES_H 17#define RENDERNODEPROPERTIES_H 18 19#include <algorithm> 20#include <stddef.h> 21#include <vector> 22#include <cutils/compiler.h> 23#include <androidfw/ResourceTypes.h> 24 25#include <SkCamera.h> 26#include <SkMatrix.h> 27#include <SkRegion.h> 28 29#include "Animator.h" 30#include "Rect.h" 31#include "RevealClip.h" 32#include "Outline.h" 33 34class SkBitmap; 35class SkColorFilter; 36class SkPaint; 37 38namespace android { 39namespace uirenderer { 40 41class Matrix4; 42class RenderNode; 43class RenderProperties; 44 45// The __VA_ARGS__ will be executed if a & b are not equal 46#define RP_SET(a, b, ...) (a != b ? (a = b, ##__VA_ARGS__, true) : false) 47#define RP_SET_AND_DIRTY(a, b) RP_SET(a, b, mPrimitiveFields.mMatrixOrPivotDirty = true) 48 49// Keep in sync with View.java:LAYER_TYPE_* 50enum LayerType { 51 kLayerTypeNone = 0, 52 // Although we cannot build the software layer directly (must be done at 53 // record time), this information is used when applying alpha. 54 kLayerTypeSoftware = 1, 55 kLayerTypeRenderLayer = 2, 56 // TODO: LayerTypeSurfaceTexture? Maybe? 57}; 58 59class ANDROID_API LayerProperties { 60public: 61 bool setType(LayerType type) { 62 if (RP_SET(mType, type)) { 63 reset(); 64 return true; 65 } 66 return false; 67 } 68 69 LayerType type() const { 70 return mType; 71 } 72 73 bool setOpaque(bool opaque) { 74 return RP_SET(mOpaque, opaque); 75 } 76 77 bool opaque() const { 78 return mOpaque; 79 } 80 81 bool setAlpha(uint8_t alpha) { 82 return RP_SET(mAlpha, alpha); 83 } 84 85 uint8_t alpha() const { 86 return mAlpha; 87 } 88 89 bool setXferMode(SkXfermode::Mode mode) { 90 return RP_SET(mMode, mode); 91 } 92 93 SkXfermode::Mode xferMode() const { 94 return mMode; 95 } 96 97 bool setColorFilter(SkColorFilter* filter); 98 99 SkColorFilter* colorFilter() const { 100 return mColorFilter; 101 } 102 103 // Sets alpha, xfermode, and colorfilter from an SkPaint 104 // paint may be NULL, in which case defaults will be set 105 bool setFromPaint(const SkPaint* paint); 106 107 bool needsBlending() const { 108 return !opaque() || alpha() < 255; 109 } 110 111 LayerProperties& operator=(const LayerProperties& other); 112 113private: 114 LayerProperties(); 115 ~LayerProperties(); 116 void reset(); 117 118 friend class RenderProperties; 119 120 LayerType mType; 121 // Whether or not that Layer's content is opaque, doesn't include alpha 122 bool mOpaque; 123 uint8_t mAlpha; 124 SkXfermode::Mode mMode; 125 SkColorFilter* mColorFilter; 126}; 127 128/* 129 * Data structure that holds the properties for a RenderNode 130 */ 131class ANDROID_API RenderProperties { 132public: 133 RenderProperties(); 134 virtual ~RenderProperties(); 135 136 RenderProperties& operator=(const RenderProperties& other); 137 138 bool setClipToBounds(bool clipToBounds) { 139 return RP_SET(mPrimitiveFields.mClipToBounds, clipToBounds); 140 } 141 142 bool setProjectBackwards(bool shouldProject) { 143 return RP_SET(mPrimitiveFields.mProjectBackwards, shouldProject); 144 } 145 146 bool setProjectionReceiver(bool shouldRecieve) { 147 return RP_SET(mPrimitiveFields.mProjectionReceiver, shouldRecieve); 148 } 149 150 bool isProjectionReceiver() const { 151 return mPrimitiveFields.mProjectionReceiver; 152 } 153 154 bool setStaticMatrix(const SkMatrix* matrix) { 155 delete mStaticMatrix; 156 if (matrix) { 157 mStaticMatrix = new SkMatrix(*matrix); 158 } else { 159 mStaticMatrix = NULL; 160 } 161 return true; 162 } 163 164 // Can return NULL 165 const SkMatrix* getStaticMatrix() const { 166 return mStaticMatrix; 167 } 168 169 bool setAnimationMatrix(const SkMatrix* matrix) { 170 delete mAnimationMatrix; 171 if (matrix) { 172 mAnimationMatrix = new SkMatrix(*matrix); 173 } else { 174 mAnimationMatrix = NULL; 175 } 176 return true; 177 } 178 179 bool setAlpha(float alpha) { 180 alpha = fminf(1.0f, fmaxf(0.0f, alpha)); 181 return RP_SET(mPrimitiveFields.mAlpha, alpha); 182 } 183 184 float getAlpha() const { 185 return mPrimitiveFields.mAlpha; 186 } 187 188 bool setHasOverlappingRendering(bool hasOverlappingRendering) { 189 return RP_SET(mPrimitiveFields.mHasOverlappingRendering, hasOverlappingRendering); 190 } 191 192 bool hasOverlappingRendering() const { 193 return mPrimitiveFields.mHasOverlappingRendering; 194 } 195 196 bool setElevation(float elevation) { 197 return RP_SET(mPrimitiveFields.mElevation, elevation); 198 // Don't dirty matrix/pivot, since they don't respect Z 199 } 200 201 float getElevation() const { 202 return mPrimitiveFields.mElevation; 203 } 204 205 bool setTranslationX(float translationX) { 206 return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationX, translationX); 207 } 208 209 float getTranslationX() const { 210 return mPrimitiveFields.mTranslationX; 211 } 212 213 bool setTranslationY(float translationY) { 214 return RP_SET_AND_DIRTY(mPrimitiveFields.mTranslationY, translationY); 215 } 216 217 float getTranslationY() const { 218 return mPrimitiveFields.mTranslationY; 219 } 220 221 bool setTranslationZ(float translationZ) { 222 return RP_SET(mPrimitiveFields.mTranslationZ, translationZ); 223 // mMatrixOrPivotDirty not set, since matrix doesn't respect Z 224 } 225 226 float getTranslationZ() const { 227 return mPrimitiveFields.mTranslationZ; 228 } 229 230 // Animation helper 231 bool setX(float value) { 232 return setTranslationX(value - getLeft()); 233 } 234 235 // Animation helper 236 float getX() const { 237 return getLeft() + getTranslationX(); 238 } 239 240 // Animation helper 241 bool setY(float value) { 242 return setTranslationY(value - getTop()); 243 } 244 245 // Animation helper 246 float getY() const { 247 return getTop() + getTranslationY(); 248 } 249 250 // Animation helper 251 bool setZ(float value) { 252 return setTranslationZ(value - getElevation()); 253 } 254 255 float getZ() const { 256 return getElevation() + getTranslationZ(); 257 } 258 259 bool setRotation(float rotation) { 260 return RP_SET_AND_DIRTY(mPrimitiveFields.mRotation, rotation); 261 } 262 263 float getRotation() const { 264 return mPrimitiveFields.mRotation; 265 } 266 267 bool setRotationX(float rotationX) { 268 return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationX, rotationX); 269 } 270 271 float getRotationX() const { 272 return mPrimitiveFields.mRotationX; 273 } 274 275 bool setRotationY(float rotationY) { 276 return RP_SET_AND_DIRTY(mPrimitiveFields.mRotationY, rotationY); 277 } 278 279 float getRotationY() const { 280 return mPrimitiveFields.mRotationY; 281 } 282 283 bool setScaleX(float scaleX) { 284 return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleX, scaleX); 285 } 286 287 float getScaleX() const { 288 return mPrimitiveFields.mScaleX; 289 } 290 291 bool setScaleY(float scaleY) { 292 return RP_SET_AND_DIRTY(mPrimitiveFields.mScaleY, scaleY); 293 } 294 295 float getScaleY() const { 296 return mPrimitiveFields.mScaleY; 297 } 298 299 bool setPivotX(float pivotX) { 300 if (RP_SET(mPrimitiveFields.mPivotX, pivotX) 301 || !mPrimitiveFields.mPivotExplicitlySet) { 302 mPrimitiveFields.mMatrixOrPivotDirty = true; 303 mPrimitiveFields.mPivotExplicitlySet = true; 304 return true; 305 } 306 return false; 307 } 308 309 /* Note that getPivotX and getPivotY are adjusted by updateMatrix(), 310 * so the value returned may be stale if the RenderProperties has been 311 * modified since the last call to updateMatrix() 312 */ 313 float getPivotX() const { 314 return mPrimitiveFields.mPivotX; 315 } 316 317 bool setPivotY(float pivotY) { 318 if (RP_SET(mPrimitiveFields.mPivotY, pivotY) 319 || !mPrimitiveFields.mPivotExplicitlySet) { 320 mPrimitiveFields.mMatrixOrPivotDirty = true; 321 mPrimitiveFields.mPivotExplicitlySet = true; 322 return true; 323 } 324 return false; 325 } 326 327 float getPivotY() const { 328 return mPrimitiveFields.mPivotY; 329 } 330 331 bool isPivotExplicitlySet() const { 332 return mPrimitiveFields.mPivotExplicitlySet; 333 } 334 335 bool setCameraDistance(float distance) { 336 if (distance != getCameraDistance()) { 337 mPrimitiveFields.mMatrixOrPivotDirty = true; 338 mComputedFields.mTransformCamera.setCameraLocation(0, 0, distance); 339 return true; 340 } 341 return false; 342 } 343 344 float getCameraDistance() const { 345 // TODO: update getCameraLocationZ() to be const 346 return const_cast<Sk3DView*>(&mComputedFields.mTransformCamera)->getCameraLocationZ(); 347 } 348 349 bool setLeft(int left) { 350 if (RP_SET(mPrimitiveFields.mLeft, left)) { 351 mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft; 352 if (!mPrimitiveFields.mPivotExplicitlySet) { 353 mPrimitiveFields.mMatrixOrPivotDirty = true; 354 } 355 return true; 356 } 357 return false; 358 } 359 360 float getLeft() const { 361 return mPrimitiveFields.mLeft; 362 } 363 364 bool setTop(int top) { 365 if (RP_SET(mPrimitiveFields.mTop, top)) { 366 mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop; 367 if (!mPrimitiveFields.mPivotExplicitlySet) { 368 mPrimitiveFields.mMatrixOrPivotDirty = true; 369 } 370 return true; 371 } 372 return false; 373 } 374 375 float getTop() const { 376 return mPrimitiveFields.mTop; 377 } 378 379 bool setRight(int right) { 380 if (RP_SET(mPrimitiveFields.mRight, right)) { 381 mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft; 382 if (!mPrimitiveFields.mPivotExplicitlySet) { 383 mPrimitiveFields.mMatrixOrPivotDirty = true; 384 } 385 return true; 386 } 387 return false; 388 } 389 390 float getRight() const { 391 return mPrimitiveFields.mRight; 392 } 393 394 bool setBottom(int bottom) { 395 if (RP_SET(mPrimitiveFields.mBottom, bottom)) { 396 mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop; 397 if (!mPrimitiveFields.mPivotExplicitlySet) { 398 mPrimitiveFields.mMatrixOrPivotDirty = true; 399 } 400 return true; 401 } 402 return false; 403 } 404 405 float getBottom() const { 406 return mPrimitiveFields.mBottom; 407 } 408 409 bool setLeftTop(int left, int top) { 410 bool leftResult = setLeft(left); 411 bool topResult = setTop(top); 412 return leftResult || topResult; 413 } 414 415 bool setLeftTopRightBottom(int left, int top, int right, int bottom) { 416 if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop 417 || right != mPrimitiveFields.mRight || bottom != mPrimitiveFields.mBottom) { 418 mPrimitiveFields.mLeft = left; 419 mPrimitiveFields.mTop = top; 420 mPrimitiveFields.mRight = right; 421 mPrimitiveFields.mBottom = bottom; 422 mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft; 423 mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop; 424 if (!mPrimitiveFields.mPivotExplicitlySet) { 425 mPrimitiveFields.mMatrixOrPivotDirty = true; 426 } 427 return true; 428 } 429 return false; 430 } 431 432 bool offsetLeftRight(float offset) { 433 if (offset != 0) { 434 mPrimitiveFields.mLeft += offset; 435 mPrimitiveFields.mRight += offset; 436 return true; 437 } 438 return false; 439 } 440 441 bool offsetTopBottom(float offset) { 442 if (offset != 0) { 443 mPrimitiveFields.mTop += offset; 444 mPrimitiveFields.mBottom += offset; 445 return true; 446 } 447 return false; 448 } 449 450 int getWidth() const { 451 return mPrimitiveFields.mWidth; 452 } 453 454 int getHeight() const { 455 return mPrimitiveFields.mHeight; 456 } 457 458 const SkMatrix* getAnimationMatrix() const { 459 return mAnimationMatrix; 460 } 461 462 bool hasTransformMatrix() const { 463 return getTransformMatrix() && !getTransformMatrix()->isIdentity(); 464 } 465 466 // May only call this if hasTransformMatrix() is true 467 bool isTransformTranslateOnly() const { 468 return getTransformMatrix()->getType() == SkMatrix::kTranslate_Mask; 469 } 470 471 const SkMatrix* getTransformMatrix() const { 472 LOG_ALWAYS_FATAL_IF(mPrimitiveFields.mMatrixOrPivotDirty, "Cannot get a dirty matrix!"); 473 return mComputedFields.mTransformMatrix; 474 } 475 476 bool getClipToBounds() const { 477 return mPrimitiveFields.mClipToBounds; 478 } 479 480 bool getHasOverlappingRendering() const { 481 return mPrimitiveFields.mHasOverlappingRendering; 482 } 483 484 const Outline& getOutline() const { 485 return mPrimitiveFields.mOutline; 486 } 487 488 const RevealClip& getRevealClip() const { 489 return mPrimitiveFields.mRevealClip; 490 } 491 492 bool getProjectBackwards() const { 493 return mPrimitiveFields.mProjectBackwards; 494 } 495 496 void debugOutputProperties(const int level) const; 497 498 void updateMatrix(); 499 500 bool hasClippingPath() const { 501 return mPrimitiveFields.mRevealClip.willClip(); 502 } 503 504 const SkPath* getClippingPath() const { 505 return mPrimitiveFields.mRevealClip.getPath(); 506 } 507 508 SkRegion::Op getClippingPathOp() const { 509 return mPrimitiveFields.mRevealClip.isInverseClip() 510 ? SkRegion::kDifference_Op : SkRegion::kIntersect_Op; 511 } 512 513 Outline& mutableOutline() { 514 return mPrimitiveFields.mOutline; 515 } 516 517 RevealClip& mutableRevealClip() { 518 return mPrimitiveFields.mRevealClip; 519 } 520 521 const LayerProperties& layerProperties() const { 522 return mLayerProperties; 523 } 524 525 LayerProperties& mutateLayerProperties() { 526 return mLayerProperties; 527 } 528 529private: 530 531 // Rendering properties 532 struct PrimitiveFields { 533 PrimitiveFields(); 534 535 Outline mOutline; 536 RevealClip mRevealClip; 537 bool mClipToBounds; 538 bool mProjectBackwards; 539 bool mProjectionReceiver; 540 float mAlpha; 541 bool mHasOverlappingRendering; 542 float mElevation; 543 float mTranslationX, mTranslationY, mTranslationZ; 544 float mRotation, mRotationX, mRotationY; 545 float mScaleX, mScaleY; 546 float mPivotX, mPivotY; 547 int mLeft, mTop, mRight, mBottom; 548 int mWidth, mHeight; 549 bool mPivotExplicitlySet; 550 bool mMatrixOrPivotDirty; 551 } mPrimitiveFields; 552 553 SkMatrix* mStaticMatrix; 554 SkMatrix* mAnimationMatrix; 555 LayerProperties mLayerProperties; 556 557 /** 558 * These fields are all generated from other properties and are not set directly. 559 */ 560 struct ComputedFields { 561 ComputedFields(); 562 ~ComputedFields(); 563 564 /** 565 * Stores the total transformation of the DisplayList based upon its scalar 566 * translate/rotate/scale properties. 567 * 568 * In the common translation-only case, the matrix isn't necessarily allocated, 569 * and the mTranslation properties are used directly. 570 */ 571 SkMatrix* mTransformMatrix; 572 573 Sk3DView mTransformCamera; 574 } mComputedFields; 575}; 576 577} /* namespace uirenderer */ 578} /* namespace android */ 579 580#endif /* RENDERNODEPROPERTIES_H */ 581