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 RenderNode(String name, View owningView)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 */ RenderNode(long nativePtr)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 */ create(String name, @Nullable View owningView)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 */ adopt(long nativePtr)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 */ start(int width, int height)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 */ end(DisplayListCanvas canvas)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 */ discardDisplayList()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 */ isValid()229 public boolean isValid() { return mValid; } 230 getNativeDisplayList()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 hasIdentityMatrix()242 public boolean hasIdentityMatrix() { 243 return nHasIdentityMatrix(mNativeRenderNode); 244 } 245 getMatrix(@onNull Matrix outMatrix)246 public void getMatrix(@NonNull Matrix outMatrix) { 247 nGetTransformMatrix(mNativeRenderNode, outMatrix.native_instance); 248 } 249 getInverseMatrix(@onNull Matrix outMatrix)250 public void getInverseMatrix(@NonNull Matrix outMatrix) { 251 nGetInverseTransformMatrix(mNativeRenderNode, outMatrix.native_instance); 252 } 253 254 /////////////////////////////////////////////////////////////////////////// 255 // RenderProperty Setters 256 /////////////////////////////////////////////////////////////////////////// 257 setLayerType(int layerType)258 public boolean setLayerType(int layerType) { 259 return nSetLayerType(mNativeRenderNode, layerType); 260 } 261 setLayerPaint(@ullable Paint paint)262 public boolean setLayerPaint(@Nullable Paint paint) { 263 return nSetLayerPaint(mNativeRenderNode, paint != null ? paint.getNativeInstance() : 0); 264 } 265 setClipBounds(@ullable Rect rect)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 */ setClipToBounds(boolean clipToBounds)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 */ setProjectBackwards(boolean shouldProject)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 */ setProjectionReceiver(boolean shouldRecieve)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 */ setOutline(@ullable Outline outline)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 hasShadow()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 */ setClipToOutline(boolean clipToOutline)338 public boolean setClipToOutline(boolean clipToOutline) { 339 return nSetClipToOutline(mNativeRenderNode, clipToOutline); 340 } 341 getClipToOutline()342 public boolean getClipToOutline() { 343 return nGetClipToOutline(mNativeRenderNode); 344 } 345 346 /** 347 * Controls the RenderNode's circular reveal clip. 348 */ setRevealClip(boolean shouldClip, float x, float y, float radius)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 */ setStaticMatrix(Matrix matrix)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 */ setAnimationMatrix(Matrix matrix)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 */ setAlpha(float alpha)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 */ getAlpha()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 */ setHasOverlappingRendering(boolean hasOverlappingRendering)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 */ hasOverlappingRendering()422 public boolean hasOverlappingRendering() { 423 //noinspection SimplifiableIfStatement 424 return nHasOverlappingRendering(mNativeRenderNode); 425 } 426 setElevation(float lift)427 public boolean setElevation(float lift) { 428 return nSetElevation(mNativeRenderNode, lift); 429 } 430 getElevation()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 */ setTranslationX(float translationX)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 */ getTranslationX()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 */ setTranslationY(float translationY)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 */ getTranslationY()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 */ setTranslationZ(float translationZ)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 */ getTranslationZ()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 */ setRotation(float rotation)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 */ getRotation()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 */ setRotationX(float rotationX)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 */ getRotationX()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 */ setRotationY(float rotationY)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 */ getRotationY()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 */ setScaleX(float scaleX)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 */ getScaleX()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 */ setScaleY(float scaleY)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 */ getScaleY()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 */ setPivotX(float pivotX)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 */ getPivotX()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 */ setPivotY(float pivotY)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 */ getPivotY()639 public float getPivotY() { 640 return nGetPivotY(mNativeRenderNode); 641 } 642 isPivotExplicitlySet()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 */ setCameraDistance(float distance)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 */ getCameraDistance()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 */ setLeft(int left)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 */ setTop(int top)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 */ setRight(int right)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 */ setBottom(int bottom)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 */ setLeftTopRightBottom(int left, int top, int right, int bottom)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 */ offsetLeftAndRight(int offset)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 */ offsetTopAndBottom(int offset)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 */ output()759 public void output() { 760 nOutput(mNativeRenderNode); 761 } 762 763 /** 764 * Gets the size of the DisplayList for debug purposes. 765 */ getDebugSize()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 */ onRenderNodeDetached()773 void onRenderNodeDetached() { 774 discardDisplayList(); 775 if (mOwningView != null) { 776 mOwningView.onRenderNodeDetached(this); 777 } 778 } 779 780 /////////////////////////////////////////////////////////////////////////// 781 // Animations 782 /////////////////////////////////////////////////////////////////////////// 783 addAnimator(RenderNodeAnimator animator)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 isAttached()792 public boolean isAttached() { 793 return mOwningView != null && mOwningView.mAttachInfo != null; 794 } 795 addAnimator(AnimatedVectorDrawable.VectorDrawableAnimatorRT animatorSet)796 public void addAnimator(AnimatedVectorDrawable.VectorDrawableAnimatorRT animatorSet) { 797 if (mOwningView == null || mOwningView.mAttachInfo == null) { 798 throw new IllegalStateException("Cannot start this animator on a detached view!"); 799 } 800 nAddAnimator(mNativeRenderNode, animatorSet.getAnimatorNativePtr()); 801 mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this); 802 } 803 endAllAnimators()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' nCreate(String name)813 private native long nCreate(String name); 814 nDestroyRenderNode(long renderNode)815 private static native void nDestroyRenderNode(long renderNode); nSetDisplayList(long renderNode, long newData)816 private static native void nSetDisplayList(long renderNode, long newData); 817 818 // Matrix 819 nGetTransformMatrix(long renderNode, long nativeMatrix)820 private static native void nGetTransformMatrix(long renderNode, long nativeMatrix); nGetInverseTransformMatrix(long renderNode, long nativeMatrix)821 private static native void nGetInverseTransformMatrix(long renderNode, long nativeMatrix); nHasIdentityMatrix(long renderNode)822 private static native boolean nHasIdentityMatrix(long renderNode); 823 824 // Properties 825 nOffsetTopAndBottom(long renderNode, int offset)826 private static native boolean nOffsetTopAndBottom(long renderNode, int offset); nOffsetLeftAndRight(long renderNode, int offset)827 private static native boolean nOffsetLeftAndRight(long renderNode, int offset); nSetLeftTopRightBottom(long renderNode, int left, int top, int right, int bottom)828 private static native boolean nSetLeftTopRightBottom(long renderNode, int left, int top, 829 int right, int bottom); nSetBottom(long renderNode, int bottom)830 private static native boolean nSetBottom(long renderNode, int bottom); nSetRight(long renderNode, int right)831 private static native boolean nSetRight(long renderNode, int right); nSetTop(long renderNode, int top)832 private static native boolean nSetTop(long renderNode, int top); nSetLeft(long renderNode, int left)833 private static native boolean nSetLeft(long renderNode, int left); nSetCameraDistance(long renderNode, float distance)834 private static native boolean nSetCameraDistance(long renderNode, float distance); nSetPivotY(long renderNode, float pivotY)835 private static native boolean nSetPivotY(long renderNode, float pivotY); nSetPivotX(long renderNode, float pivotX)836 private static native boolean nSetPivotX(long renderNode, float pivotX); nSetLayerType(long renderNode, int layerType)837 private static native boolean nSetLayerType(long renderNode, int layerType); nSetLayerPaint(long renderNode, long paint)838 private static native boolean nSetLayerPaint(long renderNode, long paint); nSetClipToBounds(long renderNode, boolean clipToBounds)839 private static native boolean nSetClipToBounds(long renderNode, boolean clipToBounds); nSetClipBounds(long renderNode, int left, int top, int right, int bottom)840 private static native boolean nSetClipBounds(long renderNode, int left, int top, 841 int right, int bottom); nSetClipBoundsEmpty(long renderNode)842 private static native boolean nSetClipBoundsEmpty(long renderNode); nSetProjectBackwards(long renderNode, boolean shouldProject)843 private static native boolean nSetProjectBackwards(long renderNode, boolean shouldProject); nSetProjectionReceiver(long renderNode, boolean shouldRecieve)844 private static native boolean nSetProjectionReceiver(long renderNode, boolean shouldRecieve); nSetOutlineRoundRect(long renderNode, int left, int top, int right, int bottom, float radius, float alpha)845 private static native boolean nSetOutlineRoundRect(long renderNode, int left, int top, 846 int right, int bottom, float radius, float alpha); nSetOutlineConvexPath(long renderNode, long nativePath, float alpha)847 private static native boolean nSetOutlineConvexPath(long renderNode, long nativePath, 848 float alpha); nSetOutlineEmpty(long renderNode)849 private static native boolean nSetOutlineEmpty(long renderNode); nSetOutlineNone(long renderNode)850 private static native boolean nSetOutlineNone(long renderNode); nHasShadow(long renderNode)851 private static native boolean nHasShadow(long renderNode); nSetClipToOutline(long renderNode, boolean clipToOutline)852 private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline); nSetRevealClip(long renderNode, boolean shouldClip, float x, float y, float radius)853 private static native boolean nSetRevealClip(long renderNode, 854 boolean shouldClip, float x, float y, float radius); nSetAlpha(long renderNode, float alpha)855 private static native boolean nSetAlpha(long renderNode, float alpha); nSetHasOverlappingRendering(long renderNode, boolean hasOverlappingRendering)856 private static native boolean nSetHasOverlappingRendering(long renderNode, 857 boolean hasOverlappingRendering); nSetElevation(long renderNode, float lift)858 private static native boolean nSetElevation(long renderNode, float lift); nSetTranslationX(long renderNode, float translationX)859 private static native boolean nSetTranslationX(long renderNode, float translationX); nSetTranslationY(long renderNode, float translationY)860 private static native boolean nSetTranslationY(long renderNode, float translationY); nSetTranslationZ(long renderNode, float translationZ)861 private static native boolean nSetTranslationZ(long renderNode, float translationZ); nSetRotation(long renderNode, float rotation)862 private static native boolean nSetRotation(long renderNode, float rotation); nSetRotationX(long renderNode, float rotationX)863 private static native boolean nSetRotationX(long renderNode, float rotationX); nSetRotationY(long renderNode, float rotationY)864 private static native boolean nSetRotationY(long renderNode, float rotationY); nSetScaleX(long renderNode, float scaleX)865 private static native boolean nSetScaleX(long renderNode, float scaleX); nSetScaleY(long renderNode, float scaleY)866 private static native boolean nSetScaleY(long renderNode, float scaleY); nSetStaticMatrix(long renderNode, long nativeMatrix)867 private static native boolean nSetStaticMatrix(long renderNode, long nativeMatrix); nSetAnimationMatrix(long renderNode, long animationMatrix)868 private static native boolean nSetAnimationMatrix(long renderNode, long animationMatrix); 869 nHasOverlappingRendering(long renderNode)870 private static native boolean nHasOverlappingRendering(long renderNode); nGetClipToOutline(long renderNode)871 private static native boolean nGetClipToOutline(long renderNode); nGetAlpha(long renderNode)872 private static native float nGetAlpha(long renderNode); nGetCameraDistance(long renderNode)873 private static native float nGetCameraDistance(long renderNode); nGetScaleX(long renderNode)874 private static native float nGetScaleX(long renderNode); nGetScaleY(long renderNode)875 private static native float nGetScaleY(long renderNode); nGetElevation(long renderNode)876 private static native float nGetElevation(long renderNode); nGetTranslationX(long renderNode)877 private static native float nGetTranslationX(long renderNode); nGetTranslationY(long renderNode)878 private static native float nGetTranslationY(long renderNode); nGetTranslationZ(long renderNode)879 private static native float nGetTranslationZ(long renderNode); nGetRotation(long renderNode)880 private static native float nGetRotation(long renderNode); nGetRotationX(long renderNode)881 private static native float nGetRotationX(long renderNode); nGetRotationY(long renderNode)882 private static native float nGetRotationY(long renderNode); nIsPivotExplicitlySet(long renderNode)883 private static native boolean nIsPivotExplicitlySet(long renderNode); nGetPivotX(long renderNode)884 private static native float nGetPivotX(long renderNode); nGetPivotY(long renderNode)885 private static native float nGetPivotY(long renderNode); nOutput(long renderNode)886 private static native void nOutput(long renderNode); nGetDebugSize(long renderNode)887 private static native int nGetDebugSize(long renderNode); 888 nRequestPositionUpdates(long renderNode, SurfaceView callback)889 private static native void nRequestPositionUpdates(long renderNode, SurfaceView callback); 890 891 /////////////////////////////////////////////////////////////////////////// 892 // Animations 893 /////////////////////////////////////////////////////////////////////////// 894 nAddAnimator(long renderNode, long animatorPtr)895 private static native void nAddAnimator(long renderNode, long animatorPtr); nEndAllAnimators(long renderNode)896 private static native void nEndAllAnimators(long renderNode); 897 898 /////////////////////////////////////////////////////////////////////////// 899 // Finalization 900 /////////////////////////////////////////////////////////////////////////// 901 902 @Override finalize()903 protected void finalize() throws Throwable { 904 try { 905 nDestroyRenderNode(mNativeRenderNode); 906 } finally { 907 super.finalize(); 908 } 909 } 910 } 911