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.graphics; 18 19 import android.animation.Animator; 20 import android.annotation.BytesLong; 21 import android.annotation.ColorInt; 22 import android.annotation.FloatRange; 23 import android.annotation.IntDef; 24 import android.annotation.NonNull; 25 import android.annotation.Nullable; 26 import android.graphics.animation.RenderNodeAnimator; 27 import android.view.NativeVectorDrawableAnimator; 28 import android.view.Surface; 29 import android.view.View; 30 31 import com.android.internal.util.ArrayUtils; 32 33 import dalvik.annotation.optimization.CriticalNative; 34 35 import libcore.util.NativeAllocationRegistry; 36 37 import java.lang.annotation.Retention; 38 import java.lang.annotation.RetentionPolicy; 39 import java.lang.ref.WeakReference; 40 41 /** 42 * <p>RenderNode is used to build hardware accelerated rendering hierarchies. Each RenderNode 43 * contains both a display list as well as a set of properties that affect the rendering of the 44 * display list. RenderNodes are used internally for all Views by default and are not typically 45 * used directly.</p> 46 * 47 * <p>RenderNodes are used to divide up the rendering content of a complex scene into smaller 48 * pieces that can then be updated individually more cheaply. Updating part of the scene only needs 49 * to update the display list or properties of a small number of RenderNode instead of redrawing 50 * everything from scratch. A RenderNode only needs its display list re-recorded when its content 51 * alone should be changed. RenderNodes can also be transformed without re-recording the display 52 * list through the transform properties.</p> 53 * 54 * <p>A text editor might for instance store each paragraph into its own RenderNode. 55 * Thus when the user inserts or removes characters, only the display list of the 56 * affected paragraph needs to be recorded again.</p> 57 * 58 * <h3>Hardware acceleration</h3> 59 * <p>RenderNodes can be drawn using a {@link RecordingCanvas}. They are not 60 * supported in software. Always make sure that the {@link android.graphics.Canvas} 61 * you are using to render a display list is hardware accelerated using 62 * {@link android.graphics.Canvas#isHardwareAccelerated()}.</p> 63 * 64 * <h3>Creating a RenderNode</h3> 65 * <pre class="prettyprint"> 66 * RenderNode renderNode = new RenderNode("myRenderNode"); 67 * renderNode.setPosition(0, 0, 50, 50); // Set the size to 50x50 68 * RecordingCanvas canvas = renderNode.beginRecording(); 69 * try { 70 * // Draw with the canvas 71 * canvas.drawRect(...); 72 * } finally { 73 * renderNode.endRecording(); 74 * }</pre> 75 * 76 * <h3>Drawing a RenderNode in a View</h3> 77 * <pre class="prettyprint"> 78 * protected void onDraw(Canvas canvas) { 79 * if (canvas.isHardwareAccelerated()) { 80 * // Check that the RenderNode has a display list, re-recording it if it does not. 81 * if (!myRenderNode.hasDisplayList()) { 82 * updateDisplayList(myRenderNode); 83 * } 84 * // Draw the RenderNode into this canvas. 85 * canvas.drawRenderNode(myRenderNode); 86 * } 87 * }</pre> 88 * 89 * <h3>Releasing resources</h3> 90 * <p>This step is not mandatory but recommended if you want to release resources 91 * held by a display list as soon as possible. Most significantly any bitmaps it may contain.</p> 92 * <pre class="prettyprint"> 93 * // Discards the display list content allowing for any held resources to be released. 94 * // After calling this 95 * renderNode.discardDisplayList();</pre> 96 * 97 * 98 * <h3>Properties</h3> 99 * <p>In addition, a RenderNode offers several properties, such as 100 * {@link #setScaleX(float)} or {@link #setTranslationX(float)}, that can be used to affect all 101 * the drawing commands recorded within. For instance, these properties can be used 102 * to move around a large number of images without re-issuing all the individual 103 * <code>canvas.drawBitmap()</code> calls.</p> 104 * 105 * <pre class="prettyprint"> 106 * private void createDisplayList() { 107 * mRenderNode = new RenderNode("MyRenderNode"); 108 * mRenderNode.setPosition(0, 0, width, height); 109 * RecordingCanvas canvas = mRenderNode.beginRecording(); 110 * try { 111 * for (Bitmap b : mBitmaps) { 112 * canvas.drawBitmap(b, 0.0f, 0.0f, null); 113 * canvas.translate(0.0f, b.getHeight()); 114 * } 115 * } finally { 116 * mRenderNode.endRecording(); 117 * } 118 * } 119 * 120 * protected void onDraw(Canvas canvas) { 121 * if (canvas.isHardwareAccelerated()) 122 * canvas.drawRenderNode(mRenderNode); 123 * } 124 * } 125 * 126 * private void moveContentBy(int x) { 127 * // This will move all the bitmaps recorded inside the display list 128 * // by x pixels to the right and redraw this view. All the commands 129 * // recorded in createDisplayList() won't be re-issued, only onDraw() 130 * // will be invoked and will execute very quickly 131 * mRenderNode.offsetLeftAndRight(x); 132 * invalidate(); 133 * }</pre> 134 * 135 * <p>A few of the properties may at first appear redundant, such as {@link #setElevation(float)} 136 * and {@link #setTranslationZ(float)}. The reason for these duplicates are to allow for a 137 * separation between static & transient usages. For example consider a button that raises from 2dp 138 * to 8dp when pressed. To achieve that an application may decide to setElevation(2dip), and then 139 * on press to animate setTranslationZ to 6dip. Combined this achieves the final desired 8dip 140 * value, but the animation need only concern itself with animating the lift from press without 141 * needing to know the initial starting value. {@link #setTranslationX(float)} and 142 * {@link #setTranslationY(float)} are similarly provided for animation uses despite the functional 143 * overlap with {@link #setPosition(Rect)}. 144 * 145 * <p>The RenderNode's transform matrix is computed at render time as follows: 146 * <pre class="prettyprint"> 147 * Matrix transform = new Matrix(); 148 * transform.setTranslate(renderNode.getTranslationX(), renderNode.getTranslationY()); 149 * transform.preRotate(renderNode.getRotationZ(), 150 * renderNode.getPivotX(), renderNode.getPivotY()); 151 * transform.preScale(renderNode.getScaleX(), renderNode.getScaleY(), 152 * renderNode.getPivotX(), renderNode.getPivotY());</pre> 153 * The current canvas transform matrix, which is translated to the RenderNode's position, 154 * is then multiplied by the RenderNode's transform matrix. Therefore the ordering of calling 155 * property setters does not affect the result. That is to say that: 156 * 157 * <pre class="prettyprint"> 158 * renderNode.setTranslationX(100); 159 * renderNode.setScaleX(100);</pre> 160 * 161 * is equivalent to: 162 * 163 * <pre class="prettyprint"> 164 * renderNode.setScaleX(100); 165 * renderNode.setTranslationX(100);</pre> 166 * 167 * <h3>Threading</h3> 168 * <p>RenderNode may be created and used on any thread but they are not thread-safe. Only 169 * a single thread may interact with a RenderNode at any given time. It is critical 170 * that the RenderNode is only used on the same thread it is drawn with. For example when using 171 * RenderNode with a custom View, then that RenderNode must only be used from the UI thread.</p> 172 * 173 * <h3>When to re-render</h3> 174 * <p>Many of the RenderNode mutation methods, such as {@link #setTranslationX(float)}, return 175 * a boolean indicating if the value actually changed or not. This is useful in detecting 176 * if a new frame should be rendered or not. A typical usage would look like: 177 * <pre class="prettyprint"> 178 * public void translateTo(int x, int y) { 179 * boolean needsUpdate = myRenderNode.setTranslationX(x); 180 * needsUpdate |= myRenderNode.setTranslationY(y); 181 * if (needsUpdate) { 182 * myOwningView.invalidate(); 183 * } 184 * }</pre> 185 * This is marginally faster than doing a more explicit up-front check if the value changed by 186 * comparing the desired value against {@link #getTranslationX()} as it minimizes JNI transitions. 187 * The actual mechanism of requesting a new frame to be rendered will depend on how this 188 * RenderNode is being drawn. If it's drawn to a containing View, as in the above snippet, 189 * then simply invalidating that View works. If instead the RenderNode is being drawn to a Canvas 190 * directly such as with {@link Surface#lockHardwareCanvas()} then a new frame needs to be drawn 191 * by calling {@link Surface#lockHardwareCanvas()}, re-drawing the root RenderNode or whatever 192 * top-level content is desired, and finally calling {@link Surface#unlockCanvasAndPost(Canvas)}. 193 * </p> 194 */ 195 @android.ravenwood.annotation.RavenwoodKeepWholeClass 196 public final class RenderNode { 197 198 // Use a Holder to allow static initialization in the boot image. 199 private static class NoImagePreloadHolder { 200 public static final NativeAllocationRegistry sRegistry = 201 NativeAllocationRegistry.createMalloced( 202 RenderNode.class.getClassLoader(), nGetNativeFinalizer()); 203 } 204 205 /** 206 * Not for general use; use only if you are ThreadedRenderer or RecordingCanvas. 207 * 208 * @hide 209 */ 210 public final long mNativeRenderNode; 211 private final AnimationHost mAnimationHost; 212 private RecordingCanvas mCurrentRecordingCanvas; 213 214 // Will be null if not currently registered 215 @Nullable 216 private CompositePositionUpdateListener mCompositePositionUpdateListener; 217 218 /** 219 * Creates a new RenderNode that can be used to record batches of 220 * drawing operations, and store / apply render properties when drawn. 221 * 222 * @param name The name of the RenderNode, used for debugging purpose. May be null. 223 */ RenderNode(@ullable String name)224 public RenderNode(@Nullable String name) { 225 this(name, null); 226 } 227 RenderNode(String name, AnimationHost animationHost)228 private RenderNode(String name, AnimationHost animationHost) { 229 mNativeRenderNode = nCreate(name); 230 NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativeRenderNode); 231 mAnimationHost = animationHost; 232 } 233 234 /** 235 * @see RenderNode#adopt(long) 236 */ RenderNode(long nativePtr)237 private RenderNode(long nativePtr) { 238 mNativeRenderNode = nativePtr; 239 NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativeRenderNode); 240 mAnimationHost = null; 241 } 242 243 /** @hide */ create(String name, @Nullable AnimationHost animationHost)244 public static RenderNode create(String name, @Nullable AnimationHost animationHost) { 245 return new RenderNode(name, animationHost); 246 } 247 248 /** 249 * Adopts an existing native render node. 250 * 251 * Note: This will *NOT* incRef() on the native object, however it will 252 * decRef() when it is destroyed. The caller should have already incRef'd it 253 * 254 * @hide 255 */ adopt(long nativePtr)256 public static RenderNode adopt(long nativePtr) { 257 return new RenderNode(nativePtr); 258 } 259 260 /** 261 * Listens for RenderNode position updates for synchronous window movement. 262 * 263 * This is not suitable for generic position listening, it is only designed & intended 264 * for use by things which require external position events like SurfaceView, PopupWindow, etc.. 265 * 266 * @hide 267 */ 268 public interface PositionUpdateListener { 269 /** 270 * Called by native by a Rendering Worker thread to update window position 271 * 272 * @hide 273 */ positionChanged(long frameNumber, int left, int top, int right, int bottom)274 void positionChanged(long frameNumber, int left, int top, int right, int bottom); 275 276 /** 277 * Called by native by a Rendering Worker thread to update window position; includes 278 * the local rect that represents the clipped area of the RenderNode's bounds. 279 * 280 * @hide 281 */ positionChanged(long frameNumber, int left, int top, int right, int bottom, int clipLeft, int clipTop, int clipRight, int clipBottom, int nodeWidth, int nodeHeight)282 default void positionChanged(long frameNumber, int left, int top, int right, int bottom, 283 int clipLeft, int clipTop, int clipRight, int clipBottom, 284 int nodeWidth, int nodeHeight) { 285 positionChanged(frameNumber, left, top, right, bottom); 286 } 287 288 /** 289 * Called by JNI 290 * 291 * @hide */ callPositionChanged(WeakReference<PositionUpdateListener> weakListener, long frameNumber, int left, int top, int right, int bottom)292 static boolean callPositionChanged(WeakReference<PositionUpdateListener> weakListener, 293 long frameNumber, int left, int top, int right, int bottom) { 294 final PositionUpdateListener listener = weakListener.get(); 295 if (listener != null) { 296 listener.positionChanged(frameNumber, left, top, right, bottom); 297 return true; 298 } else { 299 return false; 300 } 301 } 302 303 /** 304 * Called by JNI 305 * 306 * @hide */ callPositionChanged2(WeakReference<PositionUpdateListener> weakListener, long frameNumber, int left, int top, int right, int bottom, int clipLeft, int clipTop, int clipRight, int clipBottom, int nodeWidth, int nodeHeight)307 static boolean callPositionChanged2(WeakReference<PositionUpdateListener> weakListener, 308 long frameNumber, int left, int top, int right, int bottom, 309 int clipLeft, int clipTop, int clipRight, int clipBottom, 310 int nodeWidth, int nodeHeight) { 311 final PositionUpdateListener listener = weakListener.get(); 312 if (listener != null) { 313 listener.positionChanged(frameNumber, left, top, right, bottom, clipLeft, 314 clipTop, clipRight, clipBottom, nodeWidth, nodeHeight); 315 return true; 316 } else { 317 return false; 318 } 319 } 320 321 /** 322 * Call to apply a stretch effect to any child SurfaceControl layers 323 * 324 * TODO: Fold this into positionChanged & have HWUI do the ASurfaceControl calls? 325 * (njawad) update to consume different stretch parameters for horizontal/vertical stretch 326 * to ensure SkiaGLRenderEngine can also apply the same stretch to a surface 327 * 328 * @hide 329 */ applyStretch(long frameNumber, float width, float height, float vecX, float vecY, float maxStretchX, float maxStretchY, float childRelativeLeft, float childRelativeTop, float childRelativeRight, float childRelativeBottom)330 default void applyStretch(long frameNumber, float width, float height, 331 float vecX, float vecY, 332 float maxStretchX, float maxStretchY, float childRelativeLeft, 333 float childRelativeTop, float childRelativeRight, float childRelativeBottom) { } 334 335 /** 336 * Called by JNI 337 * 338 * @hide */ callApplyStretch(WeakReference<PositionUpdateListener> weakListener, long frameNumber, float width, float height, float vecX, float vecY, float maxStretchX, float maxStretchY, float childRelativeLeft, float childRelativeTop, float childRelativeRight, float childRelativeBottom)339 static boolean callApplyStretch(WeakReference<PositionUpdateListener> weakListener, 340 long frameNumber, float width, float height, 341 float vecX, float vecY, 342 float maxStretchX, float maxStretchY, float childRelativeLeft, 343 float childRelativeTop, float childRelativeRight, float childRelativeBottom) { 344 final PositionUpdateListener listener = weakListener.get(); 345 if (listener != null) { 346 listener.applyStretch(frameNumber, width, height, vecX, vecY, maxStretchX, 347 maxStretchY, childRelativeLeft, childRelativeTop, childRelativeRight, 348 childRelativeBottom); 349 return true; 350 } else { 351 return false; 352 } 353 } 354 355 /** 356 * Called by native on RenderThread to notify that the view is no longer in the 357 * draw tree. UI thread is blocked at this point. 358 * 359 * @hide 360 */ positionLost(long frameNumber)361 void positionLost(long frameNumber); 362 363 /** 364 * Called by JNI 365 * 366 * @hide */ callPositionLost(WeakReference<PositionUpdateListener> weakListener, long frameNumber)367 static boolean callPositionLost(WeakReference<PositionUpdateListener> weakListener, 368 long frameNumber) { 369 final PositionUpdateListener listener = weakListener.get(); 370 if (listener != null) { 371 listener.positionLost(frameNumber); 372 return true; 373 } else { 374 return false; 375 } 376 } 377 378 } 379 380 private static final class CompositePositionUpdateListener implements PositionUpdateListener { 381 private final PositionUpdateListener[] mListeners; 382 private static final PositionUpdateListener[] sEmpty = new PositionUpdateListener[0]; 383 CompositePositionUpdateListener(PositionUpdateListener... listeners)384 CompositePositionUpdateListener(PositionUpdateListener... listeners) { 385 mListeners = listeners != null ? listeners : sEmpty; 386 } 387 with(PositionUpdateListener listener)388 public CompositePositionUpdateListener with(PositionUpdateListener listener) { 389 return new CompositePositionUpdateListener( 390 ArrayUtils.appendElement(PositionUpdateListener.class, mListeners, listener)); 391 } 392 without(PositionUpdateListener listener)393 public CompositePositionUpdateListener without(PositionUpdateListener listener) { 394 return new CompositePositionUpdateListener( 395 ArrayUtils.removeElement(PositionUpdateListener.class, mListeners, listener)); 396 } 397 398 @Override positionChanged(long frameNumber, int left, int top, int right, int bottom)399 public void positionChanged(long frameNumber, int left, int top, int right, int bottom) { 400 for (PositionUpdateListener pul : mListeners) { 401 pul.positionChanged(frameNumber, left, top, right, bottom); 402 } 403 } 404 405 @Override positionChanged(long frameNumber, int left, int top, int right, int bottom, int clipLeft, int clipTop, int clipRight, int clipBottom, int nodeWidth, int nodeHeight)406 public void positionChanged(long frameNumber, int left, int top, int right, int bottom, 407 int clipLeft, int clipTop, int clipRight, int clipBottom, 408 int nodeWidth, int nodeHeight) { 409 for (PositionUpdateListener pul : mListeners) { 410 pul.positionChanged(frameNumber, left, top, right, bottom, clipLeft, clipTop, 411 clipRight, clipBottom, nodeWidth, nodeHeight); 412 } 413 } 414 415 @Override positionLost(long frameNumber)416 public void positionLost(long frameNumber) { 417 for (PositionUpdateListener pul : mListeners) { 418 pul.positionLost(frameNumber); 419 } 420 } 421 422 @Override applyStretch(long frameNumber, float width, float height, float vecX, float vecY, float maxStretchX, float maxStretchY, float childRelativeLeft, float childRelativeTop, float childRelativeRight, float childRelativeBottom)423 public void applyStretch(long frameNumber, float width, float height, 424 float vecX, float vecY, float maxStretchX, float maxStretchY, float childRelativeLeft, 425 float childRelativeTop, float childRelativeRight, float childRelativeBottom) { 426 for (PositionUpdateListener pul : mListeners) { 427 pul.applyStretch(frameNumber, width, height, vecX, vecY, maxStretchX, 428 maxStretchY, childRelativeLeft, childRelativeTop, childRelativeRight, 429 childRelativeBottom); 430 } 431 } 432 } 433 434 /** 435 * Enable callbacks for position changes. Call only from the UI thread or with 436 * external synchronization. 437 * 438 * @hide 439 */ addPositionUpdateListener(@onNull PositionUpdateListener listener)440 public void addPositionUpdateListener(@NonNull PositionUpdateListener listener) { 441 CompositePositionUpdateListener comp = mCompositePositionUpdateListener; 442 if (comp == null) { 443 comp = new CompositePositionUpdateListener(listener); 444 } else { 445 comp = comp.with(listener); 446 } 447 mCompositePositionUpdateListener = comp; 448 nRequestPositionUpdates(mNativeRenderNode, new WeakReference<>(comp)); 449 } 450 451 /** 452 * Disable a callback for position changes. Call only from the UI thread or with 453 * external synchronization. 454 * 455 * @param listener Callback to remove 456 * @hide 457 */ removePositionUpdateListener(@onNull PositionUpdateListener listener)458 public void removePositionUpdateListener(@NonNull PositionUpdateListener listener) { 459 CompositePositionUpdateListener comp = mCompositePositionUpdateListener; 460 if (comp != null) { 461 comp = comp.without(listener); 462 mCompositePositionUpdateListener = comp; 463 nRequestPositionUpdates(mNativeRenderNode, new WeakReference<>(comp)); 464 } 465 } 466 467 /** 468 * Starts recording a display list for the render node. All 469 * operations performed on the returned canvas are recorded and 470 * stored in this display list. 471 * 472 * {@link #endRecording()} must be called when the recording is finished in order to apply 473 * the updated display list. Failing to call {@link #endRecording()} will result in an 474 * {@link IllegalStateException} if {@link #beginRecording(int, int)} is called again. 475 * 476 * @param width The width of the recording viewport. This will not alter the width of the 477 * RenderNode itself, that must be set with {@link #setPosition(Rect)}. 478 * @param height The height of the recording viewport. This will not alter the height of the 479 * RenderNode itself, that must be set with {@link #setPosition(Rect)}. 480 * @return A canvas to record drawing operations. 481 * @throws IllegalStateException If a recording is already in progress. That is, the previous 482 * call to {@link #beginRecording(int, int)} did not call {@link #endRecording()}. 483 * @see #endRecording() 484 * @see #hasDisplayList() 485 */ beginRecording(int width, int height)486 public @NonNull RecordingCanvas beginRecording(int width, int height) { 487 if (mCurrentRecordingCanvas != null) { 488 throw new IllegalStateException( 489 "Recording currently in progress - missing #endRecording() call?"); 490 } 491 mCurrentRecordingCanvas = RecordingCanvas.obtain(this, width, height); 492 return mCurrentRecordingCanvas; 493 } 494 495 /** 496 * Same as {@link #beginRecording(int, int)} with the width & height set 497 * to the RenderNode's own width & height. The RenderNode's width & height may be set 498 * with {@link #setPosition(int, int, int, int)}. 499 * 500 * @return A canvas to record drawing operations. 501 * @throws IllegalStateException If a recording is already in progress. That is, the previous 502 * call to {@link #beginRecording(int, int)} did not call {@link #endRecording()}. 503 * @see #endRecording() 504 * @see #hasDisplayList() 505 */ beginRecording()506 public @NonNull RecordingCanvas beginRecording() { 507 return beginRecording(nGetWidth(mNativeRenderNode), nGetHeight(mNativeRenderNode)); 508 } 509 510 /** 511 * ` 512 * Ends the recording for this display list. Calling this method marks 513 * the display list valid and {@link #hasDisplayList()} will return true. 514 * 515 * @see #beginRecording(int, int) 516 * @see #hasDisplayList() 517 */ endRecording()518 public void endRecording() { 519 if (mCurrentRecordingCanvas == null) { 520 throw new IllegalStateException( 521 "No recording in progress, forgot to call #beginRecording()?"); 522 } 523 RecordingCanvas canvas = mCurrentRecordingCanvas; 524 mCurrentRecordingCanvas = null; 525 canvas.finishRecording(this); 526 canvas.recycle(); 527 } 528 529 /** 530 * @hide 531 * @deprecated use {@link #beginRecording(int, int)} instead 532 */ 533 @Deprecated start(int width, int height)534 public RecordingCanvas start(int width, int height) { 535 return beginRecording(width, height); 536 } 537 538 /** 539 * @hide 540 * @deprecated use {@link #endRecording()} instead 541 */ 542 @Deprecated end(RecordingCanvas canvas)543 public void end(RecordingCanvas canvas) { 544 if (canvas != mCurrentRecordingCanvas) { 545 throw new IllegalArgumentException("Wrong canvas"); 546 } 547 endRecording(); 548 } 549 550 /** 551 * Reset native resources. This is called when cleaning up the state of display lists 552 * during destruction of hardware resources, to ensure that we do not hold onto 553 * obsolete resources after related resources are gone. 554 */ discardDisplayList()555 public void discardDisplayList() { 556 nDiscardDisplayList(mNativeRenderNode); 557 } 558 559 /** 560 * Returns whether the RenderNode has a display list. If this returns false, the RenderNode 561 * should be re-recorded with {@link #beginRecording()} and {@link #endRecording()}. 562 * 563 * A RenderNode without a display list may still be drawn, however it will have no impact 564 * on the rendering content until its display list is updated. 565 * 566 * When a RenderNode is no longer drawn by anything the system may automatically 567 * invoke {@link #discardDisplayList()}. It is therefore important to ensure that 568 * {@link #hasDisplayList()} is true on a RenderNode prior to drawing it. 569 * 570 * See {@link #discardDisplayList()} 571 * 572 * @return boolean true if this RenderNode has a display list, false otherwise. 573 */ hasDisplayList()574 public boolean hasDisplayList() { 575 return nIsValid(mNativeRenderNode); 576 } 577 578 /////////////////////////////////////////////////////////////////////////// 579 // Matrix manipulation 580 /////////////////////////////////////////////////////////////////////////// 581 582 /** 583 * Whether or not the RenderNode has an identity transform. This is a faster 584 * way to do the otherwise equivalent {@link #getMatrix(Matrix)} {@link Matrix#isIdentity()} 585 * as it doesn't require copying the Matrix first, thus minimizing overhead. 586 * 587 * @return true if the RenderNode has an identity transform, false otherwise 588 */ hasIdentityMatrix()589 public boolean hasIdentityMatrix() { 590 return nHasIdentityMatrix(mNativeRenderNode); 591 } 592 593 /** 594 * Gets the current transform matrix 595 * 596 * @param outMatrix The matrix to store the transform of the RenderNode 597 */ getMatrix(@onNull Matrix outMatrix)598 public void getMatrix(@NonNull Matrix outMatrix) { 599 nGetTransformMatrix(mNativeRenderNode, outMatrix.ni()); 600 } 601 602 /** 603 * Gets the current transform inverted. This is a faster way to do the otherwise 604 * equivalent {@link #getMatrix(Matrix)} followed by {@link Matrix#invert(Matrix)} 605 * 606 * @param outMatrix The matrix to store the inverse transform of the RenderNode 607 */ getInverseMatrix(@onNull Matrix outMatrix)608 public void getInverseMatrix(@NonNull Matrix outMatrix) { 609 nGetInverseTransformMatrix(mNativeRenderNode, outMatrix.ni()); 610 } 611 612 /////////////////////////////////////////////////////////////////////////// 613 // RenderProperty Setters 614 /////////////////////////////////////////////////////////////////////////// 615 616 /** 617 * @hide 618 * @deprecated use {@link #setUseCompositingLayer(boolean, Paint)} instead 619 */ 620 @Deprecated setLayerType(int layerType)621 public boolean setLayerType(int layerType) { 622 return nSetLayerType(mNativeRenderNode, layerType); 623 } 624 625 /** 626 * @hide 627 * @deprecated use {@link #setUseCompositingLayer(boolean, Paint)} instead 628 */ 629 @Deprecated setLayerPaint(@ullable Paint paint)630 public boolean setLayerPaint(@Nullable Paint paint) { 631 return nSetLayerPaint(mNativeRenderNode, paint != null ? paint.getNativeInstance() : 0); 632 } 633 634 /** 635 * Controls whether or not to force this RenderNode to render to an intermediate buffer. 636 * Internally RenderNode will already promote itself to a composition layer if it's useful 637 * for performance or required for the current combination of {@link #setAlpha(float)} and 638 * {@link #setHasOverlappingRendering(boolean)}. 639 * 640 * <p>The usage of this is instead to allow for either overriding of the internal behavior 641 * if it's measured to be necessary for the particular rendering content in question or, more 642 * usefully, to add a composition effect to the RenderNode via the optional paint parameter. 643 * 644 * <p>Note: When a RenderNode is using a compositing layer it will also result in 645 * clipToBounds=true behavior. 646 * 647 * @param forceToLayer if true this forces the RenderNode to use an intermediate buffer. 648 * Default & generally recommended value is false. 649 * @param paint The blend mode, alpha, and ColorFilter to apply to the compositing layer. 650 * Only applies if forceToLayer is true. The paint's alpha is multiplied 651 * with {@link #getAlpha()} to resolve the final alpha of the RenderNode. 652 * If null then no additional composition effects are applied on top of the 653 * composition layer. 654 * @return True if the value changed, false if the new value was the same as the previous value. 655 */ setUseCompositingLayer(boolean forceToLayer, @Nullable Paint paint)656 public boolean setUseCompositingLayer(boolean forceToLayer, @Nullable Paint paint) { 657 boolean didChange = nSetLayerType(mNativeRenderNode, forceToLayer ? 2 : 0); 658 didChange |= nSetLayerPaint(mNativeRenderNode, 659 paint != null ? paint.getNativeInstance() : 0); 660 return didChange; 661 } 662 663 /** 664 * Gets whether or not a compositing layer is forced to be used. The default & recommended 665 * is false, as it is typically faster to avoid using compositing layers. 666 * See {@link #setUseCompositingLayer(boolean, Paint)}. 667 * 668 * @return true if a compositing layer is forced, false otherwise 669 */ getUseCompositingLayer()670 public boolean getUseCompositingLayer() { 671 return nGetLayerType(mNativeRenderNode) != 0; 672 } 673 674 /** 675 * Sets an additional clip on the RenderNode. If null, the extra clip is removed from the 676 * RenderNode. If non-null, the RenderNode will be clipped to this rect. In addition if 677 * {@link #setClipToBounds(boolean)} is true, then the RenderNode will be clipped to the 678 * intersection of this rectangle and the bounds of the render node, which is set with 679 * {@link #setPosition(Rect)}. 680 * 681 * <p>This is equivalent to do a {@link Canvas#clipRect(Rect)} at the start of this 682 * RenderNode's display list. However, as this is a property of the RenderNode instead 683 * of part of the display list it can be more easily animated for transient additional 684 * clipping. An example usage of this would be the {@link android.transition.ChangeBounds} 685 * transition animation with the resizeClip=true option. 686 * 687 * @param rect the bounds to clip to. If null, the additional clip is removed. 688 * @return True if the value changed, false if the new value was the same as the previous value. 689 */ setClipRect(@ullable Rect rect)690 public boolean setClipRect(@Nullable Rect rect) { 691 if (rect == null) { 692 return nSetClipBoundsEmpty(mNativeRenderNode); 693 } else { 694 return nSetClipBounds(mNativeRenderNode, rect.left, rect.top, rect.right, rect.bottom); 695 } 696 } 697 698 /** 699 * Set whether the Render node should clip itself to its bounds. This defaults to true, 700 * and is useful to the renderer in enable quick-rejection of chunks of the tree as well as 701 * better partial invalidation support. Clipping can be further restricted or controlled 702 * through the combination of this property as well as {@link #setClipRect(Rect)}, which 703 * allows for a different clipping rectangle to be used in addition to or instead of the 704 * {@link #setPosition(int, int, int, int)} or the RenderNode. 705 * 706 * @param clipToBounds true if the display list should clip to its bounds, false otherwise. 707 * @return True if the value changed, false if the new value was the same as the previous value. 708 */ setClipToBounds(boolean clipToBounds)709 public boolean setClipToBounds(boolean clipToBounds) { 710 return nSetClipToBounds(mNativeRenderNode, clipToBounds); 711 } 712 713 /** 714 * Returns whether or not the RenderNode is clipping to its bounds. See 715 * {@link #setClipToBounds(boolean)} and {@link #setPosition(int, int, int, int)} 716 * 717 * @return true if the render node clips to its bounds, false otherwise. 718 */ getClipToBounds()719 public boolean getClipToBounds() { 720 return nGetClipToBounds(mNativeRenderNode); 721 } 722 723 /** 724 * <p>Sets whether the RenderNode should be drawn immediately after the 725 * closest ancestor RenderNode containing a projection receiver. 726 * 727 * <p>The default is false, and the rendering of this node happens in the typical draw order. 728 * 729 * <p>If true, then at rendering time this rendernode will not be drawn in order with the 730 * {@link Canvas#drawRenderNode(RenderNode)} command that drew this RenderNode, but instead 731 * it will be re-positioned in the RenderNode tree to be drawn on the closet ancestor with a 732 * child rendernode that has {@link #setProjectionReceiver(boolean)} as true. 733 * 734 * <p>The typical usage of this is to allow a child RenderNode to draw on a parent's background, 735 * such as the platform's usage with {@link android.graphics.drawable.RippleDrawable}. Consider 736 * the following structure, built out of which RenderNode called drawRenderNode on a different 737 * RenderNode: 738 * 739 * <pre> 740 * +-------------+ 741 * |RenderNode: P| 742 * +-+----------++ 743 * | | 744 * v v 745 * +-------+-----+ +-+--------------+ 746 * |RenderNode: C| |RenderNode: P'BG| 747 * +-------+-----+ +----------------+ 748 * | 749 * | 750 * +--------+-------+ 751 * |RenderNode: C'BG| 752 * +----------------+ 753 * </pre> 754 * 755 * If P'BG is a projection receiver, and C'BG is set to project backwards then C'BG will 756 * behave as if it was drawn directly by P'BG instead of by C. This includes inheriting P'BG's 757 * clip instead of C's clip. 758 * 759 * @param shouldProject true if the display list should be projected onto a 760 * containing volume. Default is false. 761 * @return True if the value changed, false if the new value was the same as the previous value. 762 */ setProjectBackwards(boolean shouldProject)763 public boolean setProjectBackwards(boolean shouldProject) { 764 return nSetProjectBackwards(mNativeRenderNode, shouldProject); 765 } 766 767 /** 768 * Sets whether the RenderNode is a projection receiver. If true then this RenderNode's parent 769 * should draw any descendant RenderNodes with ProjectBackwards=true directly on top of it. 770 * Default value is false. See 771 * {@link #setProjectBackwards(boolean)} for a description of what this entails. 772 * 773 * @param shouldReceive True if this RenderNode is a projection receiver, false otherwise. 774 * Default is false. 775 * @return True if the value changed, false if the new value was the same as the previous value. 776 */ setProjectionReceiver(boolean shouldReceive)777 public boolean setProjectionReceiver(boolean shouldReceive) { 778 return nSetProjectionReceiver(mNativeRenderNode, shouldReceive); 779 } 780 781 /** 782 * Sets the outline, defining the shape that casts a shadow, and the path to 783 * be clipped if setClipToOutline is set. 784 * 785 * This will make a copy of the provided {@link Outline}, so any future modifications 786 * to the outline will need to call {@link #setOutline(Outline)} with the modified 787 * outline for those changes to be applied. 788 * 789 * @param outline The outline to use for this RenderNode. 790 * @return True if the value changed, false if the new value was the same as the previous value. 791 */ setOutline(@ullable Outline outline)792 public boolean setOutline(@Nullable Outline outline) { 793 if (outline == null) { 794 return nSetOutlineNone(mNativeRenderNode); 795 } 796 797 switch (outline.mMode) { 798 case Outline.MODE_EMPTY: 799 return nSetOutlineEmpty(mNativeRenderNode); 800 case Outline.MODE_ROUND_RECT: 801 return nSetOutlineRoundRect(mNativeRenderNode, 802 outline.mRect.left, outline.mRect.top, 803 outline.mRect.right, outline.mRect.bottom, 804 outline.mRadius, outline.mAlpha); 805 case Outline.MODE_PATH: 806 return nSetOutlinePath(mNativeRenderNode, outline.mPath.mNativePath, 807 outline.mAlpha); 808 } 809 810 throw new IllegalArgumentException("Unrecognized outline?"); 811 } 812 813 /** @hide */ clearStretch()814 public boolean clearStretch() { 815 return nClearStretch(mNativeRenderNode); 816 } 817 818 /** @hide */ stretch(float vecX, float vecY, float maxStretchAmountX, float maxStretchAmountY)819 public boolean stretch(float vecX, float vecY, 820 float maxStretchAmountX, float maxStretchAmountY) { 821 if (Float.isInfinite(vecX) || Float.isNaN(vecX)) { 822 throw new IllegalArgumentException("vecX must be a finite, non-NaN value " + vecX); 823 } 824 if (Float.isInfinite(vecY) || Float.isNaN(vecY)) { 825 throw new IllegalArgumentException("vecY must be a finite, non-NaN value " + vecY); 826 } 827 828 if (maxStretchAmountX <= 0.0f) { 829 throw new IllegalArgumentException( 830 "The max horizontal stretch amount must be >0, got " + maxStretchAmountX); 831 } 832 if (maxStretchAmountY <= 0.0f) { 833 throw new IllegalArgumentException( 834 "The max vertical stretch amount must be >0, got " + maxStretchAmountY); 835 } 836 return nStretch( 837 mNativeRenderNode, 838 vecX, 839 vecY, 840 maxStretchAmountX, 841 maxStretchAmountY 842 ); 843 } 844 845 /** 846 * Checks if the RenderNode has a shadow. That is, if the combination of {@link #getElevation()} 847 * and {@link #getTranslationZ()} is greater than zero, there is an {@link Outline} set with 848 * a valid shadow caster path, and the provided outline has a non-zero 849 * {@link Outline#getAlpha()}. 850 * 851 * @return True if this RenderNode has a shadow, false otherwise 852 */ hasShadow()853 public boolean hasShadow() { 854 return nHasShadow(mNativeRenderNode); 855 } 856 857 /** 858 * Sets the color of the spot shadow that is drawn when the RenderNode has a positive Z or 859 * elevation value and is drawn inside of a {@link Canvas#enableZ()} section. 860 * <p> 861 * By default the shadow color is black. Generally, this color will be opaque so the intensity 862 * of the shadow is consistent between different RenderNodes with different colors. 863 * <p> 864 * The opacity of the final spot shadow is a function of the shadow caster height, the 865 * alpha channel of the outlineSpotShadowColor (typically opaque), and the 866 * {@link android.R.attr#spotShadowAlpha} theme attribute 867 * 868 * @param color The color this RenderNode will cast for its elevation spot shadow. 869 * @return True if the value changed, false if the new value was the same as the previous value. 870 */ setSpotShadowColor(@olorInt int color)871 public boolean setSpotShadowColor(@ColorInt int color) { 872 return nSetSpotShadowColor(mNativeRenderNode, color); 873 } 874 875 /** 876 * @return The shadow color set by {@link #setSpotShadowColor(int)}, or black if nothing 877 * was set 878 */ getSpotShadowColor()879 public @ColorInt int getSpotShadowColor() { 880 return nGetSpotShadowColor(mNativeRenderNode); 881 } 882 883 /** 884 * Sets the color of the ambient shadow that is drawn when the RenderNode has a positive Z or 885 * elevation value and is drawn inside of a {@link Canvas#enableZ()} section. 886 * <p> 887 * By default the shadow color is black. Generally, this color will be opaque so the intensity 888 * of the shadow is consistent between different RenderNodes with different colors. 889 * <p> 890 * The opacity of the final ambient shadow is a function of the shadow caster height, the 891 * alpha channel of the outlineAmbientShadowColor (typically opaque), and the 892 * {@link android.R.attr#ambientShadowAlpha} theme attribute. 893 * 894 * @param color The color this RenderNode will cast for its elevation shadow. 895 * @return True if the value changed, false if the new value was the same as the previous value. 896 */ setAmbientShadowColor(@olorInt int color)897 public boolean setAmbientShadowColor(@ColorInt int color) { 898 return nSetAmbientShadowColor(mNativeRenderNode, color); 899 } 900 901 /** 902 * @return The shadow color set by {@link #setAmbientShadowColor(int)}, or black if 903 * nothing was set 904 */ getAmbientShadowColor()905 public @ColorInt int getAmbientShadowColor() { 906 return nGetAmbientShadowColor(mNativeRenderNode); 907 } 908 909 /** 910 * Enables or disables clipping to the outline. 911 * 912 * @param clipToOutline true if clipping to the outline. 913 * @return True if the clipToOutline value changed, false if previous value matched the new 914 * value. 915 */ setClipToOutline(boolean clipToOutline)916 public boolean setClipToOutline(boolean clipToOutline) { 917 return nSetClipToOutline(mNativeRenderNode, clipToOutline); 918 } 919 920 /** 921 * See {@link #setClipToOutline(boolean)} 922 * 923 * @return True if this RenderNode clips to its outline, false otherwise 924 */ getClipToOutline()925 public boolean getClipToOutline() { 926 return nGetClipToOutline(mNativeRenderNode); 927 } 928 929 /** 930 * Controls the RenderNode's circular reveal clip. 931 * 932 * @hide 933 */ setRevealClip(boolean shouldClip, float x, float y, float radius)934 public boolean setRevealClip(boolean shouldClip, 935 float x, float y, float radius) { 936 return nSetRevealClip(mNativeRenderNode, shouldClip, x, y, radius); 937 } 938 939 /** 940 * Set the static matrix on the display list. The specified matrix is combined with other 941 * transforms (such as {@link #setScaleX(float)}, {@link #setRotationZ(float)}, etc.) 942 * 943 * @param matrix A transform matrix to apply to this display list 944 * @hide TODO Do we want this? 945 */ setStaticMatrix(Matrix matrix)946 public boolean setStaticMatrix(Matrix matrix) { 947 return nSetStaticMatrix(mNativeRenderNode, matrix.ni()); 948 } 949 950 /** 951 * Set the Animation matrix on the display list. This matrix exists if an Animation is 952 * currently playing on a View, and is set on the display list during at draw() time. When 953 * the Animation finishes, the matrix should be cleared by sending <code>null</code> 954 * for the matrix parameter. 955 * 956 * @param matrix The matrix, null indicates that the matrix should be cleared. 957 * @see #getAnimationMatrix() 958 * 959 * @hide TODO Do we want this? 960 */ setAnimationMatrix(@ullable Matrix matrix)961 public boolean setAnimationMatrix(@Nullable Matrix matrix) { 962 return nSetAnimationMatrix(mNativeRenderNode, 963 (matrix != null) ? matrix.ni() : 0); 964 } 965 966 /** 967 * Returns the previously set Animation matrix. This matrix exists if an Animation is 968 * currently playing on a View, and is set on the display list during at draw() time. 969 * Returns <code>null</code> when there is no transformation provided by 970 * {@link #setAnimationMatrix(Matrix)}. 971 * 972 * @return the current Animation matrix. 973 * @see #setAnimationMatrix(Matrix) 974 * 975 * @hide 976 */ 977 @Nullable getAnimationMatrix()978 public Matrix getAnimationMatrix() { 979 Matrix output = new Matrix(); 980 if (nGetAnimationMatrix(mNativeRenderNode, output.ni())) { 981 return output; 982 } else { 983 return null; 984 } 985 } 986 987 /** 988 * Sets the translucency level for the display list. 989 * 990 * @param alpha The translucency of the display list, must be a value between 0.0f and 1.0f 991 * @see View#setAlpha(float) 992 * @see #getAlpha() 993 * @return True if the value changed, false if the new value was the same as the previous value. 994 */ setAlpha(float alpha)995 public boolean setAlpha(float alpha) { 996 return nSetAlpha(mNativeRenderNode, alpha); 997 } 998 999 /** 1000 * Configure the {@link android.graphics.RenderEffect} to apply to this RenderNode. This 1001 * will apply a visual effect to the end result of the contents of this RenderNode before 1002 * it is drawn into the destination. For example if 1003 * {@link RenderEffect#createBlurEffect(float, float, RenderEffect, Shader.TileMode)} 1004 * is provided, the contents will be drawn in a separate layer, then this layer will 1005 * be blurred when this RenderNode is drawn into the destination. 1006 * @param renderEffect to be applied to the RenderNode. Passing null clears all previously 1007 * configured RenderEffects 1008 * @return True if the value changed, false if the new value was the same as the previous value. 1009 */ setRenderEffect(@ullable RenderEffect renderEffect)1010 public boolean setRenderEffect(@Nullable RenderEffect renderEffect) { 1011 return nSetRenderEffect(mNativeRenderNode, 1012 renderEffect != null ? renderEffect.getNativeInstance() : 0); 1013 } 1014 1015 /** 1016 * Configure the {@link android.graphics.RenderEffect} to apply to the backdrop contents of 1017 * this RenderNode. This will apply a visual effect to the result of the backdrop contents 1018 * of this RenderNode before the RenderNode is drawn into the destination. For example if 1019 * {@link RenderEffect#createBlurEffect(float, float, RenderEffect, Shader.TileMode)} 1020 * is provided, the previous content behind this RenderNode will be blurred before the 1021 * RenderNode is drawn in to the destination. 1022 * @param renderEffect to be applied to the backdrop contents of this RenderNode. Passing 1023 * null clears all previously configured RenderEffects 1024 * @return True if the value changed, false if the new value was the same as the previous value. 1025 * @hide 1026 */ setBackdropRenderEffect(@ullable RenderEffect renderEffect)1027 public boolean setBackdropRenderEffect(@Nullable RenderEffect renderEffect) { 1028 return nSetBackdropRenderEffect(mNativeRenderNode, 1029 renderEffect != null ? renderEffect.getNativeInstance() : 0); 1030 } 1031 1032 /** 1033 * Returns the translucency level of this display list. 1034 * 1035 * @return A value between 0.0f and 1.0f 1036 * @see #setAlpha(float) 1037 */ getAlpha()1038 public float getAlpha() { 1039 return nGetAlpha(mNativeRenderNode); 1040 } 1041 1042 /** 1043 * Sets whether the display list renders content which overlaps. Non-overlapping rendering 1044 * can use a fast path for alpha that avoids rendering to an offscreen buffer. By default 1045 * display lists consider they do not have overlapping content. 1046 * 1047 * @param hasOverlappingRendering False if the content is guaranteed to be non-overlapping, 1048 * true otherwise. 1049 * @see android.view.View#hasOverlappingRendering() 1050 * @see #hasOverlappingRendering() 1051 */ setHasOverlappingRendering(boolean hasOverlappingRendering)1052 public boolean setHasOverlappingRendering(boolean hasOverlappingRendering) { 1053 return nSetHasOverlappingRendering(mNativeRenderNode, hasOverlappingRendering); 1054 } 1055 1056 /** @hide */ 1057 @IntDef({USAGE_BACKGROUND}) 1058 @Retention(RetentionPolicy.SOURCE) 1059 public @interface UsageHint { 1060 } 1061 1062 /** 1063 * The default usage hint 1064 * 1065 * @hide 1066 */ 1067 public static final int USAGE_UNKNOWN = 0; 1068 1069 /** 1070 * Usage is background content 1071 * 1072 * @hide 1073 */ 1074 public static final int USAGE_BACKGROUND = 1; 1075 1076 /** 1077 * Provides a hint on what this RenderNode's display list content contains. This hint is used 1078 * for automatic content transforms to improve accessibility or similar. 1079 * 1080 * @hide 1081 */ setUsageHint(@sageHint int usageHint)1082 public void setUsageHint(@UsageHint int usageHint) { 1083 nSetUsageHint(mNativeRenderNode, usageHint); 1084 } 1085 1086 /** 1087 * Indicates whether the content of this display list overlaps. 1088 * 1089 * @return True if this display list renders content which overlaps, false otherwise. 1090 * @see #setHasOverlappingRendering(boolean) 1091 */ hasOverlappingRendering()1092 public boolean hasOverlappingRendering() { 1093 return nHasOverlappingRendering(mNativeRenderNode); 1094 } 1095 1096 /** 1097 * Sets the base elevation of this RenderNode in pixels 1098 * 1099 * @param lift the elevation in pixels 1100 * @return True if the value changed, false if the new value was the same as the previous value. 1101 */ setElevation(float lift)1102 public boolean setElevation(float lift) { 1103 return nSetElevation(mNativeRenderNode, lift); 1104 } 1105 1106 /** 1107 * See {@link #setElevation(float)} 1108 * 1109 * @return The RenderNode's current elevation 1110 */ getElevation()1111 public float getElevation() { 1112 return nGetElevation(mNativeRenderNode); 1113 } 1114 1115 /** 1116 * Sets the translation value for the display list on the X axis. 1117 * 1118 * @param translationX The X axis translation value of the display list, in pixels 1119 * @see View#setTranslationX(float) 1120 * @see #getTranslationX() 1121 * @return True if the value changed, false if the new value was the same as the previous value. 1122 */ setTranslationX(float translationX)1123 public boolean setTranslationX(float translationX) { 1124 return nSetTranslationX(mNativeRenderNode, translationX); 1125 } 1126 1127 /** 1128 * Returns the translation value for this display list on the X axis, in pixels. 1129 * 1130 * @see #setTranslationX(float) 1131 */ getTranslationX()1132 public float getTranslationX() { 1133 return nGetTranslationX(mNativeRenderNode); 1134 } 1135 1136 /** 1137 * Sets the translation value for the display list on the Y axis. 1138 * 1139 * @param translationY The Y axis translation value of the display list, in pixels 1140 * @see View#setTranslationY(float) 1141 * @see #getTranslationY() 1142 * @return True if the value changed, false if the new value was the same as the previous value. 1143 */ setTranslationY(float translationY)1144 public boolean setTranslationY(float translationY) { 1145 return nSetTranslationY(mNativeRenderNode, translationY); 1146 } 1147 1148 /** 1149 * Returns the translation value for this display list on the Y axis, in pixels. 1150 * 1151 * @see #setTranslationY(float) 1152 */ getTranslationY()1153 public float getTranslationY() { 1154 return nGetTranslationY(mNativeRenderNode); 1155 } 1156 1157 /** 1158 * Sets the translation value for the display list on the Z axis. 1159 * 1160 * @see View#setTranslationZ(float) 1161 * @see #getTranslationZ() 1162 * @return True if the value changed, false if the new value was the same as the previous value. 1163 */ setTranslationZ(float translationZ)1164 public boolean setTranslationZ(float translationZ) { 1165 return nSetTranslationZ(mNativeRenderNode, translationZ); 1166 } 1167 1168 /** 1169 * Returns the translation value for this display list on the Z axis. 1170 * 1171 * @see #setTranslationZ(float) 1172 */ getTranslationZ()1173 public float getTranslationZ() { 1174 return nGetTranslationZ(mNativeRenderNode); 1175 } 1176 1177 /** 1178 * Sets the rotation value for the display list around the Z axis. 1179 * 1180 * @param rotation The rotation value of the display list, in degrees 1181 * @see View#setRotation(float) 1182 * @see #getRotationZ() 1183 * @return True if the value changed, false if the new value was the same as the previous value. 1184 */ setRotationZ(float rotation)1185 public boolean setRotationZ(float rotation) { 1186 return nSetRotation(mNativeRenderNode, rotation); 1187 } 1188 1189 /** 1190 * Returns the rotation value for this display list around the Z axis, in degrees. 1191 * 1192 * @see #setRotationZ(float) 1193 */ getRotationZ()1194 public float getRotationZ() { 1195 return nGetRotation(mNativeRenderNode); 1196 } 1197 1198 /** 1199 * Sets the rotation value for the display list around the X axis. 1200 * 1201 * @param rotationX The rotation value of the display list, in degrees 1202 * @see View#setRotationX(float) 1203 * @see #getRotationX() 1204 * @return True if the value changed, false if the new value was the same as the previous value. 1205 */ setRotationX(float rotationX)1206 public boolean setRotationX(float rotationX) { 1207 return nSetRotationX(mNativeRenderNode, rotationX); 1208 } 1209 1210 /** 1211 * Returns the rotation value for this display list around the X axis, in degrees. 1212 * 1213 * @see #setRotationX(float) 1214 */ getRotationX()1215 public float getRotationX() { 1216 return nGetRotationX(mNativeRenderNode); 1217 } 1218 1219 /** 1220 * Sets the rotation value for the display list around the Y axis. 1221 * 1222 * @param rotationY The rotation value of the display list, in degrees 1223 * @see View#setRotationY(float) 1224 * @see #getRotationY() 1225 * @return True if the value changed, false if the new value was the same as the previous value. 1226 */ setRotationY(float rotationY)1227 public boolean setRotationY(float rotationY) { 1228 return nSetRotationY(mNativeRenderNode, rotationY); 1229 } 1230 1231 /** 1232 * Returns the rotation value for this display list around the Y axis, in degrees. 1233 * 1234 * @see #setRotationY(float) 1235 */ getRotationY()1236 public float getRotationY() { 1237 return nGetRotationY(mNativeRenderNode); 1238 } 1239 1240 /** 1241 * Sets the scale value for the display list on the X axis. 1242 * 1243 * @param scaleX The scale value of the display list 1244 * @see View#setScaleX(float) 1245 * @see #getScaleX() 1246 * @return True if the value changed, false if the new value was the same as the previous value. 1247 */ setScaleX(float scaleX)1248 public boolean setScaleX(float scaleX) { 1249 return nSetScaleX(mNativeRenderNode, scaleX); 1250 } 1251 1252 /** 1253 * Returns the scale value for this display list on the X axis. 1254 * 1255 * @see #setScaleX(float) 1256 */ getScaleX()1257 public float getScaleX() { 1258 return nGetScaleX(mNativeRenderNode); 1259 } 1260 1261 /** 1262 * Sets the scale value for the display list on the Y axis. 1263 * 1264 * @param scaleY The scale value of the display list 1265 * @see View#setScaleY(float) 1266 * @see #getScaleY() 1267 * @return True if the value changed, false if the new value was the same as the previous value. 1268 */ setScaleY(float scaleY)1269 public boolean setScaleY(float scaleY) { 1270 return nSetScaleY(mNativeRenderNode, scaleY); 1271 } 1272 1273 /** 1274 * Returns the scale value for this display list on the Y axis. 1275 * 1276 * @see #setScaleY(float) 1277 */ getScaleY()1278 public float getScaleY() { 1279 return nGetScaleY(mNativeRenderNode); 1280 } 1281 1282 /** 1283 * Sets the pivot value for the display list on the X axis 1284 * 1285 * @param pivotX The pivot value of the display list on the X axis, in pixels 1286 * @see View#setPivotX(float) 1287 * @see #getPivotX() 1288 * @return True if the value changed, false if the new value was the same as the previous value. 1289 */ setPivotX(float pivotX)1290 public boolean setPivotX(float pivotX) { 1291 return nSetPivotX(mNativeRenderNode, pivotX); 1292 } 1293 1294 /** 1295 * Returns the pivot value for this display list on the X axis, in pixels. 1296 * 1297 * @see #setPivotX(float) 1298 */ getPivotX()1299 public float getPivotX() { 1300 return nGetPivotX(mNativeRenderNode); 1301 } 1302 1303 /** 1304 * Sets the pivot value for the display list on the Y axis 1305 * 1306 * @param pivotY The pivot value of the display list on the Y axis, in pixels 1307 * @see View#setPivotY(float) 1308 * @see #getPivotY() 1309 * @return True if the value changed, false if the new value was the same as the previous value. 1310 */ setPivotY(float pivotY)1311 public boolean setPivotY(float pivotY) { 1312 return nSetPivotY(mNativeRenderNode, pivotY); 1313 } 1314 1315 /** 1316 * Returns the pivot value for this display list on the Y axis, in pixels. 1317 * 1318 * @see #setPivotY(float) 1319 */ getPivotY()1320 public float getPivotY() { 1321 return nGetPivotY(mNativeRenderNode); 1322 } 1323 1324 /** 1325 * @return Whether or not a pivot was explicitly set with {@link #setPivotX(float)} or 1326 * {@link #setPivotY(float)}. If no pivot has been set then the pivot will be the center 1327 * of the RenderNode. 1328 */ isPivotExplicitlySet()1329 public boolean isPivotExplicitlySet() { 1330 return nIsPivotExplicitlySet(mNativeRenderNode); 1331 } 1332 1333 /** 1334 * Clears any pivot previously set by a call to {@link #setPivotX(float)} or 1335 * {@link #setPivotY(float)}. After calling this {@link #isPivotExplicitlySet()} will be false 1336 * and the pivot used for rotation will return to default of being centered on the view. 1337 * 1338 * @return True if the value changed, false if the new value was the same as the previous value. 1339 */ resetPivot()1340 public boolean resetPivot() { 1341 return nResetPivot(mNativeRenderNode); 1342 } 1343 1344 /** 1345 * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which 1346 * RenderNodes are drawn) from the camera to this RenderNode. The camera's distance 1347 * affects 3D transformations, for instance rotations around the X and Y 1348 * axis. If the rotationX or rotationY properties are changed and this view is 1349 * large (more than half the size of the screen), it is recommended to always 1350 * use a camera distance that's greater than the height (X axis rotation) or 1351 * the width (Y axis rotation) of this view.</p> 1352 * 1353 * <p>The distance of the camera from the drawing plane can have an affect on the 1354 * perspective distortion of the RenderNode when it is rotated around the x or y axis. 1355 * For example, a large distance will result in a large viewing angle, and there 1356 * will not be much perspective distortion of the view as it rotates. A short 1357 * distance may cause much more perspective distortion upon rotation, and can 1358 * also result in some drawing artifacts if the rotated view ends up partially 1359 * behind the camera (which is why the recommendation is to use a distance at 1360 * least as far as the size of the view, if the view is to be rotated.)</p> 1361 * 1362 * <p>The distance is expressed in pixels and must always be positive</p> 1363 * 1364 * @param distance The distance in pixels, must always be positive 1365 * @see #setRotationX(float) 1366 * @see #setRotationY(float) 1367 * @return True if the value changed, false if the new value was the same as the previous value. 1368 */ setCameraDistance( @loatRangefrom = 0.0f, to = Float.MAX_VALUE) float distance)1369 public boolean setCameraDistance( 1370 @FloatRange(from = 0.0f, to = Float.MAX_VALUE) float distance) { 1371 if (!Float.isFinite(distance) || distance < 0.0f) { 1372 throw new IllegalArgumentException("distance must be finite & positive, given=" 1373 + distance); 1374 } 1375 // Native actually wants this to be negative not positive, so we flip it. 1376 return nSetCameraDistance(mNativeRenderNode, -distance); 1377 } 1378 1379 /** 1380 * Returns the distance in Z of the camera for this RenderNode 1381 * 1382 * @return the distance along the Z axis in pixels. 1383 * @see #setCameraDistance(float) 1384 */ getCameraDistance()1385 public @FloatRange(from = 0.0f, to = Float.MAX_VALUE) float getCameraDistance() { 1386 return -nGetCameraDistance(mNativeRenderNode); 1387 } 1388 1389 /** 1390 * Sets the left position for the RenderNode. 1391 * 1392 * @param left The left position, in pixels, of the RenderNode 1393 * @return true if the value changed, false otherwise 1394 * @hide 1395 */ setLeft(int left)1396 public boolean setLeft(int left) { 1397 return nSetLeft(mNativeRenderNode, left); 1398 } 1399 1400 /** 1401 * Sets the top position for the RenderNode. 1402 * 1403 * @param top The top position, in pixels, of the RenderNode 1404 * @return true if the value changed, false otherwise. 1405 * @hide 1406 */ setTop(int top)1407 public boolean setTop(int top) { 1408 return nSetTop(mNativeRenderNode, top); 1409 } 1410 1411 /** 1412 * Sets the right position for the RenderNode. 1413 * 1414 * @param right The right position, in pixels, of the RenderNode 1415 * @return true if the value changed, false otherwise. 1416 * @hide 1417 */ setRight(int right)1418 public boolean setRight(int right) { 1419 return nSetRight(mNativeRenderNode, right); 1420 } 1421 1422 /** 1423 * Sets the bottom position for the RenderNode. 1424 * 1425 * @param bottom The bottom position, in pixels, of the RenderNode 1426 * @return true if the value changed, false otherwise. 1427 * @hide 1428 */ setBottom(int bottom)1429 public boolean setBottom(int bottom) { 1430 return nSetBottom(mNativeRenderNode, bottom); 1431 } 1432 1433 /** 1434 * Gets the left position for the RenderNode. 1435 * 1436 * @return the left position in pixels 1437 */ getLeft()1438 public int getLeft() { 1439 return nGetLeft(mNativeRenderNode); 1440 } 1441 1442 /** 1443 * Gets the top position for the RenderNode. 1444 * 1445 * @return the top position in pixels 1446 */ getTop()1447 public int getTop() { 1448 return nGetTop(mNativeRenderNode); 1449 } 1450 1451 /** 1452 * Gets the right position for the RenderNode. 1453 * 1454 * @return the right position in pixels 1455 */ getRight()1456 public int getRight() { 1457 return nGetRight(mNativeRenderNode); 1458 } 1459 1460 /** 1461 * Gets the bottom position for the RenderNode. 1462 * 1463 * @return the bottom position in pixels 1464 */ getBottom()1465 public int getBottom() { 1466 return nGetBottom(mNativeRenderNode); 1467 } 1468 1469 /** 1470 * Gets the width of the RenderNode, which is the right - left. 1471 * 1472 * @return the width of the RenderNode 1473 */ getWidth()1474 public int getWidth() { 1475 return nGetWidth(mNativeRenderNode); 1476 } 1477 1478 /** 1479 * Gets the height of the RenderNode, which is the bottom - top. 1480 * 1481 * @return the height of the RenderNode 1482 */ getHeight()1483 public int getHeight() { 1484 return nGetHeight(mNativeRenderNode); 1485 } 1486 1487 /** 1488 * Sets the left, top, right, and bottom of the RenderNode. 1489 * 1490 * @param left The left position of the RenderNode, in pixels 1491 * @param top The top position of the RenderNode, in pixels 1492 * @param right The right position of the RenderNode, in pixels 1493 * @param bottom The bottom position of the RenderNode, in pixels 1494 * @return true if any values changed, false otherwise. 1495 * @hide 1496 */ setLeftTopRightBottom(int left, int top, int right, int bottom)1497 public boolean setLeftTopRightBottom(int left, int top, int right, int bottom) { 1498 return nSetLeftTopRightBottom(mNativeRenderNode, left, top, right, bottom); 1499 } 1500 1501 /** 1502 * Sets the position of the RenderNode. 1503 * 1504 * @param left The left position of the RenderNode, in pixels 1505 * @param top The top position of the RenderNode, in pixels 1506 * @param right The right position of the RenderNode, in pixels 1507 * @param bottom The bottom position of the RenderNode, in pixels 1508 * @return True if the value changed, false if the new value was the same as the previous value. 1509 */ setPosition(int left, int top, int right, int bottom)1510 public boolean setPosition(int left, int top, int right, int bottom) { 1511 return nSetLeftTopRightBottom(mNativeRenderNode, left, top, right, bottom); 1512 } 1513 1514 /** 1515 * Sets the position of the RenderNode. 1516 * 1517 * @param position The position rectangle in pixels 1518 * @return True if the value changed, false if the new value was the same as the previous value. 1519 */ setPosition(@onNull Rect position)1520 public boolean setPosition(@NonNull Rect position) { 1521 return nSetLeftTopRightBottom(mNativeRenderNode, 1522 position.left, position.top, position.right, position.bottom); 1523 } 1524 1525 /** 1526 * Offsets the left and right positions for the RenderNode 1527 * 1528 * @param offset The amount that the left and right positions are offset in pixels 1529 * @return True if the value changed, false if the new value was the same as the previous value. 1530 */ offsetLeftAndRight(int offset)1531 public boolean offsetLeftAndRight(int offset) { 1532 return nOffsetLeftAndRight(mNativeRenderNode, offset); 1533 } 1534 1535 /** 1536 * Offsets the top and bottom values for the RenderNode 1537 * 1538 * @param offset The amount that the left and right positions are offset in pixels 1539 * @return True if the value changed, false if the new value was the same as the previous value. 1540 */ offsetTopAndBottom(int offset)1541 public boolean offsetTopAndBottom(int offset) { 1542 return nOffsetTopAndBottom(mNativeRenderNode, offset); 1543 } 1544 1545 /** 1546 * Outputs the RenderNode to the log. This method exists for use by 1547 * tools to output display lists for selected nodes to the log. 1548 * 1549 * @hide TODO: Expose? Should the shape of this be different than forced dump to logcat? 1550 */ output()1551 public void output() { 1552 nOutput(mNativeRenderNode); 1553 } 1554 1555 /** 1556 * Gets the approximate memory usage of the RenderNode for debug purposes. Does not include 1557 * the memory usage of any child RenderNodes nor any bitmaps, only the memory usage of 1558 * this RenderNode and any data it owns. 1559 * 1560 * @return Approximate memory usage in bytes. 1561 */ computeApproximateMemoryUsage()1562 public @BytesLong long computeApproximateMemoryUsage() { 1563 return nGetUsageSize(mNativeRenderNode); 1564 } 1565 1566 /** 1567 * Gets the approximate amount of memory allocated for the RenderNode for debug purposes. 1568 * Does not include the memory allocated by any child RenderNodes nor any bitmaps, only the 1569 * memory allocated for this RenderNode and any data it owns. 1570 * 1571 * The difference between this and {@link #computeApproximateMemoryUsage()} is this includes 1572 * memory allocated but not used. In particular structures such as DisplayLists are similar 1573 * to things like ArrayLists - they need to resize as commands are added to them. As such, 1574 * memory used can be less than memory allocated. 1575 * 1576 * @hide */ computeApproximateMemoryAllocated()1577 public @BytesLong long computeApproximateMemoryAllocated() { 1578 return nGetAllocatedSize(mNativeRenderNode); 1579 } 1580 1581 /** 1582 * Sets whether or not to allow force dark to apply to this RenderNode. 1583 * 1584 * Setting this to false will disable the auto-dark feature on everything this RenderNode 1585 * draws, including any descendants. 1586 * 1587 * Setting this to true will allow this RenderNode to be automatically made dark, however 1588 * a value of 'true' will not override any 'false' value in its parent chain nor will 1589 * it prevent any 'false' in any of its children. 1590 * 1591 * @param allow Whether or not to allow force dark. 1592 * @return True if the value changed, false if the new value was the same as the previous value. 1593 */ setForceDarkAllowed(boolean allow)1594 public boolean setForceDarkAllowed(boolean allow) { 1595 return nSetAllowForceDark(mNativeRenderNode, allow); 1596 } 1597 1598 /** 1599 * See {@link #setForceDarkAllowed(boolean)} 1600 * 1601 * @return true if force dark is allowed (default), false if it is disabled 1602 */ isForceDarkAllowed()1603 public boolean isForceDarkAllowed() { 1604 return nGetAllowForceDark(mNativeRenderNode); 1605 } 1606 1607 /** 1608 * Returns the unique ID that identifies this RenderNode. This ID is unique for the 1609 * lifetime of the process. IDs are reset on process death, and are unique only within 1610 * the process. 1611 * 1612 * This ID is intended to be used with debugging tools to associate a particular 1613 * RenderNode across different debug dumping & inspection tools. For example 1614 * a View layout inspector should include the unique ID for any RenderNodes that it owns 1615 * to associate the drawing content with the layout content. 1616 * 1617 * @return the unique ID for this RenderNode 1618 */ getUniqueId()1619 public long getUniqueId() { 1620 return nGetUniqueId(mNativeRenderNode); 1621 } 1622 1623 /** 1624 * Captures whether this RenderNote represents a TextureView 1625 * TODO(b/281695725): Clean this up once TextureView use setFrameRate API 1626 * 1627 * @hide 1628 */ setIsTextureView()1629 public void setIsTextureView() { 1630 nSetIsTextureView(mNativeRenderNode); 1631 } 1632 1633 /////////////////////////////////////////////////////////////////////////// 1634 // Animations 1635 /////////////////////////////////////////////////////////////////////////// 1636 1637 /** 1638 * TODO: Figure out if this can be eliminated/refactored away 1639 * 1640 * For now this interface exists to de-couple RenderNode from anything View-specific in a 1641 * bit of a kludge. 1642 * 1643 * @hide 1644 */ 1645 public interface AnimationHost { 1646 /** @hide */ registerAnimatingRenderNode(RenderNode renderNode, Animator animator)1647 void registerAnimatingRenderNode(RenderNode renderNode, Animator animator); 1648 1649 /** @hide */ registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator)1650 void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator); 1651 1652 /** @hide */ isAttached()1653 boolean isAttached(); 1654 } 1655 1656 /** @hide */ addAnimator(RenderNodeAnimator animator)1657 public void addAnimator(RenderNodeAnimator animator) { 1658 if (!isAttached()) { 1659 throw new IllegalStateException("Cannot start this animator on a detached view!"); 1660 } 1661 nAddAnimator(mNativeRenderNode, animator.getNativeAnimator()); 1662 mAnimationHost.registerAnimatingRenderNode(this, animator); 1663 } 1664 1665 /** @hide */ isAttached()1666 public boolean isAttached() { 1667 return mAnimationHost != null && mAnimationHost.isAttached(); 1668 } 1669 1670 /** @hide */ registerVectorDrawableAnimator(NativeVectorDrawableAnimator animatorSet)1671 public void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animatorSet) { 1672 if (!isAttached()) { 1673 throw new IllegalStateException("Cannot start this animator on a detached view!"); 1674 } 1675 mAnimationHost.registerVectorDrawableAnimator(animatorSet); 1676 } 1677 1678 /** @hide */ endAllAnimators()1679 public void endAllAnimators() { 1680 nEndAllAnimators(mNativeRenderNode); 1681 } 1682 1683 /** @hide */ forceEndAnimators()1684 public void forceEndAnimators() { 1685 nForceEndAnimators(mNativeRenderNode); 1686 } 1687 1688 /////////////////////////////////////////////////////////////////////////// 1689 // Regular JNI methods 1690 /////////////////////////////////////////////////////////////////////////// 1691 nCreate(String name)1692 private static native long nCreate(String name); 1693 nGetNativeFinalizer()1694 private static native long nGetNativeFinalizer(); 1695 nOutput(long renderNode)1696 private static native void nOutput(long renderNode); 1697 nGetUsageSize(long renderNode)1698 private static native int nGetUsageSize(long renderNode); nGetAllocatedSize(long renderNode)1699 private static native int nGetAllocatedSize(long renderNode); 1700 nRequestPositionUpdates(long renderNode, WeakReference<PositionUpdateListener> callback)1701 private static native void nRequestPositionUpdates(long renderNode, 1702 WeakReference<PositionUpdateListener> callback); 1703 1704 // Animations 1705 nAddAnimator(long renderNode, long animatorPtr)1706 private static native void nAddAnimator(long renderNode, long animatorPtr); 1707 nEndAllAnimators(long renderNode)1708 private static native void nEndAllAnimators(long renderNode); 1709 nForceEndAnimators(long renderNode)1710 private static native void nForceEndAnimators(long renderNode); 1711 1712 /////////////////////////////////////////////////////////////////////////// 1713 // @CriticalNative methods 1714 /////////////////////////////////////////////////////////////////////////// 1715 1716 @CriticalNative nDiscardDisplayList(long renderNode)1717 private static native void nDiscardDisplayList(long renderNode); 1718 1719 @CriticalNative nIsValid(long renderNode)1720 private static native boolean nIsValid(long renderNode); 1721 1722 // Matrix 1723 1724 @CriticalNative nGetTransformMatrix(long renderNode, long nativeMatrix)1725 private static native void nGetTransformMatrix(long renderNode, long nativeMatrix); 1726 1727 @CriticalNative nGetInverseTransformMatrix(long renderNode, long nativeMatrix)1728 private static native void nGetInverseTransformMatrix(long renderNode, long nativeMatrix); 1729 1730 @CriticalNative nHasIdentityMatrix(long renderNode)1731 private static native boolean nHasIdentityMatrix(long renderNode); 1732 1733 // Properties 1734 1735 @CriticalNative nOffsetTopAndBottom(long renderNode, int offset)1736 private static native boolean nOffsetTopAndBottom(long renderNode, int offset); 1737 1738 @CriticalNative nOffsetLeftAndRight(long renderNode, int offset)1739 private static native boolean nOffsetLeftAndRight(long renderNode, int offset); 1740 1741 @CriticalNative nSetLeftTopRightBottom(long renderNode, int left, int top, int right, int bottom)1742 private static native boolean nSetLeftTopRightBottom(long renderNode, int left, int top, 1743 int right, int bottom); 1744 1745 @CriticalNative nSetLeft(long renderNode, int left)1746 private static native boolean nSetLeft(long renderNode, int left); 1747 1748 @CriticalNative nSetTop(long renderNode, int top)1749 private static native boolean nSetTop(long renderNode, int top); 1750 1751 @CriticalNative nSetRight(long renderNode, int right)1752 private static native boolean nSetRight(long renderNode, int right); 1753 1754 @CriticalNative nSetBottom(long renderNode, int bottom)1755 private static native boolean nSetBottom(long renderNode, int bottom); 1756 1757 @CriticalNative nGetLeft(long renderNode)1758 private static native int nGetLeft(long renderNode); 1759 1760 @CriticalNative nGetTop(long renderNode)1761 private static native int nGetTop(long renderNode); 1762 1763 @CriticalNative nGetRight(long renderNode)1764 private static native int nGetRight(long renderNode); 1765 1766 @CriticalNative nGetBottom(long renderNode)1767 private static native int nGetBottom(long renderNode); 1768 1769 @CriticalNative nSetCameraDistance(long renderNode, float distance)1770 private static native boolean nSetCameraDistance(long renderNode, float distance); 1771 1772 @CriticalNative nSetPivotY(long renderNode, float pivotY)1773 private static native boolean nSetPivotY(long renderNode, float pivotY); 1774 1775 @CriticalNative nSetPivotX(long renderNode, float pivotX)1776 private static native boolean nSetPivotX(long renderNode, float pivotX); 1777 1778 @CriticalNative nResetPivot(long renderNode)1779 private static native boolean nResetPivot(long renderNode); 1780 1781 @CriticalNative nSetLayerType(long renderNode, int layerType)1782 private static native boolean nSetLayerType(long renderNode, int layerType); 1783 1784 @CriticalNative nGetLayerType(long renderNode)1785 private static native int nGetLayerType(long renderNode); 1786 1787 @CriticalNative nSetLayerPaint(long renderNode, long paint)1788 private static native boolean nSetLayerPaint(long renderNode, long paint); 1789 1790 @CriticalNative nSetClipToBounds(long renderNode, boolean clipToBounds)1791 private static native boolean nSetClipToBounds(long renderNode, boolean clipToBounds); 1792 1793 @CriticalNative nGetClipToBounds(long renderNode)1794 private static native boolean nGetClipToBounds(long renderNode); 1795 1796 @CriticalNative nSetClipBounds(long renderNode, int left, int top, int right, int bottom)1797 private static native boolean nSetClipBounds(long renderNode, int left, int top, 1798 int right, int bottom); 1799 1800 @CriticalNative nSetClipBoundsEmpty(long renderNode)1801 private static native boolean nSetClipBoundsEmpty(long renderNode); 1802 1803 @CriticalNative nSetProjectBackwards(long renderNode, boolean shouldProject)1804 private static native boolean nSetProjectBackwards(long renderNode, boolean shouldProject); 1805 1806 @CriticalNative nSetProjectionReceiver(long renderNode, boolean shouldReceive)1807 private static native boolean nSetProjectionReceiver(long renderNode, boolean shouldReceive); 1808 1809 @CriticalNative nSetOutlineRoundRect(long renderNode, int left, int top, int right, int bottom, float radius, float alpha)1810 private static native boolean nSetOutlineRoundRect(long renderNode, int left, int top, 1811 int right, int bottom, float radius, float alpha); 1812 1813 @CriticalNative nSetOutlinePath(long renderNode, long nativePath, float alpha)1814 private static native boolean nSetOutlinePath(long renderNode, long nativePath, 1815 float alpha); 1816 1817 @CriticalNative nSetOutlineEmpty(long renderNode)1818 private static native boolean nSetOutlineEmpty(long renderNode); 1819 1820 @CriticalNative nSetOutlineNone(long renderNode)1821 private static native boolean nSetOutlineNone(long renderNode); 1822 1823 @CriticalNative nClearStretch(long renderNode)1824 private static native boolean nClearStretch(long renderNode); 1825 1826 @CriticalNative nStretch(long renderNode, float vecX, float vecY, float maxStretchX, float maxStretchY)1827 private static native boolean nStretch(long renderNode, float vecX, float vecY, 1828 float maxStretchX, float maxStretchY); 1829 1830 @CriticalNative nHasShadow(long renderNode)1831 private static native boolean nHasShadow(long renderNode); 1832 1833 @CriticalNative nSetSpotShadowColor(long renderNode, int color)1834 private static native boolean nSetSpotShadowColor(long renderNode, int color); 1835 1836 @CriticalNative nSetAmbientShadowColor(long renderNode, int color)1837 private static native boolean nSetAmbientShadowColor(long renderNode, int color); 1838 1839 @CriticalNative nGetSpotShadowColor(long renderNode)1840 private static native int nGetSpotShadowColor(long renderNode); 1841 1842 @CriticalNative nGetAmbientShadowColor(long renderNode)1843 private static native int nGetAmbientShadowColor(long renderNode); 1844 1845 @CriticalNative nSetClipToOutline(long renderNode, boolean clipToOutline)1846 private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline); 1847 1848 @CriticalNative nSetRevealClip(long renderNode, boolean shouldClip, float x, float y, float radius)1849 private static native boolean nSetRevealClip(long renderNode, 1850 boolean shouldClip, float x, float y, float radius); 1851 1852 @CriticalNative nSetAlpha(long renderNode, float alpha)1853 private static native boolean nSetAlpha(long renderNode, float alpha); 1854 1855 @CriticalNative nSetRenderEffect(long renderNode, long renderEffect)1856 private static native boolean nSetRenderEffect(long renderNode, long renderEffect); 1857 1858 @CriticalNative nSetBackdropRenderEffect(long renderNode, long renderEffect)1859 private static native boolean nSetBackdropRenderEffect(long renderNode, long renderEffect); 1860 1861 @CriticalNative nSetHasOverlappingRendering(long renderNode, boolean hasOverlappingRendering)1862 private static native boolean nSetHasOverlappingRendering(long renderNode, 1863 boolean hasOverlappingRendering); 1864 1865 @CriticalNative nSetUsageHint(long renderNode, int usageHint)1866 private static native void nSetUsageHint(long renderNode, int usageHint); 1867 1868 @CriticalNative nSetElevation(long renderNode, float lift)1869 private static native boolean nSetElevation(long renderNode, float lift); 1870 1871 @CriticalNative nSetTranslationX(long renderNode, float translationX)1872 private static native boolean nSetTranslationX(long renderNode, float translationX); 1873 1874 @CriticalNative nSetTranslationY(long renderNode, float translationY)1875 private static native boolean nSetTranslationY(long renderNode, float translationY); 1876 1877 @CriticalNative nSetTranslationZ(long renderNode, float translationZ)1878 private static native boolean nSetTranslationZ(long renderNode, float translationZ); 1879 1880 @CriticalNative nSetRotation(long renderNode, float rotation)1881 private static native boolean nSetRotation(long renderNode, float rotation); 1882 1883 @CriticalNative nSetRotationX(long renderNode, float rotationX)1884 private static native boolean nSetRotationX(long renderNode, float rotationX); 1885 1886 @CriticalNative nSetRotationY(long renderNode, float rotationY)1887 private static native boolean nSetRotationY(long renderNode, float rotationY); 1888 1889 @CriticalNative nSetScaleX(long renderNode, float scaleX)1890 private static native boolean nSetScaleX(long renderNode, float scaleX); 1891 1892 @CriticalNative nSetScaleY(long renderNode, float scaleY)1893 private static native boolean nSetScaleY(long renderNode, float scaleY); 1894 1895 @CriticalNative nSetStaticMatrix(long renderNode, long nativeMatrix)1896 private static native boolean nSetStaticMatrix(long renderNode, long nativeMatrix); 1897 1898 @CriticalNative nSetAnimationMatrix(long renderNode, long animationMatrix)1899 private static native boolean nSetAnimationMatrix(long renderNode, long animationMatrix); 1900 1901 @CriticalNative nHasOverlappingRendering(long renderNode)1902 private static native boolean nHasOverlappingRendering(long renderNode); 1903 1904 @CriticalNative nGetAnimationMatrix(long renderNode, long animationMatrix)1905 private static native boolean nGetAnimationMatrix(long renderNode, long animationMatrix); 1906 1907 @CriticalNative nGetClipToOutline(long renderNode)1908 private static native boolean nGetClipToOutline(long renderNode); 1909 1910 @CriticalNative nGetAlpha(long renderNode)1911 private static native float nGetAlpha(long renderNode); 1912 1913 @CriticalNative nGetCameraDistance(long renderNode)1914 private static native float nGetCameraDistance(long renderNode); 1915 1916 @CriticalNative nGetScaleX(long renderNode)1917 private static native float nGetScaleX(long renderNode); 1918 1919 @CriticalNative nGetScaleY(long renderNode)1920 private static native float nGetScaleY(long renderNode); 1921 1922 @CriticalNative nGetElevation(long renderNode)1923 private static native float nGetElevation(long renderNode); 1924 1925 @CriticalNative nGetTranslationX(long renderNode)1926 private static native float nGetTranslationX(long renderNode); 1927 1928 @CriticalNative nGetTranslationY(long renderNode)1929 private static native float nGetTranslationY(long renderNode); 1930 1931 @CriticalNative nGetTranslationZ(long renderNode)1932 private static native float nGetTranslationZ(long renderNode); 1933 1934 @CriticalNative nGetRotation(long renderNode)1935 private static native float nGetRotation(long renderNode); 1936 1937 @CriticalNative nGetRotationX(long renderNode)1938 private static native float nGetRotationX(long renderNode); 1939 1940 @CriticalNative nGetRotationY(long renderNode)1941 private static native float nGetRotationY(long renderNode); 1942 1943 @CriticalNative nIsPivotExplicitlySet(long renderNode)1944 private static native boolean nIsPivotExplicitlySet(long renderNode); 1945 1946 @CriticalNative nGetPivotX(long renderNode)1947 private static native float nGetPivotX(long renderNode); 1948 1949 @CriticalNative nGetPivotY(long renderNode)1950 private static native float nGetPivotY(long renderNode); 1951 1952 @CriticalNative nGetWidth(long renderNode)1953 private static native int nGetWidth(long renderNode); 1954 1955 @CriticalNative nGetHeight(long renderNode)1956 private static native int nGetHeight(long renderNode); 1957 1958 @CriticalNative nSetAllowForceDark(long renderNode, boolean allowForceDark)1959 private static native boolean nSetAllowForceDark(long renderNode, boolean allowForceDark); 1960 1961 @CriticalNative nGetAllowForceDark(long renderNode)1962 private static native boolean nGetAllowForceDark(long renderNode); 1963 1964 @CriticalNative nGetUniqueId(long renderNode)1965 private static native long nGetUniqueId(long renderNode); 1966 1967 @CriticalNative nSetIsTextureView(long renderNode)1968 private static native void nSetIsTextureView(long renderNode); 1969 } 1970