RenderNode.java revision 44b49f070aafe8ad44efae87341121cce49ff11c
1/* 2 * Copyright (C) 2010 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 17package android.view; 18 19import android.annotation.NonNull; 20import android.annotation.Nullable; 21import android.graphics.Matrix; 22import android.graphics.Outline; 23import android.graphics.Paint; 24import android.graphics.Rect; 25import android.graphics.drawable.AnimatedVectorDrawable; 26 27/** 28 * <p>A display list records a series of graphics related operations and can replay 29 * them later. Display lists are usually built by recording operations on a 30 * {@link DisplayListCanvas}. Replaying the operations from a display list avoids 31 * executing application code on every frame, and is thus much more efficient.</p> 32 * 33 * <p>Display lists are used internally for all views by default, and are not 34 * typically used directly. One reason to consider using a display is a custom 35 * {@link View} implementation that needs to issue a large number of drawing commands. 36 * When the view invalidates, all the drawing commands must be reissued, even if 37 * large portions of the drawing command stream stay the same frame to frame, which 38 * can become a performance bottleneck. To solve this issue, a custom View might split 39 * its content into several display lists. A display list is updated only when its 40 * content, and only its content, needs to be updated.</p> 41 * 42 * <p>A text editor might for instance store each paragraph into its own display list. 43 * Thus when the user inserts or removes characters, only the display list of the 44 * affected paragraph needs to be recorded again.</p> 45 * 46 * <h3>Hardware acceleration</h3> 47 * <p>Display lists can only be replayed using a {@link DisplayListCanvas}. They are not 48 * supported in software. Always make sure that the {@link android.graphics.Canvas} 49 * you are using to render a display list is hardware accelerated using 50 * {@link android.graphics.Canvas#isHardwareAccelerated()}.</p> 51 * 52 * <h3>Creating a display list</h3> 53 * <pre class="prettyprint"> 54 * HardwareRenderer renderer = myView.getHardwareRenderer(); 55 * if (renderer != null) { 56 * DisplayList displayList = renderer.createDisplayList(); 57 * DisplayListCanvas canvas = displayList.start(width, height); 58 * try { 59 * // Draw onto the canvas 60 * // For instance: canvas.drawBitmap(...); 61 * } finally { 62 * displayList.end(); 63 * } 64 * } 65 * </pre> 66 * 67 * <h3>Rendering a display list on a View</h3> 68 * <pre class="prettyprint"> 69 * protected void onDraw(Canvas canvas) { 70 * if (canvas.isHardwareAccelerated()) { 71 * DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas; 72 * displayListCanvas.drawDisplayList(mDisplayList); 73 * } 74 * } 75 * </pre> 76 * 77 * <h3>Releasing resources</h3> 78 * <p>This step is not mandatory but recommended if you want to release resources 79 * held by a display list as soon as possible.</p> 80 * <pre class="prettyprint"> 81 * // Mark this display list invalid, it cannot be used for drawing anymore, 82 * // and release resources held by this display list 83 * displayList.clear(); 84 * </pre> 85 * 86 * <h3>Properties</h3> 87 * <p>In addition, a display list offers several properties, such as 88 * {@link #setScaleX(float)} or {@link #setLeft(int)}, that can be used to affect all 89 * the drawing commands recorded within. For instance, these properties can be used 90 * to move around a large number of images without re-issuing all the individual 91 * <code>drawBitmap()</code> calls.</p> 92 * 93 * <pre class="prettyprint"> 94 * private void createDisplayList() { 95 * mDisplayList = DisplayList.create("MyDisplayList"); 96 * DisplayListCanvas canvas = mDisplayList.start(width, height); 97 * try { 98 * for (Bitmap b : mBitmaps) { 99 * canvas.drawBitmap(b, 0.0f, 0.0f, null); 100 * canvas.translate(0.0f, b.getHeight()); 101 * } 102 * } finally { 103 * displayList.end(); 104 * } 105 * } 106 * 107 * protected void onDraw(Canvas canvas) { 108 * if (canvas.isHardwareAccelerated()) { 109 * DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas; 110 * displayListCanvas.drawDisplayList(mDisplayList); 111 * } 112 * } 113 * 114 * private void moveContentBy(int x) { 115 * // This will move all the bitmaps recorded inside the display list 116 * // by x pixels to the right and redraw this view. All the commands 117 * // recorded in createDisplayList() won't be re-issued, only onDraw() 118 * // will be invoked and will execute very quickly 119 * mDisplayList.offsetLeftAndRight(x); 120 * invalidate(); 121 * } 122 * </pre> 123 * 124 * <h3>Threading</h3> 125 * <p>Display lists must be created on and manipulated from the UI thread only.</p> 126 * 127 * @hide 128 */ 129public class RenderNode { 130 131 private boolean mValid; 132 // Do not access directly unless you are ThreadedRenderer 133 final long mNativeRenderNode; 134 private final View mOwningView; 135 136 private RenderNode(String name, View owningView) { 137 mNativeRenderNode = nCreate(name); 138 mOwningView = owningView; 139 if (mOwningView instanceof SurfaceView) { 140 nRequestPositionUpdates(mNativeRenderNode, (SurfaceView) mOwningView); 141 } 142 } 143 144 /** 145 * @see RenderNode#adopt(long) 146 */ 147 private RenderNode(long nativePtr) { 148 mNativeRenderNode = nativePtr; 149 mOwningView = null; 150 } 151 152 /** 153 * Creates a new RenderNode that can be used to record batches of 154 * drawing operations, and store / apply render properties when drawn. 155 * 156 * @param name The name of the RenderNode, used for debugging purpose. May be null. 157 * 158 * @return A new RenderNode. 159 */ 160 public static RenderNode create(String name, @Nullable View owningView) { 161 return new RenderNode(name, owningView); 162 } 163 164 /** 165 * Adopts an existing native render node. 166 * 167 * Note: This will *NOT* incRef() on the native object, however it will 168 * decRef() when it is destroyed. The caller should have already incRef'd it 169 */ 170 public static RenderNode adopt(long nativePtr) { 171 return new RenderNode(nativePtr); 172 } 173 174 175 /** 176 * Starts recording a display list for the render node. All 177 * operations performed on the returned canvas are recorded and 178 * stored in this display list. 179 * 180 * Calling this method will mark the render node invalid until 181 * {@link #end(DisplayListCanvas)} is called. 182 * Only valid render nodes can be replayed. 183 * 184 * @param width The width of the recording viewport 185 * @param height The height of the recording viewport 186 * 187 * @return A canvas to record drawing operations. 188 * 189 * @see #end(DisplayListCanvas) 190 * @see #isValid() 191 */ 192 public DisplayListCanvas start(int width, int height) { 193 return DisplayListCanvas.obtain(this, width, height); 194 } 195 196 /** 197 * Ends the recording for this display list. A display list cannot be 198 * replayed if recording is not finished. Calling this method marks 199 * the display list valid and {@link #isValid()} will return true. 200 * 201 * @see #start(int, int) 202 * @see #isValid() 203 */ 204 public void end(DisplayListCanvas canvas) { 205 long displayList = canvas.finishRecording(); 206 nSetDisplayList(mNativeRenderNode, displayList); 207 canvas.recycle(); 208 mValid = true; 209 } 210 211 /** 212 * Reset native resources. This is called when cleaning up the state of display lists 213 * during destruction of hardware resources, to ensure that we do not hold onto 214 * obsolete resources after related resources are gone. 215 */ 216 public void discardDisplayList() { 217 if (!mValid) return; 218 219 nSetDisplayList(mNativeRenderNode, 0); 220 mValid = false; 221 } 222 223 /** 224 * Returns whether the RenderNode's display list content is currently usable. 225 * If this returns false, the display list should be re-recorded prior to replaying it. 226 * 227 * @return boolean true if the display list is able to be replayed, false otherwise. 228 */ 229 public boolean isValid() { return mValid; } 230 231 long getNativeDisplayList() { 232 if (!mValid) { 233 throw new IllegalStateException("The display list is not valid."); 234 } 235 return mNativeRenderNode; 236 } 237 238 /////////////////////////////////////////////////////////////////////////// 239 // Matrix manipulation 240 /////////////////////////////////////////////////////////////////////////// 241 242 public boolean hasIdentityMatrix() { 243 return nHasIdentityMatrix(mNativeRenderNode); 244 } 245 246 public void getMatrix(@NonNull Matrix outMatrix) { 247 nGetTransformMatrix(mNativeRenderNode, outMatrix.native_instance); 248 } 249 250 public void getInverseMatrix(@NonNull Matrix outMatrix) { 251 nGetInverseTransformMatrix(mNativeRenderNode, outMatrix.native_instance); 252 } 253 254 /////////////////////////////////////////////////////////////////////////// 255 // RenderProperty Setters 256 /////////////////////////////////////////////////////////////////////////// 257 258 public boolean setLayerType(int layerType) { 259 return nSetLayerType(mNativeRenderNode, layerType); 260 } 261 262 public boolean setLayerPaint(@Nullable Paint paint) { 263 return nSetLayerPaint(mNativeRenderNode, paint != null ? paint.getNativeInstance() : 0); 264 } 265 266 public boolean setClipBounds(@Nullable Rect rect) { 267 if (rect == null) { 268 return nSetClipBoundsEmpty(mNativeRenderNode); 269 } else { 270 return nSetClipBounds(mNativeRenderNode, rect.left, rect.top, rect.right, rect.bottom); 271 } 272 } 273 274 /** 275 * Set whether the Render node should clip itself to its bounds. This property is controlled by 276 * the view's parent. 277 * 278 * @param clipToBounds true if the display list should clip to its bounds 279 */ 280 public boolean setClipToBounds(boolean clipToBounds) { 281 return nSetClipToBounds(mNativeRenderNode, clipToBounds); 282 } 283 284 /** 285 * Sets whether the display list should be drawn immediately after the 286 * closest ancestor display list containing a projection receiver. 287 * 288 * @param shouldProject true if the display list should be projected onto a 289 * containing volume. 290 */ 291 public boolean setProjectBackwards(boolean shouldProject) { 292 return nSetProjectBackwards(mNativeRenderNode, shouldProject); 293 } 294 295 /** 296 * Sets whether the display list is a projection receiver - that its parent 297 * DisplayList should draw any descendent DisplayLists with 298 * ProjectBackwards=true directly on top of it. Default value is false. 299 */ 300 public boolean setProjectionReceiver(boolean shouldRecieve) { 301 return nSetProjectionReceiver(mNativeRenderNode, shouldRecieve); 302 } 303 304 /** 305 * Sets the outline, defining the shape that casts a shadow, and the path to 306 * be clipped if setClipToOutline is set. 307 * 308 * Deep copies the data into native to simplify reference ownership. 309 */ 310 public boolean setOutline(Outline outline) { 311 if (outline == null) { 312 return nSetOutlineNone(mNativeRenderNode); 313 } else if (outline.isEmpty()) { 314 return nSetOutlineEmpty(mNativeRenderNode); 315 } else if (outline.mRect != null) { 316 return nSetOutlineRoundRect(mNativeRenderNode, outline.mRect.left, outline.mRect.top, 317 outline.mRect.right, outline.mRect.bottom, outline.mRadius, outline.mAlpha); 318 } else if (outline.mPath != null) { 319 return nSetOutlineConvexPath(mNativeRenderNode, outline.mPath.mNativePath, 320 outline.mAlpha); 321 } 322 throw new IllegalArgumentException("Unrecognized outline?"); 323 } 324 325 public boolean hasShadow() { 326 return nHasShadow(mNativeRenderNode); 327 } 328 329 /** 330 * Enables or disables clipping to the outline. 331 * 332 * @param clipToOutline true if clipping to the outline. 333 */ 334 public boolean setClipToOutline(boolean clipToOutline) { 335 return nSetClipToOutline(mNativeRenderNode, clipToOutline); 336 } 337 338 public boolean getClipToOutline() { 339 return nGetClipToOutline(mNativeRenderNode); 340 } 341 342 /** 343 * Controls the RenderNode's circular reveal clip. 344 */ 345 public boolean setRevealClip(boolean shouldClip, 346 float x, float y, float radius) { 347 return nSetRevealClip(mNativeRenderNode, shouldClip, x, y, radius); 348 } 349 350 /** 351 * Set the static matrix on the display list. The specified matrix is combined with other 352 * transforms (such as {@link #setScaleX(float)}, {@link #setRotation(float)}, etc.) 353 * 354 * @param matrix A transform matrix to apply to this display list 355 */ 356 public boolean setStaticMatrix(Matrix matrix) { 357 return nSetStaticMatrix(mNativeRenderNode, matrix.native_instance); 358 } 359 360 /** 361 * Set the Animation matrix on the display list. This matrix exists if an Animation is 362 * currently playing on a View, and is set on the display list during at draw() time. When 363 * the Animation finishes, the matrix should be cleared by sending <code>null</code> 364 * for the matrix parameter. 365 * 366 * @param matrix The matrix, null indicates that the matrix should be cleared. 367 */ 368 public boolean setAnimationMatrix(Matrix matrix) { 369 return nSetAnimationMatrix(mNativeRenderNode, 370 (matrix != null) ? matrix.native_instance : 0); 371 } 372 373 /** 374 * Sets the translucency level for the display list. 375 * 376 * @param alpha The translucency of the display list, must be a value between 0.0f and 1.0f 377 * 378 * @see View#setAlpha(float) 379 * @see #getAlpha() 380 */ 381 public boolean setAlpha(float alpha) { 382 return nSetAlpha(mNativeRenderNode, alpha); 383 } 384 385 /** 386 * Returns the translucency level of this display list. 387 * 388 * @return A value between 0.0f and 1.0f 389 * 390 * @see #setAlpha(float) 391 */ 392 public float getAlpha() { 393 return nGetAlpha(mNativeRenderNode); 394 } 395 396 /** 397 * Sets whether the display list renders content which overlaps. Non-overlapping rendering 398 * can use a fast path for alpha that avoids rendering to an offscreen buffer. By default 399 * display lists consider they do not have overlapping content. 400 * 401 * @param hasOverlappingRendering False if the content is guaranteed to be non-overlapping, 402 * true otherwise. 403 * 404 * @see android.view.View#hasOverlappingRendering() 405 * @see #hasOverlappingRendering() 406 */ 407 public boolean setHasOverlappingRendering(boolean hasOverlappingRendering) { 408 return nSetHasOverlappingRendering(mNativeRenderNode, hasOverlappingRendering); 409 } 410 411 /** 412 * Indicates whether the content of this display list overlaps. 413 * 414 * @return True if this display list renders content which overlaps, false otherwise. 415 * 416 * @see #setHasOverlappingRendering(boolean) 417 */ 418 public boolean hasOverlappingRendering() { 419 //noinspection SimplifiableIfStatement 420 return nHasOverlappingRendering(mNativeRenderNode); 421 } 422 423 public boolean setElevation(float lift) { 424 return nSetElevation(mNativeRenderNode, lift); 425 } 426 427 public float getElevation() { 428 return nGetElevation(mNativeRenderNode); 429 } 430 431 /** 432 * Sets the translation value for the display list on the X axis. 433 * 434 * @param translationX The X axis translation value of the display list, in pixels 435 * 436 * @see View#setTranslationX(float) 437 * @see #getTranslationX() 438 */ 439 public boolean setTranslationX(float translationX) { 440 return nSetTranslationX(mNativeRenderNode, translationX); 441 } 442 443 /** 444 * Returns the translation value for this display list on the X axis, in pixels. 445 * 446 * @see #setTranslationX(float) 447 */ 448 public float getTranslationX() { 449 return nGetTranslationX(mNativeRenderNode); 450 } 451 452 /** 453 * Sets the translation value for the display list on the Y axis. 454 * 455 * @param translationY The Y axis translation value of the display list, in pixels 456 * 457 * @see View#setTranslationY(float) 458 * @see #getTranslationY() 459 */ 460 public boolean setTranslationY(float translationY) { 461 return nSetTranslationY(mNativeRenderNode, translationY); 462 } 463 464 /** 465 * Returns the translation value for this display list on the Y axis, in pixels. 466 * 467 * @see #setTranslationY(float) 468 */ 469 public float getTranslationY() { 470 return nGetTranslationY(mNativeRenderNode); 471 } 472 473 /** 474 * Sets the translation value for the display list on the Z axis. 475 * 476 * @see View#setTranslationZ(float) 477 * @see #getTranslationZ() 478 */ 479 public boolean setTranslationZ(float translationZ) { 480 return nSetTranslationZ(mNativeRenderNode, translationZ); 481 } 482 483 /** 484 * Returns the translation value for this display list on the Z axis. 485 * 486 * @see #setTranslationZ(float) 487 */ 488 public float getTranslationZ() { 489 return nGetTranslationZ(mNativeRenderNode); 490 } 491 492 /** 493 * Sets the rotation value for the display list around the Z axis. 494 * 495 * @param rotation The rotation value of the display list, in degrees 496 * 497 * @see View#setRotation(float) 498 * @see #getRotation() 499 */ 500 public boolean setRotation(float rotation) { 501 return nSetRotation(mNativeRenderNode, rotation); 502 } 503 504 /** 505 * Returns the rotation value for this display list around the Z axis, in degrees. 506 * 507 * @see #setRotation(float) 508 */ 509 public float getRotation() { 510 return nGetRotation(mNativeRenderNode); 511 } 512 513 /** 514 * Sets the rotation value for the display list around the X axis. 515 * 516 * @param rotationX The rotation value of the display list, in degrees 517 * 518 * @see View#setRotationX(float) 519 * @see #getRotationX() 520 */ 521 public boolean setRotationX(float rotationX) { 522 return nSetRotationX(mNativeRenderNode, rotationX); 523 } 524 525 /** 526 * Returns the rotation value for this display list around the X axis, in degrees. 527 * 528 * @see #setRotationX(float) 529 */ 530 public float getRotationX() { 531 return nGetRotationX(mNativeRenderNode); 532 } 533 534 /** 535 * Sets the rotation value for the display list around the Y axis. 536 * 537 * @param rotationY The rotation value of the display list, in degrees 538 * 539 * @see View#setRotationY(float) 540 * @see #getRotationY() 541 */ 542 public boolean setRotationY(float rotationY) { 543 return nSetRotationY(mNativeRenderNode, rotationY); 544 } 545 546 /** 547 * Returns the rotation value for this display list around the Y axis, in degrees. 548 * 549 * @see #setRotationY(float) 550 */ 551 public float getRotationY() { 552 return nGetRotationY(mNativeRenderNode); 553 } 554 555 /** 556 * Sets the scale value for the display list on the X axis. 557 * 558 * @param scaleX The scale value of the display list 559 * 560 * @see View#setScaleX(float) 561 * @see #getScaleX() 562 */ 563 public boolean setScaleX(float scaleX) { 564 return nSetScaleX(mNativeRenderNode, scaleX); 565 } 566 567 /** 568 * Returns the scale value for this display list on the X axis. 569 * 570 * @see #setScaleX(float) 571 */ 572 public float getScaleX() { 573 return nGetScaleX(mNativeRenderNode); 574 } 575 576 /** 577 * Sets the scale value for the display list on the Y axis. 578 * 579 * @param scaleY The scale value of the display list 580 * 581 * @see View#setScaleY(float) 582 * @see #getScaleY() 583 */ 584 public boolean setScaleY(float scaleY) { 585 return nSetScaleY(mNativeRenderNode, scaleY); 586 } 587 588 /** 589 * Returns the scale value for this display list on the Y axis. 590 * 591 * @see #setScaleY(float) 592 */ 593 public float getScaleY() { 594 return nGetScaleY(mNativeRenderNode); 595 } 596 597 /** 598 * Sets the pivot value for the display list on the X axis 599 * 600 * @param pivotX The pivot value of the display list on the X axis, in pixels 601 * 602 * @see View#setPivotX(float) 603 * @see #getPivotX() 604 */ 605 public boolean setPivotX(float pivotX) { 606 return nSetPivotX(mNativeRenderNode, pivotX); 607 } 608 609 /** 610 * Returns the pivot value for this display list on the X axis, in pixels. 611 * 612 * @see #setPivotX(float) 613 */ 614 public float getPivotX() { 615 return nGetPivotX(mNativeRenderNode); 616 } 617 618 /** 619 * Sets the pivot value for the display list on the Y axis 620 * 621 * @param pivotY The pivot value of the display list on the Y axis, in pixels 622 * 623 * @see View#setPivotY(float) 624 * @see #getPivotY() 625 */ 626 public boolean setPivotY(float pivotY) { 627 return nSetPivotY(mNativeRenderNode, pivotY); 628 } 629 630 /** 631 * Returns the pivot value for this display list on the Y axis, in pixels. 632 * 633 * @see #setPivotY(float) 634 */ 635 public float getPivotY() { 636 return nGetPivotY(mNativeRenderNode); 637 } 638 639 public boolean isPivotExplicitlySet() { 640 return nIsPivotExplicitlySet(mNativeRenderNode); 641 } 642 643 /** 644 * Sets the camera distance for the display list. Refer to 645 * {@link View#setCameraDistance(float)} for more information on how to 646 * use this property. 647 * 648 * @param distance The distance in Z of the camera of the display list 649 * 650 * @see View#setCameraDistance(float) 651 * @see #getCameraDistance() 652 */ 653 public boolean setCameraDistance(float distance) { 654 return nSetCameraDistance(mNativeRenderNode, distance); 655 } 656 657 /** 658 * Returns the distance in Z of the camera of the display list. 659 * 660 * @see #setCameraDistance(float) 661 */ 662 public float getCameraDistance() { 663 return nGetCameraDistance(mNativeRenderNode); 664 } 665 666 /** 667 * Sets the left position for the display list. 668 * 669 * @param left The left position, in pixels, of the display list 670 * 671 * @see View#setLeft(int) 672 */ 673 public boolean setLeft(int left) { 674 return nSetLeft(mNativeRenderNode, left); 675 } 676 677 /** 678 * Sets the top position for the display list. 679 * 680 * @param top The top position, in pixels, of the display list 681 * 682 * @see View#setTop(int) 683 */ 684 public boolean setTop(int top) { 685 return nSetTop(mNativeRenderNode, top); 686 } 687 688 /** 689 * Sets the right position for the display list. 690 * 691 * @param right The right position, in pixels, of the display list 692 * 693 * @see View#setRight(int) 694 */ 695 public boolean setRight(int right) { 696 return nSetRight(mNativeRenderNode, right); 697 } 698 699 /** 700 * Sets the bottom position for the display list. 701 * 702 * @param bottom The bottom position, in pixels, of the display list 703 * 704 * @see View#setBottom(int) 705 */ 706 public boolean setBottom(int bottom) { 707 return nSetBottom(mNativeRenderNode, bottom); 708 } 709 710 /** 711 * Sets the left and top positions for the display list 712 * 713 * @param left The left position of the display list, in pixels 714 * @param top The top position of the display list, in pixels 715 * @param right The right position of the display list, in pixels 716 * @param bottom The bottom position of the display list, in pixels 717 * 718 * @see View#setLeft(int) 719 * @see View#setTop(int) 720 * @see View#setRight(int) 721 * @see View#setBottom(int) 722 */ 723 public boolean setLeftTopRightBottom(int left, int top, int right, int bottom) { 724 return nSetLeftTopRightBottom(mNativeRenderNode, left, top, right, bottom); 725 } 726 727 /** 728 * Offsets the left and right positions for the display list 729 * 730 * @param offset The amount that the left and right positions of the display 731 * list are offset, in pixels 732 * 733 * @see View#offsetLeftAndRight(int) 734 */ 735 public boolean offsetLeftAndRight(int offset) { 736 return nOffsetLeftAndRight(mNativeRenderNode, offset); 737 } 738 739 /** 740 * Offsets the top and bottom values for the display list 741 * 742 * @param offset The amount that the top and bottom positions of the display 743 * list are offset, in pixels 744 * 745 * @see View#offsetTopAndBottom(int) 746 */ 747 public boolean offsetTopAndBottom(int offset) { 748 return nOffsetTopAndBottom(mNativeRenderNode, offset); 749 } 750 751 /** 752 * Outputs the display list to the log. This method exists for use by 753 * tools to output display lists for selected nodes to the log. 754 */ 755 public void output() { 756 nOutput(mNativeRenderNode); 757 } 758 759 /** 760 * Gets the size of the DisplayList for debug purposes. 761 */ 762 public int getDebugSize() { 763 return nGetDebugSize(mNativeRenderNode); 764 } 765 766 /** 767 * Called by native when the passed displaylist is removed from the draw tree 768 */ 769 void onRenderNodeDetached() { 770 discardDisplayList(); 771 if (mOwningView != null) { 772 mOwningView.onRenderNodeDetached(this); 773 } 774 } 775 776 /////////////////////////////////////////////////////////////////////////// 777 // Animations 778 /////////////////////////////////////////////////////////////////////////// 779 780 public void addAnimator(RenderNodeAnimator animator) { 781 if (mOwningView == null || mOwningView.mAttachInfo == null) { 782 throw new IllegalStateException("Cannot start this animator on a detached view!"); 783 } 784 nAddAnimator(mNativeRenderNode, animator.getNativeAnimator()); 785 mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this); 786 } 787 788 public boolean isAttached() { 789 return mOwningView != null && mOwningView.mAttachInfo != null; 790 } 791 792 public void addAnimator(AnimatedVectorDrawable.VectorDrawableAnimatorRT animatorSet) { 793 if (mOwningView == null || mOwningView.mAttachInfo == null) { 794 throw new IllegalStateException("Cannot start this animator on a detached view!"); 795 } 796 nAddAnimator(mNativeRenderNode, animatorSet.getAnimatorNativePtr()); 797 mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this); 798 } 799 800 public void endAllAnimators() { 801 nEndAllAnimators(mNativeRenderNode); 802 } 803 804 /////////////////////////////////////////////////////////////////////////// 805 // Native methods 806 /////////////////////////////////////////////////////////////////////////// 807 808 // Intentionally not static because it acquires a reference to 'this' 809 private native long nCreate(String name); 810 811 private static native void nDestroyRenderNode(long renderNode); 812 private static native void nSetDisplayList(long renderNode, long newData); 813 814 // Matrix 815 816 private static native void nGetTransformMatrix(long renderNode, long nativeMatrix); 817 private static native void nGetInverseTransformMatrix(long renderNode, long nativeMatrix); 818 private static native boolean nHasIdentityMatrix(long renderNode); 819 820 // Properties 821 822 private static native boolean nOffsetTopAndBottom(long renderNode, int offset); 823 private static native boolean nOffsetLeftAndRight(long renderNode, int offset); 824 private static native boolean nSetLeftTopRightBottom(long renderNode, int left, int top, 825 int right, int bottom); 826 private static native boolean nSetBottom(long renderNode, int bottom); 827 private static native boolean nSetRight(long renderNode, int right); 828 private static native boolean nSetTop(long renderNode, int top); 829 private static native boolean nSetLeft(long renderNode, int left); 830 private static native boolean nSetCameraDistance(long renderNode, float distance); 831 private static native boolean nSetPivotY(long renderNode, float pivotY); 832 private static native boolean nSetPivotX(long renderNode, float pivotX); 833 private static native boolean nSetLayerType(long renderNode, int layerType); 834 private static native boolean nSetLayerPaint(long renderNode, long paint); 835 private static native boolean nSetClipToBounds(long renderNode, boolean clipToBounds); 836 private static native boolean nSetClipBounds(long renderNode, int left, int top, 837 int right, int bottom); 838 private static native boolean nSetClipBoundsEmpty(long renderNode); 839 private static native boolean nSetProjectBackwards(long renderNode, boolean shouldProject); 840 private static native boolean nSetProjectionReceiver(long renderNode, boolean shouldRecieve); 841 private static native boolean nSetOutlineRoundRect(long renderNode, int left, int top, 842 int right, int bottom, float radius, float alpha); 843 private static native boolean nSetOutlineConvexPath(long renderNode, long nativePath, 844 float alpha); 845 private static native boolean nSetOutlineEmpty(long renderNode); 846 private static native boolean nSetOutlineNone(long renderNode); 847 private static native boolean nHasShadow(long renderNode); 848 private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline); 849 private static native boolean nSetRevealClip(long renderNode, 850 boolean shouldClip, float x, float y, float radius); 851 private static native boolean nSetAlpha(long renderNode, float alpha); 852 private static native boolean nSetHasOverlappingRendering(long renderNode, 853 boolean hasOverlappingRendering); 854 private static native boolean nSetElevation(long renderNode, float lift); 855 private static native boolean nSetTranslationX(long renderNode, float translationX); 856 private static native boolean nSetTranslationY(long renderNode, float translationY); 857 private static native boolean nSetTranslationZ(long renderNode, float translationZ); 858 private static native boolean nSetRotation(long renderNode, float rotation); 859 private static native boolean nSetRotationX(long renderNode, float rotationX); 860 private static native boolean nSetRotationY(long renderNode, float rotationY); 861 private static native boolean nSetScaleX(long renderNode, float scaleX); 862 private static native boolean nSetScaleY(long renderNode, float scaleY); 863 private static native boolean nSetStaticMatrix(long renderNode, long nativeMatrix); 864 private static native boolean nSetAnimationMatrix(long renderNode, long animationMatrix); 865 866 private static native boolean nHasOverlappingRendering(long renderNode); 867 private static native boolean nGetClipToOutline(long renderNode); 868 private static native float nGetAlpha(long renderNode); 869 private static native float nGetCameraDistance(long renderNode); 870 private static native float nGetScaleX(long renderNode); 871 private static native float nGetScaleY(long renderNode); 872 private static native float nGetElevation(long renderNode); 873 private static native float nGetTranslationX(long renderNode); 874 private static native float nGetTranslationY(long renderNode); 875 private static native float nGetTranslationZ(long renderNode); 876 private static native float nGetRotation(long renderNode); 877 private static native float nGetRotationX(long renderNode); 878 private static native float nGetRotationY(long renderNode); 879 private static native boolean nIsPivotExplicitlySet(long renderNode); 880 private static native float nGetPivotX(long renderNode); 881 private static native float nGetPivotY(long renderNode); 882 private static native void nOutput(long renderNode); 883 private static native int nGetDebugSize(long renderNode); 884 885 private static native void nRequestPositionUpdates(long renderNode, SurfaceView callback); 886 887 /////////////////////////////////////////////////////////////////////////// 888 // Animations 889 /////////////////////////////////////////////////////////////////////////// 890 891 private static native void nAddAnimator(long renderNode, long animatorPtr); 892 private static native void nEndAllAnimators(long renderNode); 893 894 /////////////////////////////////////////////////////////////////////////// 895 // Finalization 896 /////////////////////////////////////////////////////////////////////////// 897 898 @Override 899 protected void finalize() throws Throwable { 900 try { 901 nDestroyRenderNode(mNativeRenderNode); 902 } finally { 903 super.finalize(); 904 } 905 } 906} 907