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 17 package android.view; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.graphics.Matrix; 22 import android.graphics.Outline; 23 import android.graphics.Paint; 24 import android.graphics.Rect; 25 import 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 */ 129 public 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(@Nullable Outline outline) { 311 if (outline == null) { 312 return nSetOutlineNone(mNativeRenderNode); 313 } 314 315 switch(outline.mMode) { 316 case Outline.MODE_EMPTY: 317 return nSetOutlineEmpty(mNativeRenderNode); 318 case Outline.MODE_ROUND_RECT: 319 return nSetOutlineRoundRect(mNativeRenderNode, outline.mRect.left, outline.mRect.top, 320 outline.mRect.right, outline.mRect.bottom, outline.mRadius, outline.mAlpha); 321 case Outline.MODE_CONVEX_PATH: 322 return nSetOutlineConvexPath(mNativeRenderNode, outline.mPath.mNativePath, 323 outline.mAlpha); 324 } 325 326 throw new IllegalArgumentException("Unrecognized outline?"); 327 } 328 329 public boolean hasShadow() { 330 return nHasShadow(mNativeRenderNode); 331 } 332 333 /** 334 * Enables or disables clipping to the outline. 335 * 336 * @param clipToOutline true if clipping to the outline. 337 */ 338 public boolean setClipToOutline(boolean clipToOutline) { 339 return nSetClipToOutline(mNativeRenderNode, clipToOutline); 340 } 341 342 public boolean getClipToOutline() { 343 return nGetClipToOutline(mNativeRenderNode); 344 } 345 346 /** 347 * Controls the RenderNode's circular reveal clip. 348 */ 349 public boolean setRevealClip(boolean shouldClip, 350 float x, float y, float radius) { 351 return nSetRevealClip(mNativeRenderNode, shouldClip, x, y, radius); 352 } 353 354 /** 355 * Set the static matrix on the display list. The specified matrix is combined with other 356 * transforms (such as {@link #setScaleX(float)}, {@link #setRotation(float)}, etc.) 357 * 358 * @param matrix A transform matrix to apply to this display list 359 */ 360 public boolean setStaticMatrix(Matrix matrix) { 361 return nSetStaticMatrix(mNativeRenderNode, matrix.native_instance); 362 } 363 364 /** 365 * Set the Animation matrix on the display list. This matrix exists if an Animation is 366 * currently playing on a View, and is set on the display list during at draw() time. When 367 * the Animation finishes, the matrix should be cleared by sending <code>null</code> 368 * for the matrix parameter. 369 * 370 * @param matrix The matrix, null indicates that the matrix should be cleared. 371 */ 372 public boolean setAnimationMatrix(Matrix matrix) { 373 return nSetAnimationMatrix(mNativeRenderNode, 374 (matrix != null) ? matrix.native_instance : 0); 375 } 376 377 /** 378 * Sets the translucency level for the display list. 379 * 380 * @param alpha The translucency of the display list, must be a value between 0.0f and 1.0f 381 * 382 * @see View#setAlpha(float) 383 * @see #getAlpha() 384 */ 385 public boolean setAlpha(float alpha) { 386 return nSetAlpha(mNativeRenderNode, alpha); 387 } 388 389 /** 390 * Returns the translucency level of this display list. 391 * 392 * @return A value between 0.0f and 1.0f 393 * 394 * @see #setAlpha(float) 395 */ 396 public float getAlpha() { 397 return nGetAlpha(mNativeRenderNode); 398 } 399 400 /** 401 * Sets whether the display list renders content which overlaps. Non-overlapping rendering 402 * can use a fast path for alpha that avoids rendering to an offscreen buffer. By default 403 * display lists consider they do not have overlapping content. 404 * 405 * @param hasOverlappingRendering False if the content is guaranteed to be non-overlapping, 406 * true otherwise. 407 * 408 * @see android.view.View#hasOverlappingRendering() 409 * @see #hasOverlappingRendering() 410 */ 411 public boolean setHasOverlappingRendering(boolean hasOverlappingRendering) { 412 return nSetHasOverlappingRendering(mNativeRenderNode, hasOverlappingRendering); 413 } 414 415 /** 416 * Indicates whether the content of this display list overlaps. 417 * 418 * @return True if this display list renders content which overlaps, false otherwise. 419 * 420 * @see #setHasOverlappingRendering(boolean) 421 */ 422 public boolean hasOverlappingRendering() { 423 //noinspection SimplifiableIfStatement 424 return nHasOverlappingRendering(mNativeRenderNode); 425 } 426 427 public boolean setElevation(float lift) { 428 return nSetElevation(mNativeRenderNode, lift); 429 } 430 431 public float getElevation() { 432 return nGetElevation(mNativeRenderNode); 433 } 434 435 /** 436 * Sets the translation value for the display list on the X axis. 437 * 438 * @param translationX The X axis translation value of the display list, in pixels 439 * 440 * @see View#setTranslationX(float) 441 * @see #getTranslationX() 442 */ 443 public boolean setTranslationX(float translationX) { 444 return nSetTranslationX(mNativeRenderNode, translationX); 445 } 446 447 /** 448 * Returns the translation value for this display list on the X axis, in pixels. 449 * 450 * @see #setTranslationX(float) 451 */ 452 public float getTranslationX() { 453 return nGetTranslationX(mNativeRenderNode); 454 } 455 456 /** 457 * Sets the translation value for the display list on the Y axis. 458 * 459 * @param translationY The Y axis translation value of the display list, in pixels 460 * 461 * @see View#setTranslationY(float) 462 * @see #getTranslationY() 463 */ 464 public boolean setTranslationY(float translationY) { 465 return nSetTranslationY(mNativeRenderNode, translationY); 466 } 467 468 /** 469 * Returns the translation value for this display list on the Y axis, in pixels. 470 * 471 * @see #setTranslationY(float) 472 */ 473 public float getTranslationY() { 474 return nGetTranslationY(mNativeRenderNode); 475 } 476 477 /** 478 * Sets the translation value for the display list on the Z axis. 479 * 480 * @see View#setTranslationZ(float) 481 * @see #getTranslationZ() 482 */ 483 public boolean setTranslationZ(float translationZ) { 484 return nSetTranslationZ(mNativeRenderNode, translationZ); 485 } 486 487 /** 488 * Returns the translation value for this display list on the Z axis. 489 * 490 * @see #setTranslationZ(float) 491 */ 492 public float getTranslationZ() { 493 return nGetTranslationZ(mNativeRenderNode); 494 } 495 496 /** 497 * Sets the rotation value for the display list around the Z axis. 498 * 499 * @param rotation The rotation value of the display list, in degrees 500 * 501 * @see View#setRotation(float) 502 * @see #getRotation() 503 */ 504 public boolean setRotation(float rotation) { 505 return nSetRotation(mNativeRenderNode, rotation); 506 } 507 508 /** 509 * Returns the rotation value for this display list around the Z axis, in degrees. 510 * 511 * @see #setRotation(float) 512 */ 513 public float getRotation() { 514 return nGetRotation(mNativeRenderNode); 515 } 516 517 /** 518 * Sets the rotation value for the display list around the X axis. 519 * 520 * @param rotationX The rotation value of the display list, in degrees 521 * 522 * @see View#setRotationX(float) 523 * @see #getRotationX() 524 */ 525 public boolean setRotationX(float rotationX) { 526 return nSetRotationX(mNativeRenderNode, rotationX); 527 } 528 529 /** 530 * Returns the rotation value for this display list around the X axis, in degrees. 531 * 532 * @see #setRotationX(float) 533 */ 534 public float getRotationX() { 535 return nGetRotationX(mNativeRenderNode); 536 } 537 538 /** 539 * Sets the rotation value for the display list around the Y axis. 540 * 541 * @param rotationY The rotation value of the display list, in degrees 542 * 543 * @see View#setRotationY(float) 544 * @see #getRotationY() 545 */ 546 public boolean setRotationY(float rotationY) { 547 return nSetRotationY(mNativeRenderNode, rotationY); 548 } 549 550 /** 551 * Returns the rotation value for this display list around the Y axis, in degrees. 552 * 553 * @see #setRotationY(float) 554 */ 555 public float getRotationY() { 556 return nGetRotationY(mNativeRenderNode); 557 } 558 559 /** 560 * Sets the scale value for the display list on the X axis. 561 * 562 * @param scaleX The scale value of the display list 563 * 564 * @see View#setScaleX(float) 565 * @see #getScaleX() 566 */ 567 public boolean setScaleX(float scaleX) { 568 return nSetScaleX(mNativeRenderNode, scaleX); 569 } 570 571 /** 572 * Returns the scale value for this display list on the X axis. 573 * 574 * @see #setScaleX(float) 575 */ 576 public float getScaleX() { 577 return nGetScaleX(mNativeRenderNode); 578 } 579 580 /** 581 * Sets the scale value for the display list on the Y axis. 582 * 583 * @param scaleY The scale value of the display list 584 * 585 * @see View#setScaleY(float) 586 * @see #getScaleY() 587 */ 588 public boolean setScaleY(float scaleY) { 589 return nSetScaleY(mNativeRenderNode, scaleY); 590 } 591 592 /** 593 * Returns the scale value for this display list on the Y axis. 594 * 595 * @see #setScaleY(float) 596 */ 597 public float getScaleY() { 598 return nGetScaleY(mNativeRenderNode); 599 } 600 601 /** 602 * Sets the pivot value for the display list on the X axis 603 * 604 * @param pivotX The pivot value of the display list on the X axis, in pixels 605 * 606 * @see View#setPivotX(float) 607 * @see #getPivotX() 608 */ 609 public boolean setPivotX(float pivotX) { 610 return nSetPivotX(mNativeRenderNode, pivotX); 611 } 612 613 /** 614 * Returns the pivot value for this display list on the X axis, in pixels. 615 * 616 * @see #setPivotX(float) 617 */ 618 public float getPivotX() { 619 return nGetPivotX(mNativeRenderNode); 620 } 621 622 /** 623 * Sets the pivot value for the display list on the Y axis 624 * 625 * @param pivotY The pivot value of the display list on the Y axis, in pixels 626 * 627 * @see View#setPivotY(float) 628 * @see #getPivotY() 629 */ 630 public boolean setPivotY(float pivotY) { 631 return nSetPivotY(mNativeRenderNode, pivotY); 632 } 633 634 /** 635 * Returns the pivot value for this display list on the Y axis, in pixels. 636 * 637 * @see #setPivotY(float) 638 */ 639 public float getPivotY() { 640 return nGetPivotY(mNativeRenderNode); 641 } 642 643 public boolean isPivotExplicitlySet() { 644 return nIsPivotExplicitlySet(mNativeRenderNode); 645 } 646 647 /** 648 * Sets the camera distance for the display list. Refer to 649 * {@link View#setCameraDistance(float)} for more information on how to 650 * use this property. 651 * 652 * @param distance The distance in Z of the camera of the display list 653 * 654 * @see View#setCameraDistance(float) 655 * @see #getCameraDistance() 656 */ 657 public boolean setCameraDistance(float distance) { 658 return nSetCameraDistance(mNativeRenderNode, distance); 659 } 660 661 /** 662 * Returns the distance in Z of the camera of the display list. 663 * 664 * @see #setCameraDistance(float) 665 */ 666 public float getCameraDistance() { 667 return nGetCameraDistance(mNativeRenderNode); 668 } 669 670 /** 671 * Sets the left position for the display list. 672 * 673 * @param left The left position, in pixels, of the display list 674 * 675 * @see View#setLeft(int) 676 */ 677 public boolean setLeft(int left) { 678 return nSetLeft(mNativeRenderNode, left); 679 } 680 681 /** 682 * Sets the top position for the display list. 683 * 684 * @param top The top position, in pixels, of the display list 685 * 686 * @see View#setTop(int) 687 */ 688 public boolean setTop(int top) { 689 return nSetTop(mNativeRenderNode, top); 690 } 691 692 /** 693 * Sets the right position for the display list. 694 * 695 * @param right The right position, in pixels, of the display list 696 * 697 * @see View#setRight(int) 698 */ 699 public boolean setRight(int right) { 700 return nSetRight(mNativeRenderNode, right); 701 } 702 703 /** 704 * Sets the bottom position for the display list. 705 * 706 * @param bottom The bottom position, in pixels, of the display list 707 * 708 * @see View#setBottom(int) 709 */ 710 public boolean setBottom(int bottom) { 711 return nSetBottom(mNativeRenderNode, bottom); 712 } 713 714 /** 715 * Sets the left and top positions for the display list 716 * 717 * @param left The left position of the display list, in pixels 718 * @param top The top position of the display list, in pixels 719 * @param right The right position of the display list, in pixels 720 * @param bottom The bottom position of the display list, in pixels 721 * 722 * @see View#setLeft(int) 723 * @see View#setTop(int) 724 * @see View#setRight(int) 725 * @see View#setBottom(int) 726 */ 727 public boolean setLeftTopRightBottom(int left, int top, int right, int bottom) { 728 return nSetLeftTopRightBottom(mNativeRenderNode, left, top, right, bottom); 729 } 730 731 /** 732 * Offsets the left and right positions for the display list 733 * 734 * @param offset The amount that the left and right positions of the display 735 * list are offset, in pixels 736 * 737 * @see View#offsetLeftAndRight(int) 738 */ 739 public boolean offsetLeftAndRight(int offset) { 740 return nOffsetLeftAndRight(mNativeRenderNode, offset); 741 } 742 743 /** 744 * Offsets the top and bottom values for the display list 745 * 746 * @param offset The amount that the top and bottom positions of the display 747 * list are offset, in pixels 748 * 749 * @see View#offsetTopAndBottom(int) 750 */ 751 public boolean offsetTopAndBottom(int offset) { 752 return nOffsetTopAndBottom(mNativeRenderNode, offset); 753 } 754 755 /** 756 * Outputs the display list to the log. This method exists for use by 757 * tools to output display lists for selected nodes to the log. 758 */ 759 public void output() { 760 nOutput(mNativeRenderNode); 761 } 762 763 /** 764 * Gets the size of the DisplayList for debug purposes. 765 */ 766 public int getDebugSize() { 767 return nGetDebugSize(mNativeRenderNode); 768 } 769 770 /** 771 * Called by native when the passed displaylist is removed from the draw tree 772 */ 773 void onRenderNodeDetached() { 774 discardDisplayList(); 775 if (mOwningView != null) { 776 mOwningView.onRenderNodeDetached(this); 777 } 778 } 779 780 /////////////////////////////////////////////////////////////////////////// 781 // Animations 782 /////////////////////////////////////////////////////////////////////////// 783 784 public void addAnimator(RenderNodeAnimator animator) { 785 if (mOwningView == null || mOwningView.mAttachInfo == null) { 786 throw new IllegalStateException("Cannot start this animator on a detached view!"); 787 } 788 nAddAnimator(mNativeRenderNode, animator.getNativeAnimator()); 789 mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this); 790 } 791 792 public boolean isAttached() { 793 return mOwningView != null && mOwningView.mAttachInfo != null; 794 } 795 796 public void registerVectorDrawableAnimator( 797 AnimatedVectorDrawable.VectorDrawableAnimatorRT animatorSet) { 798 if (mOwningView == null || mOwningView.mAttachInfo == null) { 799 throw new IllegalStateException("Cannot start this animator on a detached view!"); 800 } 801 mOwningView.mAttachInfo.mViewRootImpl.registerVectorDrawableAnimator(animatorSet); 802 } 803 804 public void endAllAnimators() { 805 nEndAllAnimators(mNativeRenderNode); 806 } 807 808 /////////////////////////////////////////////////////////////////////////// 809 // Native methods 810 /////////////////////////////////////////////////////////////////////////// 811 812 // Intentionally not static because it acquires a reference to 'this' 813 private native long nCreate(String name); 814 815 private static native void nDestroyRenderNode(long renderNode); 816 private static native void nSetDisplayList(long renderNode, long newData); 817 818 // Matrix 819 820 private static native void nGetTransformMatrix(long renderNode, long nativeMatrix); 821 private static native void nGetInverseTransformMatrix(long renderNode, long nativeMatrix); 822 private static native boolean nHasIdentityMatrix(long renderNode); 823 824 // Properties 825 826 private static native boolean nOffsetTopAndBottom(long renderNode, int offset); 827 private static native boolean nOffsetLeftAndRight(long renderNode, int offset); 828 private static native boolean nSetLeftTopRightBottom(long renderNode, int left, int top, 829 int right, int bottom); 830 private static native boolean nSetBottom(long renderNode, int bottom); 831 private static native boolean nSetRight(long renderNode, int right); 832 private static native boolean nSetTop(long renderNode, int top); 833 private static native boolean nSetLeft(long renderNode, int left); 834 private static native boolean nSetCameraDistance(long renderNode, float distance); 835 private static native boolean nSetPivotY(long renderNode, float pivotY); 836 private static native boolean nSetPivotX(long renderNode, float pivotX); 837 private static native boolean nSetLayerType(long renderNode, int layerType); 838 private static native boolean nSetLayerPaint(long renderNode, long paint); 839 private static native boolean nSetClipToBounds(long renderNode, boolean clipToBounds); 840 private static native boolean nSetClipBounds(long renderNode, int left, int top, 841 int right, int bottom); 842 private static native boolean nSetClipBoundsEmpty(long renderNode); 843 private static native boolean nSetProjectBackwards(long renderNode, boolean shouldProject); 844 private static native boolean nSetProjectionReceiver(long renderNode, boolean shouldRecieve); 845 private static native boolean nSetOutlineRoundRect(long renderNode, int left, int top, 846 int right, int bottom, float radius, float alpha); 847 private static native boolean nSetOutlineConvexPath(long renderNode, long nativePath, 848 float alpha); 849 private static native boolean nSetOutlineEmpty(long renderNode); 850 private static native boolean nSetOutlineNone(long renderNode); 851 private static native boolean nHasShadow(long renderNode); 852 private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline); 853 private static native boolean nSetRevealClip(long renderNode, 854 boolean shouldClip, float x, float y, float radius); 855 private static native boolean nSetAlpha(long renderNode, float alpha); 856 private static native boolean nSetHasOverlappingRendering(long renderNode, 857 boolean hasOverlappingRendering); 858 private static native boolean nSetElevation(long renderNode, float lift); 859 private static native boolean nSetTranslationX(long renderNode, float translationX); 860 private static native boolean nSetTranslationY(long renderNode, float translationY); 861 private static native boolean nSetTranslationZ(long renderNode, float translationZ); 862 private static native boolean nSetRotation(long renderNode, float rotation); 863 private static native boolean nSetRotationX(long renderNode, float rotationX); 864 private static native boolean nSetRotationY(long renderNode, float rotationY); 865 private static native boolean nSetScaleX(long renderNode, float scaleX); 866 private static native boolean nSetScaleY(long renderNode, float scaleY); 867 private static native boolean nSetStaticMatrix(long renderNode, long nativeMatrix); 868 private static native boolean nSetAnimationMatrix(long renderNode, long animationMatrix); 869 870 private static native boolean nHasOverlappingRendering(long renderNode); 871 private static native boolean nGetClipToOutline(long renderNode); 872 private static native float nGetAlpha(long renderNode); 873 private static native float nGetCameraDistance(long renderNode); 874 private static native float nGetScaleX(long renderNode); 875 private static native float nGetScaleY(long renderNode); 876 private static native float nGetElevation(long renderNode); 877 private static native float nGetTranslationX(long renderNode); 878 private static native float nGetTranslationY(long renderNode); 879 private static native float nGetTranslationZ(long renderNode); 880 private static native float nGetRotation(long renderNode); 881 private static native float nGetRotationX(long renderNode); 882 private static native float nGetRotationY(long renderNode); 883 private static native boolean nIsPivotExplicitlySet(long renderNode); 884 private static native float nGetPivotX(long renderNode); 885 private static native float nGetPivotY(long renderNode); 886 private static native void nOutput(long renderNode); 887 private static native int nGetDebugSize(long renderNode); 888 889 private static native void nRequestPositionUpdates(long renderNode, SurfaceView callback); 890 891 /////////////////////////////////////////////////////////////////////////// 892 // Animations 893 /////////////////////////////////////////////////////////////////////////// 894 895 private static native void nAddAnimator(long renderNode, long animatorPtr); 896 private static native void nEndAllAnimators(long renderNode); 897 898 /////////////////////////////////////////////////////////////////////////// 899 // Finalization 900 /////////////////////////////////////////////////////////////////////////// 901 902 @Override 903 protected void finalize() throws Throwable { 904 try { 905 nDestroyRenderNode(mNativeRenderNode); 906 } finally { 907 super.finalize(); 908 } 909 } 910 } 911