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