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