Files
frameworks_base/graphics/java/android/graphics/RenderNode.java
Andrew Sapperstein 8fe35e5f21 Fix broken @see tags in public documentation.
These were previously being suppressed by doclava but with this change,
all failures are fixed and the suppression logic has been removed.

To fix the issues, there were a few possible changes made:
- broken reference to a public API (such as incorrect parameters): fixed
- unnecessary @link inside an @see tag: fixed
- @see referring to an @hide or @SystemApi: reference removed
- broken references to inner class constructors
 - worked around by fully qualifying the constructor

Bug: 6963924
Test: make doc-comment-check-docs
Exempt-From-Owner-Approval: cherry-picked from master
Change-Id: Ifbdce2de96cdffa560bd90f549fa7184d1f9af85
Merged-In: Ifbdce2de96cdffa560bd90f549fa7184d1f9af85
(cherry picked from commit e0624c7a40)
2020-05-01 18:25:32 +00:00

1763 lines
66 KiB
Java

/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.graphics;
import android.annotation.BytesLong;
import android.annotation.ColorInt;
import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.animation.RenderNodeAnimator;
import android.view.NativeVectorDrawableAnimator;
import android.view.Surface;
import android.view.View;
import com.android.internal.util.ArrayUtils;
import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
import libcore.util.NativeAllocationRegistry;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* <p>RenderNode is used to build hardware accelerated rendering hierarchies. Each RenderNode
* contains both a display list as well as a set of properties that affect the rendering of the
* display list. RenderNodes are used internally for all Views by default and are not typically
* used directly.</p>
*
* <p>RenderNodes are used to divide up the rendering content of a complex scene into smaller
* pieces that can then be updated individually more cheaply. Updating part of the scene only needs
* to update the display list or properties of a small number of RenderNode instead of redrawing
* everything from scratch. A RenderNode only needs its display list re-recorded when its content
* alone should be changed. RenderNodes can also be transformed without re-recording the display
* list through the transform properties.</p>
*
* <p>A text editor might for instance store each paragraph into its own RenderNode.
* Thus when the user inserts or removes characters, only the display list of the
* affected paragraph needs to be recorded again.</p>
*
* <h3>Hardware acceleration</h3>
* <p>RenderNodes can be drawn using a {@link RecordingCanvas}. They are not
* supported in software. Always make sure that the {@link android.graphics.Canvas}
* you are using to render a display list is hardware accelerated using
* {@link android.graphics.Canvas#isHardwareAccelerated()}.</p>
*
* <h3>Creating a RenderNode</h3>
* <pre class="prettyprint">
* RenderNode renderNode = new RenderNode("myRenderNode");
* renderNode.setPosition(0, 0, 50, 50); // Set the size to 50x50
* RecordingCanvas canvas = renderNode.beginRecording();
* try {
* // Draw with the canvas
* canvas.drawRect(...);
* } finally {
* renderNode.endRecording();
* }</pre>
*
* <h3>Drawing a RenderNode in a View</h3>
* <pre class="prettyprint">
* protected void onDraw(Canvas canvas) {
* if (canvas.isHardwareAccelerated()) {
* // Check that the RenderNode has a display list, re-recording it if it does not.
* if (!myRenderNode.hasDisplayList()) {
* updateDisplayList(myRenderNode);
* }
* // Draw the RenderNode into this canvas.
* canvas.drawRenderNode(myRenderNode);
* }
* }</pre>
*
* <h3>Releasing resources</h3>
* <p>This step is not mandatory but recommended if you want to release resources
* held by a display list as soon as possible. Most significantly any bitmaps it may contain.</p>
* <pre class="prettyprint">
* // Discards the display list content allowing for any held resources to be released.
* // After calling this
* renderNode.discardDisplayList();</pre>
*
*
* <h3>Properties</h3>
* <p>In addition, a RenderNode offers several properties, such as
* {@link #setScaleX(float)} or {@link #setTranslationX(float)}, that can be used to affect all
* the drawing commands recorded within. For instance, these properties can be used
* to move around a large number of images without re-issuing all the individual
* <code>canvas.drawBitmap()</code> calls.</p>
*
* <pre class="prettyprint">
* private void createDisplayList() {
* mRenderNode = new RenderNode("MyRenderNode");
* mRenderNode.setPosition(0, 0, width, height);
* RecordingCanvas canvas = mRenderNode.beginRecording();
* try {
* for (Bitmap b : mBitmaps) {
* canvas.drawBitmap(b, 0.0f, 0.0f, null);
* canvas.translate(0.0f, b.getHeight());
* }
* } finally {
* mRenderNode.endRecording();
* }
* }
*
* protected void onDraw(Canvas canvas) {
* if (canvas.isHardwareAccelerated())
* canvas.drawRenderNode(mRenderNode);
* }
* }
*
* private void moveContentBy(int x) {
* // This will move all the bitmaps recorded inside the display list
* // by x pixels to the right and redraw this view. All the commands
* // recorded in createDisplayList() won't be re-issued, only onDraw()
* // will be invoked and will execute very quickly
* mRenderNode.offsetLeftAndRight(x);
* invalidate();
* }</pre>
*
* <p>A few of the properties may at first appear redundant, such as {@link #setElevation(float)}
* and {@link #setTranslationZ(float)}. The reason for these duplicates are to allow for a
* separation between static & transient usages. For example consider a button that raises from 2dp
* to 8dp when pressed. To achieve that an application may decide to setElevation(2dip), and then
* on press to animate setTranslationZ to 6dip. Combined this achieves the final desired 8dip
* value, but the animation need only concern itself with animating the lift from press without
* needing to know the initial starting value. {@link #setTranslationX(float)} and
* {@link #setTranslationY(float)} are similarly provided for animation uses despite the functional
* overlap with {@link #setPosition(Rect)}.
*
* <p>The RenderNode's transform matrix is computed at render time as follows:
* <pre class="prettyprint">
* Matrix transform = new Matrix();
* transform.setTranslate(renderNode.getTranslationX(), renderNode.getTranslationY());
* transform.preRotate(renderNode.getRotationZ(),
* renderNode.getPivotX(), renderNode.getPivotY());
* transform.preScale(renderNode.getScaleX(), renderNode.getScaleY(),
* renderNode.getPivotX(), renderNode.getPivotY());</pre>
* The current canvas transform matrix, which is translated to the RenderNode's position,
* is then multiplied by the RenderNode's transform matrix. Therefore the ordering of calling
* property setters does not affect the result. That is to say that:
*
* <pre class="prettyprint">
* renderNode.setTranslationX(100);
* renderNode.setScaleX(100);</pre>
*
* is equivalent to:
*
* <pre class="prettyprint">
* renderNode.setScaleX(100);
* renderNode.setTranslationX(100);</pre>
*
* <h3>Threading</h3>
* <p>RenderNode may be created and used on any thread but they are not thread-safe. Only
* a single thread may interact with a RenderNode at any given time. It is critical
* that the RenderNode is only used on the same thread it is drawn with. For example when using
* RenderNode with a custom View, then that RenderNode must only be used from the UI thread.</p>
*
* <h3>When to re-render</h3>
* <p>Many of the RenderNode mutation methods, such as {@link #setTranslationX(float)}, return
* a boolean indicating if the value actually changed or not. This is useful in detecting
* if a new frame should be rendered or not. A typical usage would look like:
* <pre class="prettyprint">
* public void translateTo(int x, int y) {
* boolean needsUpdate = myRenderNode.setTranslationX(x);
* needsUpdate |= myRenderNode.setTranslationY(y);
* if (needsUpdate) {
* myOwningView.invalidate();
* }
* }</pre>
* This is marginally faster than doing a more explicit up-front check if the value changed by
* comparing the desired value against {@link #getTranslationX()} as it minimizes JNI transitions.
* The actual mechanism of requesting a new frame to be rendered will depend on how this
* RenderNode is being drawn. If it's drawn to a containing View, as in the above snippet,
* then simply invalidating that View works. If instead the RenderNode is being drawn to a Canvas
* directly such as with {@link Surface#lockHardwareCanvas()} then a new frame needs to be drawn
* by calling {@link Surface#lockHardwareCanvas()}, re-drawing the root RenderNode or whatever
* top-level content is desired, and finally calling {@link Surface#unlockCanvasAndPost(Canvas)}.
* </p>
*/
public final class RenderNode {
// Use a Holder to allow static initialization in the boot image.
private static class NoImagePreloadHolder {
public static final NativeAllocationRegistry sRegistry =
NativeAllocationRegistry.createMalloced(
RenderNode.class.getClassLoader(), nGetNativeFinalizer());
}
/**
* Not for general use; use only if you are ThreadedRenderer or RecordingCanvas.
*
* @hide
*/
public final long mNativeRenderNode;
private final AnimationHost mAnimationHost;
private RecordingCanvas mCurrentRecordingCanvas;
// Will be null if not currently registered
@Nullable
private CompositePositionUpdateListener mCompositePositionUpdateListener;
/**
* Creates a new RenderNode that can be used to record batches of
* drawing operations, and store / apply render properties when drawn.
*
* @param name The name of the RenderNode, used for debugging purpose. May be null.
*/
public RenderNode(@Nullable String name) {
this(name, null);
}
private RenderNode(String name, AnimationHost animationHost) {
mNativeRenderNode = nCreate(name);
NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativeRenderNode);
mAnimationHost = animationHost;
}
/**
* @see RenderNode#adopt(long)
*/
private RenderNode(long nativePtr) {
mNativeRenderNode = nativePtr;
NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativeRenderNode);
mAnimationHost = null;
}
/** @hide */
public static RenderNode create(String name, @Nullable AnimationHost animationHost) {
return new RenderNode(name, animationHost);
}
/**
* Adopts an existing native render node.
*
* Note: This will *NOT* incRef() on the native object, however it will
* decRef() when it is destroyed. The caller should have already incRef'd it
*
* @hide
*/
public static RenderNode adopt(long nativePtr) {
return new RenderNode(nativePtr);
}
/**
* Listens for RenderNode position updates for synchronous window movement.
*
* This is not suitable for generic position listening, it is only designed & intended
* for use by things which require external position events like SurfaceView, PopupWindow, etc..
*
* @hide
*/
public interface PositionUpdateListener {
/**
* Called by native by a Rendering Worker thread to update window position
*
* @hide
*/
void positionChanged(long frameNumber, int left, int top, int right, int bottom);
/**
* Called by native on RenderThread to notify that the view is no longer in the
* draw tree. UI thread is blocked at this point.
*
* @hide
*/
void positionLost(long frameNumber);
}
private static final class CompositePositionUpdateListener implements PositionUpdateListener {
private final PositionUpdateListener[] mListeners;
private static final PositionUpdateListener[] sEmpty = new PositionUpdateListener[0];
CompositePositionUpdateListener(PositionUpdateListener... listeners) {
mListeners = listeners != null ? listeners : sEmpty;
}
public CompositePositionUpdateListener with(PositionUpdateListener listener) {
return new CompositePositionUpdateListener(
ArrayUtils.appendElement(PositionUpdateListener.class, mListeners, listener));
}
public CompositePositionUpdateListener without(PositionUpdateListener listener) {
return new CompositePositionUpdateListener(
ArrayUtils.removeElement(PositionUpdateListener.class, mListeners, listener));
}
@Override
public void positionChanged(long frameNumber, int left, int top, int right, int bottom) {
for (PositionUpdateListener pul : mListeners) {
pul.positionChanged(frameNumber, left, top, right, bottom);
}
}
@Override
public void positionLost(long frameNumber) {
for (PositionUpdateListener pul : mListeners) {
pul.positionLost(frameNumber);
}
}
}
/**
* Enable callbacks for position changes. Call only from the UI thread or with
* external synchronization.
*
* @hide
*/
public void addPositionUpdateListener(@NonNull PositionUpdateListener listener) {
CompositePositionUpdateListener comp = mCompositePositionUpdateListener;
if (comp == null) {
comp = new CompositePositionUpdateListener(listener);
} else {
comp = comp.with(listener);
}
mCompositePositionUpdateListener = comp;
nRequestPositionUpdates(mNativeRenderNode, comp);
}
/**
* Disable a callback for position changes. Call only from the UI thread or with
* external synchronization.
*
* @param listener Callback to remove
* @hide
*/
public void removePositionUpdateListener(@NonNull PositionUpdateListener listener) {
CompositePositionUpdateListener comp = mCompositePositionUpdateListener;
if (comp != null) {
comp = comp.without(listener);
mCompositePositionUpdateListener = comp;
nRequestPositionUpdates(mNativeRenderNode, comp);
}
}
/**
* Starts recording a display list for the render node. All
* operations performed on the returned canvas are recorded and
* stored in this display list.
*
* {@link #endRecording()} must be called when the recording is finished in order to apply
* the updated display list. Failing to call {@link #endRecording()} will result in an
* {@link IllegalStateException} if {@link #beginRecording(int, int)} is called again.
*
* @param width The width of the recording viewport. This will not alter the width of the
* RenderNode itself, that must be set with {@link #setPosition(Rect)}.
* @param height The height of the recording viewport. This will not alter the height of the
* RenderNode itself, that must be set with {@link #setPosition(Rect)}.
* @return A canvas to record drawing operations.
* @throws IllegalStateException If a recording is already in progress. That is, the previous
* call to {@link #beginRecording(int, int)} did not call {@link #endRecording()}.
* @see #endRecording()
* @see #hasDisplayList()
*/
public @NonNull RecordingCanvas beginRecording(int width, int height) {
if (mCurrentRecordingCanvas != null) {
throw new IllegalStateException(
"Recording currently in progress - missing #endRecording() call?");
}
mCurrentRecordingCanvas = RecordingCanvas.obtain(this, width, height);
return mCurrentRecordingCanvas;
}
/**
* Same as {@link #beginRecording(int, int)} with the width & height set
* to the RenderNode's own width & height. The RenderNode's width & height may be set
* with {@link #setPosition(int, int, int, int)}.
*
* @return A canvas to record drawing operations.
* @throws IllegalStateException If a recording is already in progress. That is, the previous
* call to {@link #beginRecording(int, int)} did not call {@link #endRecording()}.
* @see #endRecording()
* @see #hasDisplayList()
*/
public @NonNull RecordingCanvas beginRecording() {
return beginRecording(nGetWidth(mNativeRenderNode), nGetHeight(mNativeRenderNode));
}
/**
* `
* Ends the recording for this display list. Calling this method marks
* the display list valid and {@link #hasDisplayList()} will return true.
*
* @see #beginRecording(int, int)
* @see #hasDisplayList()
*/
public void endRecording() {
if (mCurrentRecordingCanvas == null) {
throw new IllegalStateException(
"No recording in progress, forgot to call #beginRecording()?");
}
RecordingCanvas canvas = mCurrentRecordingCanvas;
mCurrentRecordingCanvas = null;
long displayList = canvas.finishRecording();
nSetDisplayList(mNativeRenderNode, displayList);
canvas.recycle();
}
/**
* @hide
* @deprecated use {@link #beginRecording(int, int)} instead
*/
@Deprecated
public RecordingCanvas start(int width, int height) {
return beginRecording(width, height);
}
/**
* @hide
* @deprecated use {@link #endRecording()} instead
*/
@Deprecated
public void end(RecordingCanvas canvas) {
if (canvas != mCurrentRecordingCanvas) {
throw new IllegalArgumentException("Wrong canvas");
}
endRecording();
}
/**
* Reset native resources. This is called when cleaning up the state of display lists
* during destruction of hardware resources, to ensure that we do not hold onto
* obsolete resources after related resources are gone.
*/
public void discardDisplayList() {
nSetDisplayList(mNativeRenderNode, 0);
}
/**
* Returns whether the RenderNode has a display list. If this returns false, the RenderNode
* should be re-recorded with {@link #beginRecording()} and {@link #endRecording()}.
*
* A RenderNode without a display list may still be drawn, however it will have no impact
* on the rendering content until its display list is updated.
*
* When a RenderNode is no longer drawn by anything the system may automatically
* invoke {@link #discardDisplayList()}. It is therefore important to ensure that
* {@link #hasDisplayList()} is true on a RenderNode prior to drawing it.
*
* See {@link #discardDisplayList()}
*
* @return boolean true if this RenderNode has a display list, false otherwise.
*/
public boolean hasDisplayList() {
return nIsValid(mNativeRenderNode);
}
///////////////////////////////////////////////////////////////////////////
// Matrix manipulation
///////////////////////////////////////////////////////////////////////////
/**
* Whether or not the RenderNode has an identity transform. This is a faster
* way to do the otherwise equivalent {@link #getMatrix(Matrix)} {@link Matrix#isIdentity()}
* as it doesn't require copying the Matrix first, thus minimizing overhead.
*
* @return true if the RenderNode has an identity transform, false otherwise
*/
public boolean hasIdentityMatrix() {
return nHasIdentityMatrix(mNativeRenderNode);
}
/**
* Gets the current transform matrix
*
* @param outMatrix The matrix to store the transform of the RenderNode
*/
public void getMatrix(@NonNull Matrix outMatrix) {
nGetTransformMatrix(mNativeRenderNode, outMatrix.native_instance);
}
/**
* Gets the current transform inverted. This is a faster way to do the otherwise
* equivalent {@link #getMatrix(Matrix)} followed by {@link Matrix#invert(Matrix)}
*
* @param outMatrix The matrix to store the inverse transform of the RenderNode
*/
public void getInverseMatrix(@NonNull Matrix outMatrix) {
nGetInverseTransformMatrix(mNativeRenderNode, outMatrix.native_instance);
}
///////////////////////////////////////////////////////////////////////////
// RenderProperty Setters
///////////////////////////////////////////////////////////////////////////
/**
* @hide
* @deprecated use {@link #setUseCompositingLayer(boolean, Paint)} instead
*/
@Deprecated
public boolean setLayerType(int layerType) {
return nSetLayerType(mNativeRenderNode, layerType);
}
/**
* @hide
* @deprecated use {@link #setUseCompositingLayer(boolean, Paint)} instead
*/
@Deprecated
public boolean setLayerPaint(@Nullable Paint paint) {
return nSetLayerPaint(mNativeRenderNode, paint != null ? paint.getNativeInstance() : 0);
}
/**
* Controls whether or not to force this RenderNode to render to an intermediate buffer.
* Internally RenderNode will already promote itself to a composition layer if it's useful
* for performance or required for the current combination of {@link #setAlpha(float)} and
* {@link #setHasOverlappingRendering(boolean)}.
*
* <p>The usage of this is instead to allow for either overriding of the internal behavior
* if it's measured to be necessary for the particular rendering content in question or, more
* usefully, to add a composition effect to the RenderNode via the optional paint parameter.
*
* <p>Note: When a RenderNode is using a compositing layer it will also result in
* clipToBounds=true behavior.
*
* @param forceToLayer if true this forces the RenderNode to use an intermediate buffer.
* Default & generally recommended value is false.
* @param paint The blend mode, alpha, and ColorFilter to apply to the compositing layer.
* Only applies if forceToLayer is true. The paint's alpha is multiplied
* with {@link #getAlpha()} to resolve the final alpha of the RenderNode.
* If null then no additional composition effects are applied on top of the
* composition layer.
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setUseCompositingLayer(boolean forceToLayer, @Nullable Paint paint) {
boolean didChange = nSetLayerType(mNativeRenderNode, forceToLayer ? 2 : 0);
didChange |= nSetLayerPaint(mNativeRenderNode,
paint != null ? paint.getNativeInstance() : 0);
return didChange;
}
/**
* Gets whether or not a compositing layer is forced to be used. The default & recommended
* is false, as it is typically faster to avoid using compositing layers.
* See {@link #setUseCompositingLayer(boolean, Paint)}.
*
* @return true if a compositing layer is forced, false otherwise
*/
public boolean getUseCompositingLayer() {
return nGetLayerType(mNativeRenderNode) != 0;
}
/**
* Sets an additional clip on the RenderNode. If null, the extra clip is removed from the
* RenderNode. If non-null, the RenderNode will be clipped to this rect. In addition if
* {@link #setClipToBounds(boolean)} is true, then the RenderNode will be clipped to the
* intersection of this rectangle and the bounds of the render node, which is set with
* {@link #setPosition(Rect)}.
*
* <p>This is equivalent to do a {@link Canvas#clipRect(Rect)} at the start of this
* RenderNode's display list. However, as this is a property of the RenderNode instead
* of part of the display list it can be more easily animated for transient additional
* clipping. An example usage of this would be the {@link android.transition.ChangeBounds}
* transition animation with the resizeClip=true option.
*
* @param rect the bounds to clip to. If null, the additional clip is removed.
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setClipRect(@Nullable Rect rect) {
if (rect == null) {
return nSetClipBoundsEmpty(mNativeRenderNode);
} else {
return nSetClipBounds(mNativeRenderNode, rect.left, rect.top, rect.right, rect.bottom);
}
}
/**
* Set whether the Render node should clip itself to its bounds. This defaults to true,
* and is useful to the renderer in enable quick-rejection of chunks of the tree as well as
* better partial invalidation support. Clipping can be further restricted or controlled
* through the combination of this property as well as {@link #setClipRect(Rect)}, which
* allows for a different clipping rectangle to be used in addition to or instead of the
* {@link #setPosition(int, int, int, int)} or the RenderNode.
*
* @param clipToBounds true if the display list should clip to its bounds, false otherwise.
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setClipToBounds(boolean clipToBounds) {
return nSetClipToBounds(mNativeRenderNode, clipToBounds);
}
/**
* Returns whether or not the RenderNode is clipping to its bounds. See
* {@link #setClipToBounds(boolean)} and {@link #setPosition(int, int, int, int)}
*
* @return true if the render node clips to its bounds, false otherwise.
*/
public boolean getClipToBounds() {
return nGetClipToBounds(mNativeRenderNode);
}
/**
* <p>Sets whether the RenderNode should be drawn immediately after the
* closest ancestor RenderNode containing a projection receiver.
*
* <p>The default is false, and the rendering of this node happens in the typical draw order.
*
* <p>If true, then at rendering time this rendernode will not be drawn in order with the
* {@link Canvas#drawRenderNode(RenderNode)} command that drew this RenderNode, but instead
* it will be re-positioned in the RenderNode tree to be drawn on the closet ancestor with a
* child rendernode that has {@link #setProjectionReceiver(boolean)} as true.
*
* <p>The typical usage of this is to allow a child RenderNode to draw on a parent's background,
* such as the platform's usage with {@link android.graphics.drawable.RippleDrawable}. Consider
* the following structure, built out of which RenderNode called drawRenderNode on a different
* RenderNode:
*
* <pre>
* +-------------+
* |RenderNode: P|
* +-+----------++
* | |
* v v
* +-------+-----+ +-+--------------+
* |RenderNode: C| |RenderNode: P'BG|
* +-------+-----+ +----------------+
* |
* |
* +--------+-------+
* |RenderNode: C'BG|
* +----------------+
* </pre>
*
* If P'BG is a projection receiver, and C'BG is set to project backwards then C'BG will
* behave as if it was drawn directly by P'BG instead of by C. This includes inheriting P'BG's
* clip instead of C's clip.
*
* @param shouldProject true if the display list should be projected onto a
* containing volume. Default is false.
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setProjectBackwards(boolean shouldProject) {
return nSetProjectBackwards(mNativeRenderNode, shouldProject);
}
/**
* Sets whether the RenderNode is a projection receiver. If true then this RenderNode's parent
* should draw any descendant RenderNodes with ProjectBackwards=true directly on top of it.
* Default value is false. See
* {@link #setProjectBackwards(boolean)} for a description of what this entails.
*
* @param shouldRecieve True if this RenderNode is a projection receiver, false otherwise.
* Default is false.
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setProjectionReceiver(boolean shouldRecieve) {
return nSetProjectionReceiver(mNativeRenderNode, shouldRecieve);
}
/**
* Sets the outline, defining the shape that casts a shadow, and the path to
* be clipped if setClipToOutline is set.
*
* This will make a copy of the provided {@link Outline}, so any future modifications
* to the outline will need to call {@link #setOutline(Outline)} with the modified
* outline for those changes to be applied.
*
* @param outline The outline to use for this RenderNode.
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setOutline(@Nullable Outline outline) {
if (outline == null) {
return nSetOutlineNone(mNativeRenderNode);
}
switch (outline.mMode) {
case Outline.MODE_EMPTY:
return nSetOutlineEmpty(mNativeRenderNode);
case Outline.MODE_ROUND_RECT:
return nSetOutlineRoundRect(mNativeRenderNode,
outline.mRect.left, outline.mRect.top,
outline.mRect.right, outline.mRect.bottom,
outline.mRadius, outline.mAlpha);
case Outline.MODE_PATH:
return nSetOutlinePath(mNativeRenderNode, outline.mPath.mNativePath,
outline.mAlpha);
}
throw new IllegalArgumentException("Unrecognized outline?");
}
/**
* Checks if the RenderNode has a shadow. That is, if the combination of {@link #getElevation()}
* and {@link #getTranslationZ()} is greater than zero, there is an {@link Outline} set with
* a valid shadow caster path, and the provided outline has a non-zero
* {@link Outline#getAlpha()}.
*
* @return True if this RenderNode has a shadow, false otherwise
*/
public boolean hasShadow() {
return nHasShadow(mNativeRenderNode);
}
/**
* Sets the color of the spot shadow that is drawn when the RenderNode has a positive Z or
* elevation value and is drawn inside of a {@link Canvas#enableZ()} section.
* <p>
* By default the shadow color is black. Generally, this color will be opaque so the intensity
* of the shadow is consistent between different RenderNodes with different colors.
* <p>
* The opacity of the final spot shadow is a function of the shadow caster height, the
* alpha channel of the outlineSpotShadowColor (typically opaque), and the
* {@link android.R.attr#spotShadowAlpha} theme attribute
*
* @param color The color this RenderNode will cast for its elevation spot shadow.
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setSpotShadowColor(@ColorInt int color) {
return nSetSpotShadowColor(mNativeRenderNode, color);
}
/**
* @return The shadow color set by {@link #setSpotShadowColor(int)}, or black if nothing
* was set
*/
public @ColorInt int getSpotShadowColor() {
return nGetSpotShadowColor(mNativeRenderNode);
}
/**
* Sets the color of the ambient shadow that is drawn when the RenderNode has a positive Z or
* elevation value and is drawn inside of a {@link Canvas#enableZ()} section.
* <p>
* By default the shadow color is black. Generally, this color will be opaque so the intensity
* of the shadow is consistent between different RenderNodes with different colors.
* <p>
* The opacity of the final ambient shadow is a function of the shadow caster height, the
* alpha channel of the outlineAmbientShadowColor (typically opaque), and the
* {@link android.R.attr#ambientShadowAlpha} theme attribute.
*
* @param color The color this RenderNode will cast for its elevation shadow.
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setAmbientShadowColor(@ColorInt int color) {
return nSetAmbientShadowColor(mNativeRenderNode, color);
}
/**
* @return The shadow color set by {@link #setAmbientShadowColor(int)}, or black if
* nothing was set
*/
public @ColorInt int getAmbientShadowColor() {
return nGetAmbientShadowColor(mNativeRenderNode);
}
/**
* Enables or disables clipping to the outline.
*
* @param clipToOutline true if clipping to the outline.
* @return True if the clipToOutline value changed, false if previous value matched the new
* value.
*/
public boolean setClipToOutline(boolean clipToOutline) {
return nSetClipToOutline(mNativeRenderNode, clipToOutline);
}
/**
* See {@link #setClipToOutline(boolean)}
*
* @return True if this RenderNode clips to its outline, false otherwise
*/
public boolean getClipToOutline() {
return nGetClipToOutline(mNativeRenderNode);
}
/**
* Controls the RenderNode's circular reveal clip.
*
* @hide
*/
public boolean setRevealClip(boolean shouldClip,
float x, float y, float radius) {
return nSetRevealClip(mNativeRenderNode, shouldClip, x, y, radius);
}
/**
* Set the static matrix on the display list. The specified matrix is combined with other
* transforms (such as {@link #setScaleX(float)}, {@link #setRotationZ(float)}, etc.)
*
* @param matrix A transform matrix to apply to this display list
* @hide TODO Do we want this?
*/
public boolean setStaticMatrix(Matrix matrix) {
return nSetStaticMatrix(mNativeRenderNode, matrix.native_instance);
}
/**
* Set the Animation matrix on the display list. This matrix exists if an Animation is
* currently playing on a View, and is set on the display list during at draw() time. When
* the Animation finishes, the matrix should be cleared by sending <code>null</code>
* for the matrix parameter.
*
* @param matrix The matrix, null indicates that the matrix should be cleared.
* @see #getAnimationMatrix()
*
* @hide TODO Do we want this?
*/
public boolean setAnimationMatrix(@Nullable Matrix matrix) {
return nSetAnimationMatrix(mNativeRenderNode,
(matrix != null) ? matrix.native_instance : 0);
}
/**
* Returns the previously set Animation matrix. This matrix exists if an Animation is
* currently playing on a View, and is set on the display list during at draw() time.
* Returns <code>null</code> when there is no transformation provided by
* {@link #setAnimationMatrix(Matrix)}.
*
* @return the current Animation matrix.
* @see #setAnimationMatrix(Matrix)
*
* @hide
*/
@Nullable
public Matrix getAnimationMatrix() {
Matrix output = new Matrix();
if (nGetAnimationMatrix(mNativeRenderNode, output.native_instance)) {
return output;
} else {
return null;
}
}
/**
* Sets the translucency level for the display list.
*
* @param alpha The translucency of the display list, must be a value between 0.0f and 1.0f
* @see View#setAlpha(float)
* @see #getAlpha()
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setAlpha(float alpha) {
return nSetAlpha(mNativeRenderNode, alpha);
}
/**
* Returns the translucency level of this display list.
*
* @return A value between 0.0f and 1.0f
* @see #setAlpha(float)
*/
public float getAlpha() {
return nGetAlpha(mNativeRenderNode);
}
/**
* Sets whether the display list renders content which overlaps. Non-overlapping rendering
* can use a fast path for alpha that avoids rendering to an offscreen buffer. By default
* display lists consider they do not have overlapping content.
*
* @param hasOverlappingRendering False if the content is guaranteed to be non-overlapping,
* true otherwise.
* @see android.view.View#hasOverlappingRendering()
* @see #hasOverlappingRendering()
*/
public boolean setHasOverlappingRendering(boolean hasOverlappingRendering) {
return nSetHasOverlappingRendering(mNativeRenderNode, hasOverlappingRendering);
}
/** @hide */
@IntDef({USAGE_BACKGROUND})
@Retention(RetentionPolicy.SOURCE)
public @interface UsageHint {
}
/**
* The default usage hint
*
* @hide
*/
public static final int USAGE_UNKNOWN = 0;
/**
* Usage is background content
*
* @hide
*/
public static final int USAGE_BACKGROUND = 1;
/**
* Provides a hint on what this RenderNode's display list content contains. This hint is used
* for automatic content transforms to improve accessibility or similar.
*
* @hide
*/
public void setUsageHint(@UsageHint int usageHint) {
nSetUsageHint(mNativeRenderNode, usageHint);
}
/**
* Indicates whether the content of this display list overlaps.
*
* @return True if this display list renders content which overlaps, false otherwise.
* @see #setHasOverlappingRendering(boolean)
*/
public boolean hasOverlappingRendering() {
return nHasOverlappingRendering(mNativeRenderNode);
}
/**
* Sets the base elevation of this RenderNode in pixels
*
* @param lift the elevation in pixels
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setElevation(float lift) {
return nSetElevation(mNativeRenderNode, lift);
}
/**
* See {@link #setElevation(float)}
*
* @return The RenderNode's current elevation
*/
public float getElevation() {
return nGetElevation(mNativeRenderNode);
}
/**
* Sets the translation value for the display list on the X axis.
*
* @param translationX The X axis translation value of the display list, in pixels
* @see View#setTranslationX(float)
* @see #getTranslationX()
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setTranslationX(float translationX) {
return nSetTranslationX(mNativeRenderNode, translationX);
}
/**
* Returns the translation value for this display list on the X axis, in pixels.
*
* @see #setTranslationX(float)
*/
public float getTranslationX() {
return nGetTranslationX(mNativeRenderNode);
}
/**
* Sets the translation value for the display list on the Y axis.
*
* @param translationY The Y axis translation value of the display list, in pixels
* @see View#setTranslationY(float)
* @see #getTranslationY()
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setTranslationY(float translationY) {
return nSetTranslationY(mNativeRenderNode, translationY);
}
/**
* Returns the translation value for this display list on the Y axis, in pixels.
*
* @see #setTranslationY(float)
*/
public float getTranslationY() {
return nGetTranslationY(mNativeRenderNode);
}
/**
* Sets the translation value for the display list on the Z axis.
*
* @see View#setTranslationZ(float)
* @see #getTranslationZ()
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setTranslationZ(float translationZ) {
return nSetTranslationZ(mNativeRenderNode, translationZ);
}
/**
* Returns the translation value for this display list on the Z axis.
*
* @see #setTranslationZ(float)
*/
public float getTranslationZ() {
return nGetTranslationZ(mNativeRenderNode);
}
/**
* Sets the rotation value for the display list around the Z axis.
*
* @param rotation The rotation value of the display list, in degrees
* @see View#setRotation(float)
* @see #getRotationZ()
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setRotationZ(float rotation) {
return nSetRotation(mNativeRenderNode, rotation);
}
/**
* Returns the rotation value for this display list around the Z axis, in degrees.
*
* @see #setRotationZ(float)
*/
public float getRotationZ() {
return nGetRotation(mNativeRenderNode);
}
/**
* Sets the rotation value for the display list around the X axis.
*
* @param rotationX The rotation value of the display list, in degrees
* @see View#setRotationX(float)
* @see #getRotationX()
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setRotationX(float rotationX) {
return nSetRotationX(mNativeRenderNode, rotationX);
}
/**
* Returns the rotation value for this display list around the X axis, in degrees.
*
* @see #setRotationX(float)
*/
public float getRotationX() {
return nGetRotationX(mNativeRenderNode);
}
/**
* Sets the rotation value for the display list around the Y axis.
*
* @param rotationY The rotation value of the display list, in degrees
* @see View#setRotationY(float)
* @see #getRotationY()
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setRotationY(float rotationY) {
return nSetRotationY(mNativeRenderNode, rotationY);
}
/**
* Returns the rotation value for this display list around the Y axis, in degrees.
*
* @see #setRotationY(float)
*/
public float getRotationY() {
return nGetRotationY(mNativeRenderNode);
}
/**
* Sets the scale value for the display list on the X axis.
*
* @param scaleX The scale value of the display list
* @see View#setScaleX(float)
* @see #getScaleX()
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setScaleX(float scaleX) {
return nSetScaleX(mNativeRenderNode, scaleX);
}
/**
* Returns the scale value for this display list on the X axis.
*
* @see #setScaleX(float)
*/
public float getScaleX() {
return nGetScaleX(mNativeRenderNode);
}
/**
* Sets the scale value for the display list on the Y axis.
*
* @param scaleY The scale value of the display list
* @see View#setScaleY(float)
* @see #getScaleY()
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setScaleY(float scaleY) {
return nSetScaleY(mNativeRenderNode, scaleY);
}
/**
* Returns the scale value for this display list on the Y axis.
*
* @see #setScaleY(float)
*/
public float getScaleY() {
return nGetScaleY(mNativeRenderNode);
}
/**
* Sets the pivot value for the display list on the X axis
*
* @param pivotX The pivot value of the display list on the X axis, in pixels
* @see View#setPivotX(float)
* @see #getPivotX()
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setPivotX(float pivotX) {
return nSetPivotX(mNativeRenderNode, pivotX);
}
/**
* Returns the pivot value for this display list on the X axis, in pixels.
*
* @see #setPivotX(float)
*/
public float getPivotX() {
return nGetPivotX(mNativeRenderNode);
}
/**
* Sets the pivot value for the display list on the Y axis
*
* @param pivotY The pivot value of the display list on the Y axis, in pixels
* @see View#setPivotY(float)
* @see #getPivotY()
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setPivotY(float pivotY) {
return nSetPivotY(mNativeRenderNode, pivotY);
}
/**
* Returns the pivot value for this display list on the Y axis, in pixels.
*
* @see #setPivotY(float)
*/
public float getPivotY() {
return nGetPivotY(mNativeRenderNode);
}
/**
* @return Whether or not a pivot was explicitly set with {@link #setPivotX(float)} or
* {@link #setPivotY(float)}. If no pivot has been set then the pivot will be the center
* of the RenderNode.
*/
public boolean isPivotExplicitlySet() {
return nIsPivotExplicitlySet(mNativeRenderNode);
}
/**
* Clears any pivot previously set by a call to {@link #setPivotX(float)} or
* {@link #setPivotY(float)}. After calling this {@link #isPivotExplicitlySet()} will be false
* and the pivot used for rotation will return to default of being centered on the view.
*
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean resetPivot() {
return nResetPivot(mNativeRenderNode);
}
/**
* <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
* RenderNodes are drawn) from the camera to this RenderNode. The camera's distance
* affects 3D transformations, for instance rotations around the X and Y
* axis. If the rotationX or rotationY properties are changed and this view is
* large (more than half the size of the screen), it is recommended to always
* use a camera distance that's greater than the height (X axis rotation) or
* the width (Y axis rotation) of this view.</p>
*
* <p>The distance of the camera from the drawing plane can have an affect on the
* perspective distortion of the RenderNode when it is rotated around the x or y axis.
* For example, a large distance will result in a large viewing angle, and there
* will not be much perspective distortion of the view as it rotates. A short
* distance may cause much more perspective distortion upon rotation, and can
* also result in some drawing artifacts if the rotated view ends up partially
* behind the camera (which is why the recommendation is to use a distance at
* least as far as the size of the view, if the view is to be rotated.)</p>
*
* <p>The distance is expressed in pixels and must always be positive</p>
*
* @param distance The distance in pixels, must always be positive
* @see #setRotationX(float)
* @see #setRotationY(float)
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setCameraDistance(
@FloatRange(from = 0.0f, to = Float.MAX_VALUE) float distance) {
if (!Float.isFinite(distance) || distance < 0.0f) {
throw new IllegalArgumentException("distance must be finite & positive, given="
+ distance);
}
// Native actually wants this to be negative not positive, so we flip it.
return nSetCameraDistance(mNativeRenderNode, -distance);
}
/**
* Returns the distance in Z of the camera for this RenderNode
*
* @return the distance along the Z axis in pixels.
* @see #setCameraDistance(float)
*/
public @FloatRange(from = 0.0f, to = Float.MAX_VALUE) float getCameraDistance() {
return -nGetCameraDistance(mNativeRenderNode);
}
/**
* Sets the left position for the RenderNode.
*
* @param left The left position, in pixels, of the RenderNode
* @return true if the value changed, false otherwise
* @hide
*/
public boolean setLeft(int left) {
return nSetLeft(mNativeRenderNode, left);
}
/**
* Sets the top position for the RenderNode.
*
* @param top The top position, in pixels, of the RenderNode
* @return true if the value changed, false otherwise.
* @hide
*/
public boolean setTop(int top) {
return nSetTop(mNativeRenderNode, top);
}
/**
* Sets the right position for the RenderNode.
*
* @param right The right position, in pixels, of the RenderNode
* @return true if the value changed, false otherwise.
* @hide
*/
public boolean setRight(int right) {
return nSetRight(mNativeRenderNode, right);
}
/**
* Sets the bottom position for the RenderNode.
*
* @param bottom The bottom position, in pixels, of the RenderNode
* @return true if the value changed, false otherwise.
* @hide
*/
public boolean setBottom(int bottom) {
return nSetBottom(mNativeRenderNode, bottom);
}
/**
* Gets the left position for the RenderNode.
*
* @return the left position in pixels
*/
public int getLeft() {
return nGetLeft(mNativeRenderNode);
}
/**
* Gets the top position for the RenderNode.
*
* @return the top position in pixels
*/
public int getTop() {
return nGetTop(mNativeRenderNode);
}
/**
* Gets the right position for the RenderNode.
*
* @return the right position in pixels
*/
public int getRight() {
return nGetRight(mNativeRenderNode);
}
/**
* Gets the bottom position for the RenderNode.
*
* @return the bottom position in pixels
*/
public int getBottom() {
return nGetBottom(mNativeRenderNode);
}
/**
* Gets the width of the RenderNode, which is the right - left.
*
* @return the width of the RenderNode
*/
public int getWidth() {
return nGetWidth(mNativeRenderNode);
}
/**
* Gets the height of the RenderNode, which is the bottom - top.
*
* @return the height of the RenderNode
*/
public int getHeight() {
return nGetHeight(mNativeRenderNode);
}
/**
* Sets the left, top, right, and bottom of the RenderNode.
*
* @param left The left position of the RenderNode, in pixels
* @param top The top position of the RenderNode, in pixels
* @param right The right position of the RenderNode, in pixels
* @param bottom The bottom position of the RenderNode, in pixels
* @return true if any values changed, false otherwise.
* @hide
*/
public boolean setLeftTopRightBottom(int left, int top, int right, int bottom) {
return nSetLeftTopRightBottom(mNativeRenderNode, left, top, right, bottom);
}
/**
* Sets the position of the RenderNode.
*
* @param left The left position of the RenderNode, in pixels
* @param top The top position of the RenderNode, in pixels
* @param right The right position of the RenderNode, in pixels
* @param bottom The bottom position of the RenderNode, in pixels
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setPosition(int left, int top, int right, int bottom) {
return nSetLeftTopRightBottom(mNativeRenderNode, left, top, right, bottom);
}
/**
* Sets the position of the RenderNode.
*
* @param position The position rectangle in pixels
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setPosition(@NonNull Rect position) {
return nSetLeftTopRightBottom(mNativeRenderNode,
position.left, position.top, position.right, position.bottom);
}
/**
* Offsets the left and right positions for the RenderNode
*
* @param offset The amount that the left and right positions are offset in pixels
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean offsetLeftAndRight(int offset) {
return nOffsetLeftAndRight(mNativeRenderNode, offset);
}
/**
* Offsets the top and bottom values for the RenderNode
*
* @param offset The amount that the left and right positions are offset in pixels
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean offsetTopAndBottom(int offset) {
return nOffsetTopAndBottom(mNativeRenderNode, offset);
}
/**
* Outputs the RenderNode to the log. This method exists for use by
* tools to output display lists for selected nodes to the log.
*
* @hide TODO: Expose? Should the shape of this be different than forced dump to logcat?
*/
public void output() {
nOutput(mNativeRenderNode);
}
/**
* Gets the approximate memory usage of the RenderNode for debug purposes. Does not include
* the memory usage of any child RenderNodes nor any bitmaps, only the memory usage of
* this RenderNode and any data it owns.
*
* @return Approximate memory usage in bytes.
*/
public @BytesLong long computeApproximateMemoryUsage() {
return nGetUsageSize(mNativeRenderNode);
}
/**
* Gets the approximate amount of memory allocated for the RenderNode for debug purposes.
* Does not include the memory allocated by any child RenderNodes nor any bitmaps, only the
* memory allocated for this RenderNode and any data it owns.
*
* The difference between this and {@link #computeApproximateMemoryUsage()} is this includes
* memory allocated but not used. In particular structures such as DisplayLists are similar
* to things like ArrayLists - they need to resize as commands are added to them. As such,
* memory used can be less than memory allocated.
*
* @hide */
public @BytesLong long computeApproximateMemoryAllocated() {
return nGetAllocatedSize(mNativeRenderNode);
}
/**
* Sets whether or not to allow force dark to apply to this RenderNode.
*
* Setting this to false will disable the auto-dark feature on everything this RenderNode
* draws, including any descendants.
*
* Setting this to true will allow this RenderNode to be automatically made dark, however
* a value of 'true' will not override any 'false' value in its parent chain nor will
* it prevent any 'false' in any of its children.
*
* @param allow Whether or not to allow force dark.
* @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setForceDarkAllowed(boolean allow) {
return nSetAllowForceDark(mNativeRenderNode, allow);
}
/**
* See {@link #setForceDarkAllowed(boolean)}
*
* @return true if force dark is allowed (default), false if it is disabled
*/
public boolean isForceDarkAllowed() {
return nGetAllowForceDark(mNativeRenderNode);
}
/**
* Returns the unique ID that identifies this RenderNode. This ID is unique for the
* lifetime of the process. IDs are reset on process death, and are unique only within
* the process.
*
* This ID is intended to be used with debugging tools to associate a particular
* RenderNode across different debug dumping & inspection tools. For example
* a View layout inspector should include the unique ID for any RenderNodes that it owns
* to associate the drawing content with the layout content.
*
* @return the unique ID for this RenderNode
*/
public long getUniqueId() {
return nGetUniqueId(mNativeRenderNode);
}
///////////////////////////////////////////////////////////////////////////
// Animations
///////////////////////////////////////////////////////////////////////////
/**
* TODO: Figure out if this can be eliminated/refactored away
*
* For now this interface exists to de-couple RenderNode from anything View-specific in a
* bit of a kludge.
*
* @hide
*/
public interface AnimationHost {
/** @hide */
void registerAnimatingRenderNode(RenderNode animator);
/** @hide */
void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator);
/** @hide */
boolean isAttached();
}
/** @hide */
public void addAnimator(RenderNodeAnimator animator) {
if (!isAttached()) {
throw new IllegalStateException("Cannot start this animator on a detached view!");
}
nAddAnimator(mNativeRenderNode, animator.getNativeAnimator());
mAnimationHost.registerAnimatingRenderNode(this);
}
/** @hide */
public boolean isAttached() {
return mAnimationHost != null && mAnimationHost.isAttached();
}
/** @hide */
public void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animatorSet) {
if (!isAttached()) {
throw new IllegalStateException("Cannot start this animator on a detached view!");
}
mAnimationHost.registerVectorDrawableAnimator(animatorSet);
}
/** @hide */
public void endAllAnimators() {
nEndAllAnimators(mNativeRenderNode);
}
///////////////////////////////////////////////////////////////////////////
// Regular JNI methods
///////////////////////////////////////////////////////////////////////////
private static native long nCreate(String name);
private static native long nGetNativeFinalizer();
private static native void nOutput(long renderNode);
private static native int nGetUsageSize(long renderNode);
private static native int nGetAllocatedSize(long renderNode);
private static native void nRequestPositionUpdates(long renderNode,
PositionUpdateListener callback);
// Animations
private static native void nAddAnimator(long renderNode, long animatorPtr);
private static native void nEndAllAnimators(long renderNode);
///////////////////////////////////////////////////////////////////////////
// @FastNative methods
///////////////////////////////////////////////////////////////////////////
@FastNative
private static native void nSetDisplayList(long renderNode, long newData);
///////////////////////////////////////////////////////////////////////////
// @CriticalNative methods
///////////////////////////////////////////////////////////////////////////
@CriticalNative
private static native boolean nIsValid(long renderNode);
// Matrix
@CriticalNative
private static native void nGetTransformMatrix(long renderNode, long nativeMatrix);
@CriticalNative
private static native void nGetInverseTransformMatrix(long renderNode, long nativeMatrix);
@CriticalNative
private static native boolean nHasIdentityMatrix(long renderNode);
// Properties
@CriticalNative
private static native boolean nOffsetTopAndBottom(long renderNode, int offset);
@CriticalNative
private static native boolean nOffsetLeftAndRight(long renderNode, int offset);
@CriticalNative
private static native boolean nSetLeftTopRightBottom(long renderNode, int left, int top,
int right, int bottom);
@CriticalNative
private static native boolean nSetLeft(long renderNode, int left);
@CriticalNative
private static native boolean nSetTop(long renderNode, int top);
@CriticalNative
private static native boolean nSetRight(long renderNode, int right);
@CriticalNative
private static native boolean nSetBottom(long renderNode, int bottom);
@CriticalNative
private static native int nGetLeft(long renderNode);
@CriticalNative
private static native int nGetTop(long renderNode);
@CriticalNative
private static native int nGetRight(long renderNode);
@CriticalNative
private static native int nGetBottom(long renderNode);
@CriticalNative
private static native boolean nSetCameraDistance(long renderNode, float distance);
@CriticalNative
private static native boolean nSetPivotY(long renderNode, float pivotY);
@CriticalNative
private static native boolean nSetPivotX(long renderNode, float pivotX);
@CriticalNative
private static native boolean nResetPivot(long renderNode);
@CriticalNative
private static native boolean nSetLayerType(long renderNode, int layerType);
@CriticalNative
private static native int nGetLayerType(long renderNode);
@CriticalNative
private static native boolean nSetLayerPaint(long renderNode, long paint);
@CriticalNative
private static native boolean nSetClipToBounds(long renderNode, boolean clipToBounds);
@CriticalNative
private static native boolean nGetClipToBounds(long renderNode);
@CriticalNative
private static native boolean nSetClipBounds(long renderNode, int left, int top,
int right, int bottom);
@CriticalNative
private static native boolean nSetClipBoundsEmpty(long renderNode);
@CriticalNative
private static native boolean nSetProjectBackwards(long renderNode, boolean shouldProject);
@CriticalNative
private static native boolean nSetProjectionReceiver(long renderNode, boolean shouldRecieve);
@CriticalNative
private static native boolean nSetOutlineRoundRect(long renderNode, int left, int top,
int right, int bottom, float radius, float alpha);
@CriticalNative
private static native boolean nSetOutlinePath(long renderNode, long nativePath,
float alpha);
@CriticalNative
private static native boolean nSetOutlineEmpty(long renderNode);
@CriticalNative
private static native boolean nSetOutlineNone(long renderNode);
@CriticalNative
private static native boolean nHasShadow(long renderNode);
@CriticalNative
private static native boolean nSetSpotShadowColor(long renderNode, int color);
@CriticalNative
private static native boolean nSetAmbientShadowColor(long renderNode, int color);
@CriticalNative
private static native int nGetSpotShadowColor(long renderNode);
@CriticalNative
private static native int nGetAmbientShadowColor(long renderNode);
@CriticalNative
private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline);
@CriticalNative
private static native boolean nSetRevealClip(long renderNode,
boolean shouldClip, float x, float y, float radius);
@CriticalNative
private static native boolean nSetAlpha(long renderNode, float alpha);
@CriticalNative
private static native boolean nSetHasOverlappingRendering(long renderNode,
boolean hasOverlappingRendering);
@CriticalNative
private static native void nSetUsageHint(long renderNode, int usageHint);
@CriticalNative
private static native boolean nSetElevation(long renderNode, float lift);
@CriticalNative
private static native boolean nSetTranslationX(long renderNode, float translationX);
@CriticalNative
private static native boolean nSetTranslationY(long renderNode, float translationY);
@CriticalNative
private static native boolean nSetTranslationZ(long renderNode, float translationZ);
@CriticalNative
private static native boolean nSetRotation(long renderNode, float rotation);
@CriticalNative
private static native boolean nSetRotationX(long renderNode, float rotationX);
@CriticalNative
private static native boolean nSetRotationY(long renderNode, float rotationY);
@CriticalNative
private static native boolean nSetScaleX(long renderNode, float scaleX);
@CriticalNative
private static native boolean nSetScaleY(long renderNode, float scaleY);
@CriticalNative
private static native boolean nSetStaticMatrix(long renderNode, long nativeMatrix);
@CriticalNative
private static native boolean nSetAnimationMatrix(long renderNode, long animationMatrix);
@CriticalNative
private static native boolean nHasOverlappingRendering(long renderNode);
@CriticalNative
private static native boolean nGetAnimationMatrix(long renderNode, long animationMatrix);
@CriticalNative
private static native boolean nGetClipToOutline(long renderNode);
@CriticalNative
private static native float nGetAlpha(long renderNode);
@CriticalNative
private static native float nGetCameraDistance(long renderNode);
@CriticalNative
private static native float nGetScaleX(long renderNode);
@CriticalNative
private static native float nGetScaleY(long renderNode);
@CriticalNative
private static native float nGetElevation(long renderNode);
@CriticalNative
private static native float nGetTranslationX(long renderNode);
@CriticalNative
private static native float nGetTranslationY(long renderNode);
@CriticalNative
private static native float nGetTranslationZ(long renderNode);
@CriticalNative
private static native float nGetRotation(long renderNode);
@CriticalNative
private static native float nGetRotationX(long renderNode);
@CriticalNative
private static native float nGetRotationY(long renderNode);
@CriticalNative
private static native boolean nIsPivotExplicitlySet(long renderNode);
@CriticalNative
private static native float nGetPivotX(long renderNode);
@CriticalNative
private static native float nGetPivotY(long renderNode);
@CriticalNative
private static native int nGetWidth(long renderNode);
@CriticalNative
private static native int nGetHeight(long renderNode);
@CriticalNative
private static native boolean nSetAllowForceDark(long renderNode, boolean allowForceDark);
@CriticalNative
private static native boolean nGetAllowForceDark(long renderNode);
@CriticalNative
private static native long nGetUniqueId(long renderNode);
}