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