RenderProperties.h revision d0a0b2a3140bfb1819a116413ce9d81886697a07
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 <stddef.h> 20#include <cutils/compiler.h> 21#include <androidfw/ResourceTypes.h> 22 23#include <SkCamera.h> 24#include <SkMatrix.h> 25 26#include "Rect.h" 27#include "Outline.h" 28 29#define TRANSLATION 0x0001 30#define ROTATION 0x0002 31#define ROTATION_3D 0x0004 32#define SCALE 0x0008 33#define PIVOT 0x0010 34 35class SkBitmap; 36class SkPaint; 37class SkRegion; 38 39namespace android { 40namespace uirenderer { 41 42class Matrix4; 43class RenderNode; 44 45/* 46 * Data structure that holds the properties for a RenderNode 47 */ 48class RenderProperties { 49public: 50 RenderProperties(); 51 virtual ~RenderProperties(); 52 53 RenderProperties& operator=(const RenderProperties& other); 54 55 void setClipToBounds(bool clipToBounds) { 56 mPrimitiveFields.mClipToBounds = clipToBounds; 57 } 58 59 void setProjectBackwards(bool shouldProject) { 60 mPrimitiveFields.mProjectBackwards = shouldProject; 61 } 62 63 void setProjectionReceiver(bool shouldRecieve) { 64 mPrimitiveFields.mProjectionReceiver = shouldRecieve; 65 } 66 67 bool isProjectionReceiver() const { 68 return mPrimitiveFields.mProjectionReceiver; 69 } 70 71 void setStaticMatrix(const SkMatrix* matrix) { 72 delete mStaticMatrix; 73 if (matrix) { 74 mStaticMatrix = new SkMatrix(*matrix); 75 } else { 76 mStaticMatrix = NULL; 77 } 78 } 79 80 // Can return NULL 81 const SkMatrix* getStaticMatrix() const { 82 return mStaticMatrix; 83 } 84 85 void setAnimationMatrix(const SkMatrix* matrix) { 86 delete mAnimationMatrix; 87 if (matrix) { 88 mAnimationMatrix = new SkMatrix(*matrix); 89 } else { 90 mAnimationMatrix = NULL; 91 } 92 } 93 94 void setAlpha(float alpha) { 95 alpha = fminf(1.0f, fmaxf(0.0f, alpha)); 96 if (alpha != mPrimitiveFields.mAlpha) { 97 mPrimitiveFields.mAlpha = alpha; 98 } 99 } 100 101 float getAlpha() const { 102 return mPrimitiveFields.mAlpha; 103 } 104 105 void setHasOverlappingRendering(bool hasOverlappingRendering) { 106 mPrimitiveFields.mHasOverlappingRendering = hasOverlappingRendering; 107 } 108 109 bool hasOverlappingRendering() const { 110 return mPrimitiveFields.mHasOverlappingRendering; 111 } 112 113 void setTranslationX(float translationX) { 114 if (translationX != mPrimitiveFields.mTranslationX) { 115 mPrimitiveFields.mTranslationX = translationX; 116 onTranslationUpdate(); 117 } 118 } 119 120 float getTranslationX() const { 121 return mPrimitiveFields.mTranslationX; 122 } 123 124 void setTranslationY(float translationY) { 125 if (translationY != mPrimitiveFields.mTranslationY) { 126 mPrimitiveFields.mTranslationY = translationY; 127 onTranslationUpdate(); 128 } 129 } 130 131 float getTranslationY() const { 132 return mPrimitiveFields.mTranslationY; 133 } 134 135 void setTranslationZ(float translationZ) { 136 if (translationZ != mPrimitiveFields.mTranslationZ) { 137 mPrimitiveFields.mTranslationZ = translationZ; 138 onTranslationUpdate(); 139 } 140 } 141 142 float getTranslationZ() const { 143 return mPrimitiveFields.mTranslationZ; 144 } 145 146 void setRotation(float rotation) { 147 if (rotation != mPrimitiveFields.mRotation) { 148 mPrimitiveFields.mRotation = rotation; 149 mPrimitiveFields.mMatrixDirty = true; 150 if (mPrimitiveFields.mRotation == 0.0f) { 151 mPrimitiveFields.mMatrixFlags &= ~ROTATION; 152 } else { 153 mPrimitiveFields.mMatrixFlags |= ROTATION; 154 } 155 } 156 } 157 158 float getRotation() const { 159 return mPrimitiveFields.mRotation; 160 } 161 162 void setRotationX(float rotationX) { 163 if (rotationX != mPrimitiveFields.mRotationX) { 164 mPrimitiveFields.mRotationX = rotationX; 165 mPrimitiveFields.mMatrixDirty = true; 166 if (mPrimitiveFields.mRotationX == 0.0f && mPrimitiveFields.mRotationY == 0.0f) { 167 mPrimitiveFields.mMatrixFlags &= ~ROTATION_3D; 168 } else { 169 mPrimitiveFields.mMatrixFlags |= ROTATION_3D; 170 } 171 } 172 } 173 174 float getRotationX() const { 175 return mPrimitiveFields.mRotationX; 176 } 177 178 void setRotationY(float rotationY) { 179 if (rotationY != mPrimitiveFields.mRotationY) { 180 mPrimitiveFields.mRotationY = rotationY; 181 mPrimitiveFields.mMatrixDirty = true; 182 if (mPrimitiveFields.mRotationX == 0.0f && mPrimitiveFields.mRotationY == 0.0f) { 183 mPrimitiveFields.mMatrixFlags &= ~ROTATION_3D; 184 } else { 185 mPrimitiveFields.mMatrixFlags |= ROTATION_3D; 186 } 187 } 188 } 189 190 float getRotationY() const { 191 return mPrimitiveFields.mRotationY; 192 } 193 194 void setScaleX(float scaleX) { 195 if (scaleX != mPrimitiveFields.mScaleX) { 196 mPrimitiveFields.mScaleX = scaleX; 197 mPrimitiveFields.mMatrixDirty = true; 198 if (mPrimitiveFields.mScaleX == 1.0f && mPrimitiveFields.mScaleY == 1.0f) { 199 mPrimitiveFields.mMatrixFlags &= ~SCALE; 200 } else { 201 mPrimitiveFields.mMatrixFlags |= SCALE; 202 } 203 } 204 } 205 206 float getScaleX() const { 207 return mPrimitiveFields.mScaleX; 208 } 209 210 void setScaleY(float scaleY) { 211 if (scaleY != mPrimitiveFields.mScaleY) { 212 mPrimitiveFields.mScaleY = scaleY; 213 mPrimitiveFields.mMatrixDirty = true; 214 if (mPrimitiveFields.mScaleX == 1.0f && mPrimitiveFields.mScaleY == 1.0f) { 215 mPrimitiveFields.mMatrixFlags &= ~SCALE; 216 } else { 217 mPrimitiveFields.mMatrixFlags |= SCALE; 218 } 219 } 220 } 221 222 float getScaleY() const { 223 return mPrimitiveFields.mScaleY; 224 } 225 226 void setPivotX(float pivotX) { 227 mPrimitiveFields.mPivotX = pivotX; 228 mPrimitiveFields.mMatrixDirty = true; 229 if (mPrimitiveFields.mPivotX == 0.0f && mPrimitiveFields.mPivotY == 0.0f) { 230 mPrimitiveFields.mMatrixFlags &= ~PIVOT; 231 } else { 232 mPrimitiveFields.mMatrixFlags |= PIVOT; 233 } 234 mPrimitiveFields.mPivotExplicitlySet = true; 235 } 236 237 /* Note that getPivotX and getPivotY are adjusted by updateMatrix(), 238 * so the value returned mPrimitiveFields.may be stale if the RenderProperties has been 239 * mPrimitiveFields.modified since the last call to updateMatrix() 240 */ 241 float getPivotX() const { 242 return mPrimitiveFields.mPivotX; 243 } 244 245 void setPivotY(float pivotY) { 246 mPrimitiveFields.mPivotY = pivotY; 247 mPrimitiveFields.mMatrixDirty = true; 248 if (mPrimitiveFields.mPivotX == 0.0f && mPrimitiveFields.mPivotY == 0.0f) { 249 mPrimitiveFields.mMatrixFlags &= ~PIVOT; 250 } else { 251 mPrimitiveFields.mMatrixFlags |= PIVOT; 252 } 253 mPrimitiveFields.mPivotExplicitlySet = true; 254 } 255 256 float getPivotY() const { 257 return mPrimitiveFields.mPivotY; 258 } 259 260 void setCameraDistance(float distance) { 261 if (distance != mCameraDistance) { 262 mCameraDistance = distance; 263 mPrimitiveFields.mMatrixDirty = true; 264 if (!mComputedFields.mTransformCamera) { 265 mComputedFields.mTransformCamera = new Sk3DView(); 266 mComputedFields.mTransformMatrix3D = new SkMatrix(); 267 } 268 mComputedFields.mTransformCamera->setCameraLocation(0, 0, distance); 269 } 270 } 271 272 float getCameraDistance() const { 273 return mCameraDistance; 274 } 275 276 void setLeft(int left) { 277 if (left != mPrimitiveFields.mLeft) { 278 mPrimitiveFields.mLeft = left; 279 mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft; 280 if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) { 281 mPrimitiveFields.mMatrixDirty = true; 282 } 283 } 284 } 285 286 float getLeft() const { 287 return mPrimitiveFields.mLeft; 288 } 289 290 void setTop(int top) { 291 if (top != mPrimitiveFields.mTop) { 292 mPrimitiveFields.mTop = top; 293 mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop; 294 if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) { 295 mPrimitiveFields.mMatrixDirty = true; 296 } 297 } 298 } 299 300 float getTop() const { 301 return mPrimitiveFields.mTop; 302 } 303 304 void setRight(int right) { 305 if (right != mPrimitiveFields.mRight) { 306 mPrimitiveFields.mRight = right; 307 mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft; 308 if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) { 309 mPrimitiveFields.mMatrixDirty = true; 310 } 311 } 312 } 313 314 float getRight() const { 315 return mPrimitiveFields.mRight; 316 } 317 318 void setBottom(int bottom) { 319 if (bottom != mPrimitiveFields.mBottom) { 320 mPrimitiveFields.mBottom = bottom; 321 mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop; 322 if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) { 323 mPrimitiveFields.mMatrixDirty = true; 324 } 325 } 326 } 327 328 float getBottom() const { 329 return mPrimitiveFields.mBottom; 330 } 331 332 void setLeftTop(int left, int top) { 333 if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop) { 334 mPrimitiveFields.mLeft = left; 335 mPrimitiveFields.mTop = top; 336 mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft; 337 mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop; 338 if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) { 339 mPrimitiveFields.mMatrixDirty = true; 340 } 341 } 342 } 343 344 void setLeftTopRightBottom(int left, int top, int right, int bottom) { 345 if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop || right != mPrimitiveFields.mRight || bottom != mPrimitiveFields.mBottom) { 346 mPrimitiveFields.mLeft = left; 347 mPrimitiveFields.mTop = top; 348 mPrimitiveFields.mRight = right; 349 mPrimitiveFields.mBottom = bottom; 350 mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft; 351 mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop; 352 if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) { 353 mPrimitiveFields.mMatrixDirty = true; 354 } 355 } 356 } 357 358 void offsetLeftRight(float offset) { 359 if (offset != 0) { 360 mPrimitiveFields.mLeft += offset; 361 mPrimitiveFields.mRight += offset; 362 if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) { 363 mPrimitiveFields.mMatrixDirty = true; 364 } 365 } 366 } 367 368 void offsetTopBottom(float offset) { 369 if (offset != 0) { 370 mPrimitiveFields.mTop += offset; 371 mPrimitiveFields.mBottom += offset; 372 if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) { 373 mPrimitiveFields.mMatrixDirty = true; 374 } 375 } 376 } 377 378 void setCaching(bool caching) { 379 mPrimitiveFields.mCaching = caching; 380 } 381 382 int getWidth() const { 383 return mPrimitiveFields.mWidth; 384 } 385 386 int getHeight() const { 387 return mPrimitiveFields.mHeight; 388 } 389 390 const SkMatrix* getAnimationMatrix() const { 391 return mAnimationMatrix; 392 } 393 394 uint32_t getMatrixFlags() const { 395 return mPrimitiveFields.mMatrixFlags; 396 } 397 398 const Matrix4* getTransformMatrix() const { 399 return mComputedFields.mTransformMatrix; 400 } 401 402 bool getCaching() const { 403 return mPrimitiveFields.mCaching; 404 } 405 406 bool getClipToBounds() const { 407 return mPrimitiveFields.mClipToBounds; 408 } 409 410 bool getHasOverlappingRendering() const { 411 return mPrimitiveFields.mHasOverlappingRendering; 412 } 413 414 const Outline& getOutline() const { 415 return mPrimitiveFields.mOutline; 416 } 417 418 bool getProjectBackwards() const { 419 return mPrimitiveFields.mProjectBackwards; 420 } 421 422 void debugOutputProperties(const int level) const; 423 424 ANDROID_API void updateMatrix(); 425 426 Outline& mutableOutline() { 427 return mPrimitiveFields.mOutline; 428 } 429 430private: 431 void onTranslationUpdate() { 432 mPrimitiveFields.mMatrixDirty = true; 433 if (mPrimitiveFields.mTranslationX == 0.0f && mPrimitiveFields.mTranslationY == 0.0f && mPrimitiveFields.mTranslationZ == 0.0f) { 434 mPrimitiveFields.mMatrixFlags &= ~TRANSLATION; 435 } else { 436 mPrimitiveFields.mMatrixFlags |= TRANSLATION; 437 } 438 } 439 440 // Rendering properties 441 struct PrimitiveFields { 442 PrimitiveFields(); 443 444 Outline mOutline; 445 bool mClipToBounds; 446 bool mProjectBackwards; 447 bool mProjectionReceiver; 448 float mAlpha; 449 bool mHasOverlappingRendering; 450 float mTranslationX, mTranslationY, mTranslationZ; 451 float mRotation, mRotationX, mRotationY; 452 float mScaleX, mScaleY; 453 float mPivotX, mPivotY; 454 int mLeft, mTop, mRight, mBottom; 455 int mWidth, mHeight; 456 int mPrevWidth, mPrevHeight; 457 bool mPivotExplicitlySet; 458 bool mMatrixDirty; 459 bool mMatrixIsIdentity; 460 uint32_t mMatrixFlags; 461 bool mCaching; 462 } mPrimitiveFields; 463 464 // mCameraDistance isn't in mPrimitiveFields as it has a complex setter 465 float mCameraDistance; 466 SkMatrix* mStaticMatrix; 467 SkMatrix* mAnimationMatrix; 468 469 /** 470 * These fields are all generated from other properties and are not set directly. 471 */ 472 struct ComputedFields { 473 ComputedFields(); 474 ~ComputedFields(); 475 476 /** 477 * Stores the total transformation of the DisplayList based upon its scalar 478 * translate/rotate/scale properties. 479 * 480 * In the common translation-only case, the matrix isn't allocated and the mTranslation 481 * properties are used directly. 482 */ 483 Matrix4* mTransformMatrix; 484 Sk3DView* mTransformCamera; 485 SkMatrix* mTransformMatrix3D; 486 } mComputedFields; 487}; 488 489} /* namespace uirenderer */ 490} /* namespace android */ 491 492#endif /* RENDERNODEPROPERTIES_H */ 493