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