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      * Captures whether this RenderNote represents a TextureView
1566      * TODO(b/281695725): Clean this up once TextureView use setFrameRate API
1567      *
1568      * @hide
1569      */
setIsTextureView()1570     public void setIsTextureView() {
1571         nSetIsTextureView(mNativeRenderNode);
1572     }
1573 
1574     ///////////////////////////////////////////////////////////////////////////
1575     // Animations
1576     ///////////////////////////////////////////////////////////////////////////
1577 
1578     /**
1579      * TODO: Figure out if this can be eliminated/refactored away
1580      *
1581      * For now this interface exists to de-couple RenderNode from anything View-specific in a
1582      * bit of a kludge.
1583      *
1584      * @hide
1585      */
1586     public interface AnimationHost {
1587         /** @hide */
registerAnimatingRenderNode(RenderNode animator)1588         void registerAnimatingRenderNode(RenderNode animator);
1589 
1590         /** @hide */
registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator)1591         void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator);
1592 
1593         /** @hide */
isAttached()1594         boolean isAttached();
1595     }
1596 
1597     /** @hide */
addAnimator(RenderNodeAnimator animator)1598     public void addAnimator(RenderNodeAnimator animator) {
1599         if (!isAttached()) {
1600             throw new IllegalStateException("Cannot start this animator on a detached view!");
1601         }
1602         nAddAnimator(mNativeRenderNode, animator.getNativeAnimator());
1603         mAnimationHost.registerAnimatingRenderNode(this);
1604     }
1605 
1606     /** @hide */
isAttached()1607     public boolean isAttached() {
1608         return mAnimationHost != null && mAnimationHost.isAttached();
1609     }
1610 
1611     /** @hide */
registerVectorDrawableAnimator(NativeVectorDrawableAnimator animatorSet)1612     public void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animatorSet) {
1613         if (!isAttached()) {
1614             throw new IllegalStateException("Cannot start this animator on a detached view!");
1615         }
1616         mAnimationHost.registerVectorDrawableAnimator(animatorSet);
1617     }
1618 
1619     /** @hide */
endAllAnimators()1620     public void endAllAnimators() {
1621         nEndAllAnimators(mNativeRenderNode);
1622     }
1623 
1624     /** @hide */
forceEndAnimators()1625     public void forceEndAnimators() {
1626         nForceEndAnimators(mNativeRenderNode);
1627     }
1628 
1629     ///////////////////////////////////////////////////////////////////////////
1630     // Regular JNI methods
1631     ///////////////////////////////////////////////////////////////////////////
1632 
nCreate(String name)1633     private static native long nCreate(String name);
1634 
nGetNativeFinalizer()1635     private static native long nGetNativeFinalizer();
1636 
nOutput(long renderNode)1637     private static native void nOutput(long renderNode);
1638 
nGetUsageSize(long renderNode)1639     private static native int nGetUsageSize(long renderNode);
nGetAllocatedSize(long renderNode)1640     private static native int nGetAllocatedSize(long renderNode);
1641 
nRequestPositionUpdates(long renderNode, WeakReference<PositionUpdateListener> callback)1642     private static native void nRequestPositionUpdates(long renderNode,
1643             WeakReference<PositionUpdateListener> callback);
1644 
1645     // Animations
1646 
nAddAnimator(long renderNode, long animatorPtr)1647     private static native void nAddAnimator(long renderNode, long animatorPtr);
1648 
nEndAllAnimators(long renderNode)1649     private static native void nEndAllAnimators(long renderNode);
1650 
nForceEndAnimators(long renderNode)1651     private static native void nForceEndAnimators(long renderNode);
1652 
1653     ///////////////////////////////////////////////////////////////////////////
1654     // @CriticalNative methods
1655     ///////////////////////////////////////////////////////////////////////////
1656 
1657     @CriticalNative
nDiscardDisplayList(long renderNode)1658     private static native void nDiscardDisplayList(long renderNode);
1659 
1660     @CriticalNative
nIsValid(long renderNode)1661     private static native boolean nIsValid(long renderNode);
1662 
1663     // Matrix
1664 
1665     @CriticalNative
nGetTransformMatrix(long renderNode, long nativeMatrix)1666     private static native void nGetTransformMatrix(long renderNode, long nativeMatrix);
1667 
1668     @CriticalNative
nGetInverseTransformMatrix(long renderNode, long nativeMatrix)1669     private static native void nGetInverseTransformMatrix(long renderNode, long nativeMatrix);
1670 
1671     @CriticalNative
nHasIdentityMatrix(long renderNode)1672     private static native boolean nHasIdentityMatrix(long renderNode);
1673 
1674     // Properties
1675 
1676     @CriticalNative
nOffsetTopAndBottom(long renderNode, int offset)1677     private static native boolean nOffsetTopAndBottom(long renderNode, int offset);
1678 
1679     @CriticalNative
nOffsetLeftAndRight(long renderNode, int offset)1680     private static native boolean nOffsetLeftAndRight(long renderNode, int offset);
1681 
1682     @CriticalNative
nSetLeftTopRightBottom(long renderNode, int left, int top, int right, int bottom)1683     private static native boolean nSetLeftTopRightBottom(long renderNode, int left, int top,
1684             int right, int bottom);
1685 
1686     @CriticalNative
nSetLeft(long renderNode, int left)1687     private static native boolean nSetLeft(long renderNode, int left);
1688 
1689     @CriticalNative
nSetTop(long renderNode, int top)1690     private static native boolean nSetTop(long renderNode, int top);
1691 
1692     @CriticalNative
nSetRight(long renderNode, int right)1693     private static native boolean nSetRight(long renderNode, int right);
1694 
1695     @CriticalNative
nSetBottom(long renderNode, int bottom)1696     private static native boolean nSetBottom(long renderNode, int bottom);
1697 
1698     @CriticalNative
nGetLeft(long renderNode)1699     private static native int nGetLeft(long renderNode);
1700 
1701     @CriticalNative
nGetTop(long renderNode)1702     private static native int nGetTop(long renderNode);
1703 
1704     @CriticalNative
nGetRight(long renderNode)1705     private static native int nGetRight(long renderNode);
1706 
1707     @CriticalNative
nGetBottom(long renderNode)1708     private static native int nGetBottom(long renderNode);
1709 
1710     @CriticalNative
nSetCameraDistance(long renderNode, float distance)1711     private static native boolean nSetCameraDistance(long renderNode, float distance);
1712 
1713     @CriticalNative
nSetPivotY(long renderNode, float pivotY)1714     private static native boolean nSetPivotY(long renderNode, float pivotY);
1715 
1716     @CriticalNative
nSetPivotX(long renderNode, float pivotX)1717     private static native boolean nSetPivotX(long renderNode, float pivotX);
1718 
1719     @CriticalNative
nResetPivot(long renderNode)1720     private static native boolean nResetPivot(long renderNode);
1721 
1722     @CriticalNative
nSetLayerType(long renderNode, int layerType)1723     private static native boolean nSetLayerType(long renderNode, int layerType);
1724 
1725     @CriticalNative
nGetLayerType(long renderNode)1726     private static native int nGetLayerType(long renderNode);
1727 
1728     @CriticalNative
nSetLayerPaint(long renderNode, long paint)1729     private static native boolean nSetLayerPaint(long renderNode, long paint);
1730 
1731     @CriticalNative
nSetClipToBounds(long renderNode, boolean clipToBounds)1732     private static native boolean nSetClipToBounds(long renderNode, boolean clipToBounds);
1733 
1734     @CriticalNative
nGetClipToBounds(long renderNode)1735     private static native boolean nGetClipToBounds(long renderNode);
1736 
1737     @CriticalNative
nSetClipBounds(long renderNode, int left, int top, int right, int bottom)1738     private static native boolean nSetClipBounds(long renderNode, int left, int top,
1739             int right, int bottom);
1740 
1741     @CriticalNative
nSetClipBoundsEmpty(long renderNode)1742     private static native boolean nSetClipBoundsEmpty(long renderNode);
1743 
1744     @CriticalNative
nSetProjectBackwards(long renderNode, boolean shouldProject)1745     private static native boolean nSetProjectBackwards(long renderNode, boolean shouldProject);
1746 
1747     @CriticalNative
nSetProjectionReceiver(long renderNode, boolean shouldRecieve)1748     private static native boolean nSetProjectionReceiver(long renderNode, boolean shouldRecieve);
1749 
1750     @CriticalNative
nSetOutlineRoundRect(long renderNode, int left, int top, int right, int bottom, float radius, float alpha)1751     private static native boolean nSetOutlineRoundRect(long renderNode, int left, int top,
1752             int right, int bottom, float radius, float alpha);
1753 
1754     @CriticalNative
nSetOutlinePath(long renderNode, long nativePath, float alpha)1755     private static native boolean nSetOutlinePath(long renderNode, long nativePath,
1756             float alpha);
1757 
1758     @CriticalNative
nSetOutlineEmpty(long renderNode)1759     private static native boolean nSetOutlineEmpty(long renderNode);
1760 
1761     @CriticalNative
nSetOutlineNone(long renderNode)1762     private static native boolean nSetOutlineNone(long renderNode);
1763 
1764     @CriticalNative
nClearStretch(long renderNode)1765     private static native boolean nClearStretch(long renderNode);
1766 
1767     @CriticalNative
nStretch(long renderNode, float vecX, float vecY, float maxStretchX, float maxStretchY)1768     private static native boolean nStretch(long renderNode, float vecX, float vecY,
1769             float maxStretchX, float maxStretchY);
1770 
1771     @CriticalNative
nHasShadow(long renderNode)1772     private static native boolean nHasShadow(long renderNode);
1773 
1774     @CriticalNative
nSetSpotShadowColor(long renderNode, int color)1775     private static native boolean nSetSpotShadowColor(long renderNode, int color);
1776 
1777     @CriticalNative
nSetAmbientShadowColor(long renderNode, int color)1778     private static native boolean nSetAmbientShadowColor(long renderNode, int color);
1779 
1780     @CriticalNative
nGetSpotShadowColor(long renderNode)1781     private static native int nGetSpotShadowColor(long renderNode);
1782 
1783     @CriticalNative
nGetAmbientShadowColor(long renderNode)1784     private static native int nGetAmbientShadowColor(long renderNode);
1785 
1786     @CriticalNative
nSetClipToOutline(long renderNode, boolean clipToOutline)1787     private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline);
1788 
1789     @CriticalNative
nSetRevealClip(long renderNode, boolean shouldClip, float x, float y, float radius)1790     private static native boolean nSetRevealClip(long renderNode,
1791             boolean shouldClip, float x, float y, float radius);
1792 
1793     @CriticalNative
nSetAlpha(long renderNode, float alpha)1794     private static native boolean nSetAlpha(long renderNode, float alpha);
1795 
1796     @CriticalNative
nSetRenderEffect(long renderNode, long renderEffect)1797     private static native boolean nSetRenderEffect(long renderNode, long renderEffect);
1798 
1799     @CriticalNative
nSetHasOverlappingRendering(long renderNode, boolean hasOverlappingRendering)1800     private static native boolean nSetHasOverlappingRendering(long renderNode,
1801             boolean hasOverlappingRendering);
1802 
1803     @CriticalNative
nSetUsageHint(long renderNode, int usageHint)1804     private static native void nSetUsageHint(long renderNode, int usageHint);
1805 
1806     @CriticalNative
nSetElevation(long renderNode, float lift)1807     private static native boolean nSetElevation(long renderNode, float lift);
1808 
1809     @CriticalNative
nSetTranslationX(long renderNode, float translationX)1810     private static native boolean nSetTranslationX(long renderNode, float translationX);
1811 
1812     @CriticalNative
nSetTranslationY(long renderNode, float translationY)1813     private static native boolean nSetTranslationY(long renderNode, float translationY);
1814 
1815     @CriticalNative
nSetTranslationZ(long renderNode, float translationZ)1816     private static native boolean nSetTranslationZ(long renderNode, float translationZ);
1817 
1818     @CriticalNative
nSetRotation(long renderNode, float rotation)1819     private static native boolean nSetRotation(long renderNode, float rotation);
1820 
1821     @CriticalNative
nSetRotationX(long renderNode, float rotationX)1822     private static native boolean nSetRotationX(long renderNode, float rotationX);
1823 
1824     @CriticalNative
nSetRotationY(long renderNode, float rotationY)1825     private static native boolean nSetRotationY(long renderNode, float rotationY);
1826 
1827     @CriticalNative
nSetScaleX(long renderNode, float scaleX)1828     private static native boolean nSetScaleX(long renderNode, float scaleX);
1829 
1830     @CriticalNative
nSetScaleY(long renderNode, float scaleY)1831     private static native boolean nSetScaleY(long renderNode, float scaleY);
1832 
1833     @CriticalNative
nSetStaticMatrix(long renderNode, long nativeMatrix)1834     private static native boolean nSetStaticMatrix(long renderNode, long nativeMatrix);
1835 
1836     @CriticalNative
nSetAnimationMatrix(long renderNode, long animationMatrix)1837     private static native boolean nSetAnimationMatrix(long renderNode, long animationMatrix);
1838 
1839     @CriticalNative
nHasOverlappingRendering(long renderNode)1840     private static native boolean nHasOverlappingRendering(long renderNode);
1841 
1842     @CriticalNative
nGetAnimationMatrix(long renderNode, long animationMatrix)1843     private static native boolean nGetAnimationMatrix(long renderNode, long animationMatrix);
1844 
1845     @CriticalNative
nGetClipToOutline(long renderNode)1846     private static native boolean nGetClipToOutline(long renderNode);
1847 
1848     @CriticalNative
nGetAlpha(long renderNode)1849     private static native float nGetAlpha(long renderNode);
1850 
1851     @CriticalNative
nGetCameraDistance(long renderNode)1852     private static native float nGetCameraDistance(long renderNode);
1853 
1854     @CriticalNative
nGetScaleX(long renderNode)1855     private static native float nGetScaleX(long renderNode);
1856 
1857     @CriticalNative
nGetScaleY(long renderNode)1858     private static native float nGetScaleY(long renderNode);
1859 
1860     @CriticalNative
nGetElevation(long renderNode)1861     private static native float nGetElevation(long renderNode);
1862 
1863     @CriticalNative
nGetTranslationX(long renderNode)1864     private static native float nGetTranslationX(long renderNode);
1865 
1866     @CriticalNative
nGetTranslationY(long renderNode)1867     private static native float nGetTranslationY(long renderNode);
1868 
1869     @CriticalNative
nGetTranslationZ(long renderNode)1870     private static native float nGetTranslationZ(long renderNode);
1871 
1872     @CriticalNative
nGetRotation(long renderNode)1873     private static native float nGetRotation(long renderNode);
1874 
1875     @CriticalNative
nGetRotationX(long renderNode)1876     private static native float nGetRotationX(long renderNode);
1877 
1878     @CriticalNative
nGetRotationY(long renderNode)1879     private static native float nGetRotationY(long renderNode);
1880 
1881     @CriticalNative
nIsPivotExplicitlySet(long renderNode)1882     private static native boolean nIsPivotExplicitlySet(long renderNode);
1883 
1884     @CriticalNative
nGetPivotX(long renderNode)1885     private static native float nGetPivotX(long renderNode);
1886 
1887     @CriticalNative
nGetPivotY(long renderNode)1888     private static native float nGetPivotY(long renderNode);
1889 
1890     @CriticalNative
nGetWidth(long renderNode)1891     private static native int nGetWidth(long renderNode);
1892 
1893     @CriticalNative
nGetHeight(long renderNode)1894     private static native int nGetHeight(long renderNode);
1895 
1896     @CriticalNative
nSetAllowForceDark(long renderNode, boolean allowForceDark)1897     private static native boolean nSetAllowForceDark(long renderNode, boolean allowForceDark);
1898 
1899     @CriticalNative
nGetAllowForceDark(long renderNode)1900     private static native boolean nGetAllowForceDark(long renderNode);
1901 
1902     @CriticalNative
nGetUniqueId(long renderNode)1903     private static native long nGetUniqueId(long renderNode);
1904 
1905     @CriticalNative
nSetIsTextureView(long renderNode)1906     private static native void nSetIsTextureView(long renderNode);
1907 }
1908