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