Home | History | Annotate | Download | only in view
      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.view;
     18 
     19 import android.annotation.NonNull;
     20 import android.annotation.Nullable;
     21 import android.graphics.Matrix;
     22 import android.graphics.Outline;
     23 import android.graphics.Paint;
     24 import android.graphics.Rect;
     25 import android.graphics.drawable.AnimatedVectorDrawable;
     26 
     27 /**
     28  * <p>A display list records a series of graphics related operations and can replay
     29  * them later. Display lists are usually built by recording operations on a
     30  * {@link DisplayListCanvas}. Replaying the operations from a display list avoids
     31  * executing application code on every frame, and is thus much more efficient.</p>
     32  *
     33  * <p>Display lists are used internally for all views by default, and are not
     34  * typically used directly. One reason to consider using a display is a custom
     35  * {@link View} implementation that needs to issue a large number of drawing commands.
     36  * When the view invalidates, all the drawing commands must be reissued, even if
     37  * large portions of the drawing command stream stay the same frame to frame, which
     38  * can become a performance bottleneck. To solve this issue, a custom View might split
     39  * its content into several display lists. A display list is updated only when its
     40  * content, and only its content, needs to be updated.</p>
     41  *
     42  * <p>A text editor might for instance store each paragraph into its own display list.
     43  * Thus when the user inserts or removes characters, only the display list of the
     44  * affected paragraph needs to be recorded again.</p>
     45  *
     46  * <h3>Hardware acceleration</h3>
     47  * <p>Display lists can only be replayed using a {@link DisplayListCanvas}. They are not
     48  * supported in software. Always make sure that the {@link android.graphics.Canvas}
     49  * you are using to render a display list is hardware accelerated using
     50  * {@link android.graphics.Canvas#isHardwareAccelerated()}.</p>
     51  *
     52  * <h3>Creating a display list</h3>
     53  * <pre class="prettyprint">
     54  *     HardwareRenderer renderer = myView.getHardwareRenderer();
     55  *     if (renderer != null) {
     56  *         DisplayList displayList = renderer.createDisplayList();
     57  *         DisplayListCanvas canvas = displayList.start(width, height);
     58  *         try {
     59  *             // Draw onto the canvas
     60  *             // For instance: canvas.drawBitmap(...);
     61  *         } finally {
     62  *             displayList.end();
     63  *         }
     64  *     }
     65  * </pre>
     66  *
     67  * <h3>Rendering a display list on a View</h3>
     68  * <pre class="prettyprint">
     69  *     protected void onDraw(Canvas canvas) {
     70  *         if (canvas.isHardwareAccelerated()) {
     71  *             DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
     72  *             displayListCanvas.drawDisplayList(mDisplayList);
     73  *         }
     74  *     }
     75  * </pre>
     76  *
     77  * <h3>Releasing resources</h3>
     78  * <p>This step is not mandatory but recommended if you want to release resources
     79  * held by a display list as soon as possible.</p>
     80  * <pre class="prettyprint">
     81  *     // Mark this display list invalid, it cannot be used for drawing anymore,
     82  *     // and release resources held by this display list
     83  *     displayList.clear();
     84  * </pre>
     85  *
     86  * <h3>Properties</h3>
     87  * <p>In addition, a display list offers several properties, such as
     88  * {@link #setScaleX(float)} or {@link #setLeft(int)}, that can be used to affect all
     89  * the drawing commands recorded within. For instance, these properties can be used
     90  * to move around a large number of images without re-issuing all the individual
     91  * <code>drawBitmap()</code> calls.</p>
     92  *
     93  * <pre class="prettyprint">
     94  *     private void createDisplayList() {
     95  *         mDisplayList = DisplayList.create("MyDisplayList");
     96  *         DisplayListCanvas canvas = mDisplayList.start(width, height);
     97  *         try {
     98  *             for (Bitmap b : mBitmaps) {
     99  *                 canvas.drawBitmap(b, 0.0f, 0.0f, null);
    100  *                 canvas.translate(0.0f, b.getHeight());
    101  *             }
    102  *         } finally {
    103  *             displayList.end();
    104  *         }
    105  *     }
    106  *
    107  *     protected void onDraw(Canvas canvas) {
    108  *         if (canvas.isHardwareAccelerated()) {
    109  *             DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
    110  *             displayListCanvas.drawDisplayList(mDisplayList);
    111  *         }
    112  *     }
    113  *
    114  *     private void moveContentBy(int x) {
    115  *          // This will move all the bitmaps recorded inside the display list
    116  *          // by x pixels to the right and redraw this view. All the commands
    117  *          // recorded in createDisplayList() won't be re-issued, only onDraw()
    118  *          // will be invoked and will execute very quickly
    119  *          mDisplayList.offsetLeftAndRight(x);
    120  *          invalidate();
    121  *     }
    122  * </pre>
    123  *
    124  * <h3>Threading</h3>
    125  * <p>Display lists must be created on and manipulated from the UI thread only.</p>
    126  *
    127  * @hide
    128  */
    129 public class RenderNode {
    130 
    131     private boolean mValid;
    132     // Do not access directly unless you are ThreadedRenderer
    133     final long mNativeRenderNode;
    134     private final View mOwningView;
    135 
    136     private RenderNode(String name, View owningView) {
    137         mNativeRenderNode = nCreate(name);
    138         mOwningView = owningView;
    139         if (mOwningView instanceof SurfaceView) {
    140             nRequestPositionUpdates(mNativeRenderNode, (SurfaceView) mOwningView);
    141         }
    142     }
    143 
    144     /**
    145      * @see RenderNode#adopt(long)
    146      */
    147     private RenderNode(long nativePtr) {
    148         mNativeRenderNode = nativePtr;
    149         mOwningView = null;
    150     }
    151 
    152     /**
    153      * Creates a new RenderNode that can be used to record batches of
    154      * drawing operations, and store / apply render properties when drawn.
    155      *
    156      * @param name The name of the RenderNode, used for debugging purpose. May be null.
    157      *
    158      * @return A new RenderNode.
    159      */
    160     public static RenderNode create(String name, @Nullable View owningView) {
    161         return new RenderNode(name, owningView);
    162     }
    163 
    164     /**
    165      * Adopts an existing native render node.
    166      *
    167      * Note: This will *NOT* incRef() on the native object, however it will
    168      * decRef() when it is destroyed. The caller should have already incRef'd it
    169      */
    170     public static RenderNode adopt(long nativePtr) {
    171         return new RenderNode(nativePtr);
    172     }
    173 
    174 
    175     /**
    176      * Starts recording a display list for the render node. All
    177      * operations performed on the returned canvas are recorded and
    178      * stored in this display list.
    179      *
    180      * Calling this method will mark the render node invalid until
    181      * {@link #end(DisplayListCanvas)} is called.
    182      * Only valid render nodes can be replayed.
    183      *
    184      * @param width The width of the recording viewport
    185      * @param height The height of the recording viewport
    186      *
    187      * @return A canvas to record drawing operations.
    188      *
    189      * @see #end(DisplayListCanvas)
    190      * @see #isValid()
    191      */
    192     public DisplayListCanvas start(int width, int height) {
    193         return DisplayListCanvas.obtain(this, width, height);
    194     }
    195 
    196     /**
    197      * Ends the recording for this display list. A display list cannot be
    198      * replayed if recording is not finished. Calling this method marks
    199      * the display list valid and {@link #isValid()} will return true.
    200      *
    201      * @see #start(int, int)
    202      * @see #isValid()
    203      */
    204     public void end(DisplayListCanvas canvas) {
    205         long displayList = canvas.finishRecording();
    206         nSetDisplayList(mNativeRenderNode, displayList);
    207         canvas.recycle();
    208         mValid = true;
    209     }
    210 
    211     /**
    212      * Reset native resources. This is called when cleaning up the state of display lists
    213      * during destruction of hardware resources, to ensure that we do not hold onto
    214      * obsolete resources after related resources are gone.
    215      */
    216     public void discardDisplayList() {
    217         if (!mValid) return;
    218 
    219         nSetDisplayList(mNativeRenderNode, 0);
    220         mValid = false;
    221     }
    222 
    223     /**
    224      * Returns whether the RenderNode's display list content is currently usable.
    225      * If this returns false, the display list should be re-recorded prior to replaying it.
    226      *
    227      * @return boolean true if the display list is able to be replayed, false otherwise.
    228      */
    229     public boolean isValid() { return mValid; }
    230 
    231     long getNativeDisplayList() {
    232         if (!mValid) {
    233             throw new IllegalStateException("The display list is not valid.");
    234         }
    235         return mNativeRenderNode;
    236     }
    237 
    238     ///////////////////////////////////////////////////////////////////////////
    239     // Matrix manipulation
    240     ///////////////////////////////////////////////////////////////////////////
    241 
    242     public boolean hasIdentityMatrix() {
    243         return nHasIdentityMatrix(mNativeRenderNode);
    244     }
    245 
    246     public void getMatrix(@NonNull Matrix outMatrix) {
    247         nGetTransformMatrix(mNativeRenderNode, outMatrix.native_instance);
    248     }
    249 
    250     public void getInverseMatrix(@NonNull Matrix outMatrix) {
    251         nGetInverseTransformMatrix(mNativeRenderNode, outMatrix.native_instance);
    252     }
    253 
    254     ///////////////////////////////////////////////////////////////////////////
    255     // RenderProperty Setters
    256     ///////////////////////////////////////////////////////////////////////////
    257 
    258     public boolean setLayerType(int layerType) {
    259         return nSetLayerType(mNativeRenderNode, layerType);
    260     }
    261 
    262     public boolean setLayerPaint(@Nullable Paint paint) {
    263         return nSetLayerPaint(mNativeRenderNode, paint != null ? paint.getNativeInstance() : 0);
    264     }
    265 
    266     public boolean setClipBounds(@Nullable Rect rect) {
    267         if (rect == null) {
    268             return nSetClipBoundsEmpty(mNativeRenderNode);
    269         } else {
    270             return nSetClipBounds(mNativeRenderNode, rect.left, rect.top, rect.right, rect.bottom);
    271         }
    272     }
    273 
    274     /**
    275      * Set whether the Render node should clip itself to its bounds. This property is controlled by
    276      * the view's parent.
    277      *
    278      * @param clipToBounds true if the display list should clip to its bounds
    279      */
    280     public boolean setClipToBounds(boolean clipToBounds) {
    281         return nSetClipToBounds(mNativeRenderNode, clipToBounds);
    282     }
    283 
    284     /**
    285      * Sets whether the display list should be drawn immediately after the
    286      * closest ancestor display list containing a projection receiver.
    287      *
    288      * @param shouldProject true if the display list should be projected onto a
    289      *            containing volume.
    290      */
    291     public boolean setProjectBackwards(boolean shouldProject) {
    292         return nSetProjectBackwards(mNativeRenderNode, shouldProject);
    293     }
    294 
    295     /**
    296      * Sets whether the display list is a projection receiver - that its parent
    297      * DisplayList should draw any descendent DisplayLists with
    298      * ProjectBackwards=true directly on top of it. Default value is false.
    299      */
    300     public boolean setProjectionReceiver(boolean shouldRecieve) {
    301         return nSetProjectionReceiver(mNativeRenderNode, shouldRecieve);
    302     }
    303 
    304     /**
    305      * Sets the outline, defining the shape that casts a shadow, and the path to
    306      * be clipped if setClipToOutline is set.
    307      *
    308      * Deep copies the data into native to simplify reference ownership.
    309      */
    310     public boolean setOutline(@Nullable Outline outline) {
    311         if (outline == null) {
    312             return nSetOutlineNone(mNativeRenderNode);
    313         }
    314 
    315         switch(outline.mMode) {
    316             case Outline.MODE_EMPTY:
    317                 return nSetOutlineEmpty(mNativeRenderNode);
    318             case Outline.MODE_ROUND_RECT:
    319                 return nSetOutlineRoundRect(mNativeRenderNode, outline.mRect.left, outline.mRect.top,
    320                         outline.mRect.right, outline.mRect.bottom, outline.mRadius, outline.mAlpha);
    321             case Outline.MODE_CONVEX_PATH:
    322                 return nSetOutlineConvexPath(mNativeRenderNode, outline.mPath.mNativePath,
    323                         outline.mAlpha);
    324         }
    325 
    326         throw new IllegalArgumentException("Unrecognized outline?");
    327     }
    328 
    329     public boolean hasShadow() {
    330         return nHasShadow(mNativeRenderNode);
    331     }
    332 
    333     /**
    334      * Enables or disables clipping to the outline.
    335      *
    336      * @param clipToOutline true if clipping to the outline.
    337      */
    338     public boolean setClipToOutline(boolean clipToOutline) {
    339         return nSetClipToOutline(mNativeRenderNode, clipToOutline);
    340     }
    341 
    342     public boolean getClipToOutline() {
    343         return nGetClipToOutline(mNativeRenderNode);
    344     }
    345 
    346     /**
    347      * Controls the RenderNode's circular reveal clip.
    348      */
    349     public boolean setRevealClip(boolean shouldClip,
    350             float x, float y, float radius) {
    351         return nSetRevealClip(mNativeRenderNode, shouldClip, x, y, radius);
    352     }
    353 
    354     /**
    355      * Set the static matrix on the display list. The specified matrix is combined with other
    356      * transforms (such as {@link #setScaleX(float)}, {@link #setRotation(float)}, etc.)
    357      *
    358      * @param matrix A transform matrix to apply to this display list
    359      */
    360     public boolean setStaticMatrix(Matrix matrix) {
    361         return nSetStaticMatrix(mNativeRenderNode, matrix.native_instance);
    362     }
    363 
    364     /**
    365      * Set the Animation matrix on the display list. This matrix exists if an Animation is
    366      * currently playing on a View, and is set on the display list during at draw() time. When
    367      * the Animation finishes, the matrix should be cleared by sending <code>null</code>
    368      * for the matrix parameter.
    369      *
    370      * @param matrix The matrix, null indicates that the matrix should be cleared.
    371      */
    372     public boolean setAnimationMatrix(Matrix matrix) {
    373         return nSetAnimationMatrix(mNativeRenderNode,
    374                 (matrix != null) ? matrix.native_instance : 0);
    375     }
    376 
    377     /**
    378      * Sets the translucency level for the display list.
    379      *
    380      * @param alpha The translucency of the display list, must be a value between 0.0f and 1.0f
    381      *
    382      * @see View#setAlpha(float)
    383      * @see #getAlpha()
    384      */
    385     public boolean setAlpha(float alpha) {
    386         return nSetAlpha(mNativeRenderNode, alpha);
    387     }
    388 
    389     /**
    390      * Returns the translucency level of this display list.
    391      *
    392      * @return A value between 0.0f and 1.0f
    393      *
    394      * @see #setAlpha(float)
    395      */
    396     public float getAlpha() {
    397         return nGetAlpha(mNativeRenderNode);
    398     }
    399 
    400     /**
    401      * Sets whether the display list renders content which overlaps. Non-overlapping rendering
    402      * can use a fast path for alpha that avoids rendering to an offscreen buffer. By default
    403      * display lists consider they do not have overlapping content.
    404      *
    405      * @param hasOverlappingRendering False if the content is guaranteed to be non-overlapping,
    406      *                                true otherwise.
    407      *
    408      * @see android.view.View#hasOverlappingRendering()
    409      * @see #hasOverlappingRendering()
    410      */
    411     public boolean setHasOverlappingRendering(boolean hasOverlappingRendering) {
    412         return nSetHasOverlappingRendering(mNativeRenderNode, hasOverlappingRendering);
    413     }
    414 
    415     /**
    416      * Indicates whether the content of this display list overlaps.
    417      *
    418      * @return True if this display list renders content which overlaps, false otherwise.
    419      *
    420      * @see #setHasOverlappingRendering(boolean)
    421      */
    422     public boolean hasOverlappingRendering() {
    423         //noinspection SimplifiableIfStatement
    424         return nHasOverlappingRendering(mNativeRenderNode);
    425     }
    426 
    427     public boolean setElevation(float lift) {
    428         return nSetElevation(mNativeRenderNode, lift);
    429     }
    430 
    431     public float getElevation() {
    432         return nGetElevation(mNativeRenderNode);
    433     }
    434 
    435     /**
    436      * Sets the translation value for the display list on the X axis.
    437      *
    438      * @param translationX The X axis translation value of the display list, in pixels
    439      *
    440      * @see View#setTranslationX(float)
    441      * @see #getTranslationX()
    442      */
    443     public boolean setTranslationX(float translationX) {
    444         return nSetTranslationX(mNativeRenderNode, translationX);
    445     }
    446 
    447     /**
    448      * Returns the translation value for this display list on the X axis, in pixels.
    449      *
    450      * @see #setTranslationX(float)
    451      */
    452     public float getTranslationX() {
    453         return nGetTranslationX(mNativeRenderNode);
    454     }
    455 
    456     /**
    457      * Sets the translation value for the display list on the Y axis.
    458      *
    459      * @param translationY The Y axis translation value of the display list, in pixels
    460      *
    461      * @see View#setTranslationY(float)
    462      * @see #getTranslationY()
    463      */
    464     public boolean setTranslationY(float translationY) {
    465         return nSetTranslationY(mNativeRenderNode, translationY);
    466     }
    467 
    468     /**
    469      * Returns the translation value for this display list on the Y axis, in pixels.
    470      *
    471      * @see #setTranslationY(float)
    472      */
    473     public float getTranslationY() {
    474         return nGetTranslationY(mNativeRenderNode);
    475     }
    476 
    477     /**
    478      * Sets the translation value for the display list on the Z axis.
    479      *
    480      * @see View#setTranslationZ(float)
    481      * @see #getTranslationZ()
    482      */
    483     public boolean setTranslationZ(float translationZ) {
    484         return nSetTranslationZ(mNativeRenderNode, translationZ);
    485     }
    486 
    487     /**
    488      * Returns the translation value for this display list on the Z axis.
    489      *
    490      * @see #setTranslationZ(float)
    491      */
    492     public float getTranslationZ() {
    493         return nGetTranslationZ(mNativeRenderNode);
    494     }
    495 
    496     /**
    497      * Sets the rotation value for the display list around the Z axis.
    498      *
    499      * @param rotation The rotation value of the display list, in degrees
    500      *
    501      * @see View#setRotation(float)
    502      * @see #getRotation()
    503      */
    504     public boolean setRotation(float rotation) {
    505         return nSetRotation(mNativeRenderNode, rotation);
    506     }
    507 
    508     /**
    509      * Returns the rotation value for this display list around the Z axis, in degrees.
    510      *
    511      * @see #setRotation(float)
    512      */
    513     public float getRotation() {
    514         return nGetRotation(mNativeRenderNode);
    515     }
    516 
    517     /**
    518      * Sets the rotation value for the display list around the X axis.
    519      *
    520      * @param rotationX The rotation value of the display list, in degrees
    521      *
    522      * @see View#setRotationX(float)
    523      * @see #getRotationX()
    524      */
    525     public boolean setRotationX(float rotationX) {
    526         return nSetRotationX(mNativeRenderNode, rotationX);
    527     }
    528 
    529     /**
    530      * Returns the rotation value for this display list around the X axis, in degrees.
    531      *
    532      * @see #setRotationX(float)
    533      */
    534     public float getRotationX() {
    535         return nGetRotationX(mNativeRenderNode);
    536     }
    537 
    538     /**
    539      * Sets the rotation value for the display list around the Y axis.
    540      *
    541      * @param rotationY The rotation value of the display list, in degrees
    542      *
    543      * @see View#setRotationY(float)
    544      * @see #getRotationY()
    545      */
    546     public boolean setRotationY(float rotationY) {
    547         return nSetRotationY(mNativeRenderNode, rotationY);
    548     }
    549 
    550     /**
    551      * Returns the rotation value for this display list around the Y axis, in degrees.
    552      *
    553      * @see #setRotationY(float)
    554      */
    555     public float getRotationY() {
    556         return nGetRotationY(mNativeRenderNode);
    557     }
    558 
    559     /**
    560      * Sets the scale value for the display list on the X axis.
    561      *
    562      * @param scaleX The scale value of the display list
    563      *
    564      * @see View#setScaleX(float)
    565      * @see #getScaleX()
    566      */
    567     public boolean setScaleX(float scaleX) {
    568         return nSetScaleX(mNativeRenderNode, scaleX);
    569     }
    570 
    571     /**
    572      * Returns the scale value for this display list on the X axis.
    573      *
    574      * @see #setScaleX(float)
    575      */
    576     public float getScaleX() {
    577         return nGetScaleX(mNativeRenderNode);
    578     }
    579 
    580     /**
    581      * Sets the scale value for the display list on the Y axis.
    582      *
    583      * @param scaleY The scale value of the display list
    584      *
    585      * @see View#setScaleY(float)
    586      * @see #getScaleY()
    587      */
    588     public boolean setScaleY(float scaleY) {
    589         return nSetScaleY(mNativeRenderNode, scaleY);
    590     }
    591 
    592     /**
    593      * Returns the scale value for this display list on the Y axis.
    594      *
    595      * @see #setScaleY(float)
    596      */
    597     public float getScaleY() {
    598         return nGetScaleY(mNativeRenderNode);
    599     }
    600 
    601     /**
    602      * Sets the pivot value for the display list on the X axis
    603      *
    604      * @param pivotX The pivot value of the display list on the X axis, in pixels
    605      *
    606      * @see View#setPivotX(float)
    607      * @see #getPivotX()
    608      */
    609     public boolean setPivotX(float pivotX) {
    610         return nSetPivotX(mNativeRenderNode, pivotX);
    611     }
    612 
    613     /**
    614      * Returns the pivot value for this display list on the X axis, in pixels.
    615      *
    616      * @see #setPivotX(float)
    617      */
    618     public float getPivotX() {
    619         return nGetPivotX(mNativeRenderNode);
    620     }
    621 
    622     /**
    623      * Sets the pivot value for the display list on the Y axis
    624      *
    625      * @param pivotY The pivot value of the display list on the Y axis, in pixels
    626      *
    627      * @see View#setPivotY(float)
    628      * @see #getPivotY()
    629      */
    630     public boolean setPivotY(float pivotY) {
    631         return nSetPivotY(mNativeRenderNode, pivotY);
    632     }
    633 
    634     /**
    635      * Returns the pivot value for this display list on the Y axis, in pixels.
    636      *
    637      * @see #setPivotY(float)
    638      */
    639     public float getPivotY() {
    640         return nGetPivotY(mNativeRenderNode);
    641     }
    642 
    643     public boolean isPivotExplicitlySet() {
    644         return nIsPivotExplicitlySet(mNativeRenderNode);
    645     }
    646 
    647     /**
    648      * Sets the camera distance for the display list. Refer to
    649      * {@link View#setCameraDistance(float)} for more information on how to
    650      * use this property.
    651      *
    652      * @param distance The distance in Z of the camera of the display list
    653      *
    654      * @see View#setCameraDistance(float)
    655      * @see #getCameraDistance()
    656      */
    657     public boolean setCameraDistance(float distance) {
    658         return nSetCameraDistance(mNativeRenderNode, distance);
    659     }
    660 
    661     /**
    662      * Returns the distance in Z of the camera of the display list.
    663      *
    664      * @see #setCameraDistance(float)
    665      */
    666     public float getCameraDistance() {
    667         return nGetCameraDistance(mNativeRenderNode);
    668     }
    669 
    670     /**
    671      * Sets the left position for the display list.
    672      *
    673      * @param left The left position, in pixels, of the display list
    674      *
    675      * @see View#setLeft(int)
    676      */
    677     public boolean setLeft(int left) {
    678         return nSetLeft(mNativeRenderNode, left);
    679     }
    680 
    681     /**
    682      * Sets the top position for the display list.
    683      *
    684      * @param top The top position, in pixels, of the display list
    685      *
    686      * @see View#setTop(int)
    687      */
    688     public boolean setTop(int top) {
    689         return nSetTop(mNativeRenderNode, top);
    690     }
    691 
    692     /**
    693      * Sets the right position for the display list.
    694      *
    695      * @param right The right position, in pixels, of the display list
    696      *
    697      * @see View#setRight(int)
    698      */
    699     public boolean setRight(int right) {
    700         return nSetRight(mNativeRenderNode, right);
    701     }
    702 
    703     /**
    704      * Sets the bottom position for the display list.
    705      *
    706      * @param bottom The bottom position, in pixels, of the display list
    707      *
    708      * @see View#setBottom(int)
    709      */
    710     public boolean setBottom(int bottom) {
    711         return nSetBottom(mNativeRenderNode, bottom);
    712     }
    713 
    714     /**
    715      * Sets the left and top positions for the display list
    716      *
    717      * @param left The left position of the display list, in pixels
    718      * @param top The top position of the display list, in pixels
    719      * @param right The right position of the display list, in pixels
    720      * @param bottom The bottom position of the display list, in pixels
    721      *
    722      * @see View#setLeft(int)
    723      * @see View#setTop(int)
    724      * @see View#setRight(int)
    725      * @see View#setBottom(int)
    726      */
    727     public boolean setLeftTopRightBottom(int left, int top, int right, int bottom) {
    728         return nSetLeftTopRightBottom(mNativeRenderNode, left, top, right, bottom);
    729     }
    730 
    731     /**
    732      * Offsets the left and right positions for the display list
    733      *
    734      * @param offset The amount that the left and right positions of the display
    735      *               list are offset, in pixels
    736      *
    737      * @see View#offsetLeftAndRight(int)
    738      */
    739     public boolean offsetLeftAndRight(int offset) {
    740         return nOffsetLeftAndRight(mNativeRenderNode, offset);
    741     }
    742 
    743     /**
    744      * Offsets the top and bottom values for the display list
    745      *
    746      * @param offset The amount that the top and bottom positions of the display
    747      *               list are offset, in pixels
    748      *
    749      * @see View#offsetTopAndBottom(int)
    750      */
    751     public boolean offsetTopAndBottom(int offset) {
    752         return nOffsetTopAndBottom(mNativeRenderNode, offset);
    753     }
    754 
    755     /**
    756      * Outputs the display list to the log. This method exists for use by
    757      * tools to output display lists for selected nodes to the log.
    758      */
    759     public void output() {
    760         nOutput(mNativeRenderNode);
    761     }
    762 
    763     /**
    764      * Gets the size of the DisplayList for debug purposes.
    765      */
    766     public int getDebugSize() {
    767         return nGetDebugSize(mNativeRenderNode);
    768     }
    769 
    770     /**
    771      * Called by native when the passed displaylist is removed from the draw tree
    772      */
    773     void onRenderNodeDetached() {
    774         discardDisplayList();
    775         if (mOwningView != null) {
    776             mOwningView.onRenderNodeDetached(this);
    777         }
    778     }
    779 
    780     ///////////////////////////////////////////////////////////////////////////
    781     // Animations
    782     ///////////////////////////////////////////////////////////////////////////
    783 
    784     public void addAnimator(RenderNodeAnimator animator) {
    785         if (mOwningView == null || mOwningView.mAttachInfo == null) {
    786             throw new IllegalStateException("Cannot start this animator on a detached view!");
    787         }
    788         nAddAnimator(mNativeRenderNode, animator.getNativeAnimator());
    789         mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this);
    790     }
    791 
    792     public boolean isAttached() {
    793         return mOwningView != null && mOwningView.mAttachInfo != null;
    794     }
    795 
    796     public void registerVectorDrawableAnimator(
    797             AnimatedVectorDrawable.VectorDrawableAnimatorRT animatorSet) {
    798         if (mOwningView == null || mOwningView.mAttachInfo == null) {
    799             throw new IllegalStateException("Cannot start this animator on a detached view!");
    800         }
    801         mOwningView.mAttachInfo.mViewRootImpl.registerVectorDrawableAnimator(animatorSet);
    802     }
    803 
    804     public void endAllAnimators() {
    805         nEndAllAnimators(mNativeRenderNode);
    806     }
    807 
    808     ///////////////////////////////////////////////////////////////////////////
    809     // Native methods
    810     ///////////////////////////////////////////////////////////////////////////
    811 
    812     // Intentionally not static because it acquires a reference to 'this'
    813     private native long nCreate(String name);
    814 
    815     private static native void nDestroyRenderNode(long renderNode);
    816     private static native void nSetDisplayList(long renderNode, long newData);
    817 
    818     // Matrix
    819 
    820     private static native void nGetTransformMatrix(long renderNode, long nativeMatrix);
    821     private static native void nGetInverseTransformMatrix(long renderNode, long nativeMatrix);
    822     private static native boolean nHasIdentityMatrix(long renderNode);
    823 
    824     // Properties
    825 
    826     private static native boolean nOffsetTopAndBottom(long renderNode, int offset);
    827     private static native boolean nOffsetLeftAndRight(long renderNode, int offset);
    828     private static native boolean nSetLeftTopRightBottom(long renderNode, int left, int top,
    829             int right, int bottom);
    830     private static native boolean nSetBottom(long renderNode, int bottom);
    831     private static native boolean nSetRight(long renderNode, int right);
    832     private static native boolean nSetTop(long renderNode, int top);
    833     private static native boolean nSetLeft(long renderNode, int left);
    834     private static native boolean nSetCameraDistance(long renderNode, float distance);
    835     private static native boolean nSetPivotY(long renderNode, float pivotY);
    836     private static native boolean nSetPivotX(long renderNode, float pivotX);
    837     private static native boolean nSetLayerType(long renderNode, int layerType);
    838     private static native boolean nSetLayerPaint(long renderNode, long paint);
    839     private static native boolean nSetClipToBounds(long renderNode, boolean clipToBounds);
    840     private static native boolean nSetClipBounds(long renderNode, int left, int top,
    841             int right, int bottom);
    842     private static native boolean nSetClipBoundsEmpty(long renderNode);
    843     private static native boolean nSetProjectBackwards(long renderNode, boolean shouldProject);
    844     private static native boolean nSetProjectionReceiver(long renderNode, boolean shouldRecieve);
    845     private static native boolean nSetOutlineRoundRect(long renderNode, int left, int top,
    846             int right, int bottom, float radius, float alpha);
    847     private static native boolean nSetOutlineConvexPath(long renderNode, long nativePath,
    848             float alpha);
    849     private static native boolean nSetOutlineEmpty(long renderNode);
    850     private static native boolean nSetOutlineNone(long renderNode);
    851     private static native boolean nHasShadow(long renderNode);
    852     private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline);
    853     private static native boolean nSetRevealClip(long renderNode,
    854             boolean shouldClip, float x, float y, float radius);
    855     private static native boolean nSetAlpha(long renderNode, float alpha);
    856     private static native boolean nSetHasOverlappingRendering(long renderNode,
    857             boolean hasOverlappingRendering);
    858     private static native boolean nSetElevation(long renderNode, float lift);
    859     private static native boolean nSetTranslationX(long renderNode, float translationX);
    860     private static native boolean nSetTranslationY(long renderNode, float translationY);
    861     private static native boolean nSetTranslationZ(long renderNode, float translationZ);
    862     private static native boolean nSetRotation(long renderNode, float rotation);
    863     private static native boolean nSetRotationX(long renderNode, float rotationX);
    864     private static native boolean nSetRotationY(long renderNode, float rotationY);
    865     private static native boolean nSetScaleX(long renderNode, float scaleX);
    866     private static native boolean nSetScaleY(long renderNode, float scaleY);
    867     private static native boolean nSetStaticMatrix(long renderNode, long nativeMatrix);
    868     private static native boolean nSetAnimationMatrix(long renderNode, long animationMatrix);
    869 
    870     private static native boolean nHasOverlappingRendering(long renderNode);
    871     private static native boolean nGetClipToOutline(long renderNode);
    872     private static native float nGetAlpha(long renderNode);
    873     private static native float nGetCameraDistance(long renderNode);
    874     private static native float nGetScaleX(long renderNode);
    875     private static native float nGetScaleY(long renderNode);
    876     private static native float nGetElevation(long renderNode);
    877     private static native float nGetTranslationX(long renderNode);
    878     private static native float nGetTranslationY(long renderNode);
    879     private static native float nGetTranslationZ(long renderNode);
    880     private static native float nGetRotation(long renderNode);
    881     private static native float nGetRotationX(long renderNode);
    882     private static native float nGetRotationY(long renderNode);
    883     private static native boolean nIsPivotExplicitlySet(long renderNode);
    884     private static native float nGetPivotX(long renderNode);
    885     private static native float nGetPivotY(long renderNode);
    886     private static native void nOutput(long renderNode);
    887     private static native int nGetDebugSize(long renderNode);
    888 
    889     private static native void nRequestPositionUpdates(long renderNode, SurfaceView callback);
    890 
    891     ///////////////////////////////////////////////////////////////////////////
    892     // Animations
    893     ///////////////////////////////////////////////////////////////////////////
    894 
    895     private static native void nAddAnimator(long renderNode, long animatorPtr);
    896     private static native void nEndAllAnimators(long renderNode);
    897 
    898     ///////////////////////////////////////////////////////////////////////////
    899     // Finalization
    900     ///////////////////////////////////////////////////////////////////////////
    901 
    902     @Override
    903     protected void finalize() throws Throwable {
    904         try {
    905             nDestroyRenderNode(mNativeRenderNode);
    906         } finally {
    907             super.finalize();
    908         }
    909     }
    910 }
    911