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