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