RenderNode.java revision 44b49f070aafe8ad44efae87341121cce49ff11c
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;
25import 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 */
129public 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(Outline outline) {
311        if (outline == null) {
312            return nSetOutlineNone(mNativeRenderNode);
313        } else if (outline.isEmpty()) {
314            return nSetOutlineEmpty(mNativeRenderNode);
315        } else if (outline.mRect != null) {
316            return nSetOutlineRoundRect(mNativeRenderNode, outline.mRect.left, outline.mRect.top,
317                    outline.mRect.right, outline.mRect.bottom, outline.mRadius, outline.mAlpha);
318        } else if (outline.mPath != null) {
319            return nSetOutlineConvexPath(mNativeRenderNode, outline.mPath.mNativePath,
320                    outline.mAlpha);
321        }
322        throw new IllegalArgumentException("Unrecognized outline?");
323    }
324
325    public boolean hasShadow() {
326        return nHasShadow(mNativeRenderNode);
327    }
328
329    /**
330     * Enables or disables clipping to the outline.
331     *
332     * @param clipToOutline true if clipping to the outline.
333     */
334    public boolean setClipToOutline(boolean clipToOutline) {
335        return nSetClipToOutline(mNativeRenderNode, clipToOutline);
336    }
337
338    public boolean getClipToOutline() {
339        return nGetClipToOutline(mNativeRenderNode);
340    }
341
342    /**
343     * Controls the RenderNode's circular reveal clip.
344     */
345    public boolean setRevealClip(boolean shouldClip,
346            float x, float y, float radius) {
347        return nSetRevealClip(mNativeRenderNode, shouldClip, x, y, radius);
348    }
349
350    /**
351     * Set the static matrix on the display list. The specified matrix is combined with other
352     * transforms (such as {@link #setScaleX(float)}, {@link #setRotation(float)}, etc.)
353     *
354     * @param matrix A transform matrix to apply to this display list
355     */
356    public boolean setStaticMatrix(Matrix matrix) {
357        return nSetStaticMatrix(mNativeRenderNode, matrix.native_instance);
358    }
359
360    /**
361     * Set the Animation matrix on the display list. This matrix exists if an Animation is
362     * currently playing on a View, and is set on the display list during at draw() time. When
363     * the Animation finishes, the matrix should be cleared by sending <code>null</code>
364     * for the matrix parameter.
365     *
366     * @param matrix The matrix, null indicates that the matrix should be cleared.
367     */
368    public boolean setAnimationMatrix(Matrix matrix) {
369        return nSetAnimationMatrix(mNativeRenderNode,
370                (matrix != null) ? matrix.native_instance : 0);
371    }
372
373    /**
374     * Sets the translucency level for the display list.
375     *
376     * @param alpha The translucency of the display list, must be a value between 0.0f and 1.0f
377     *
378     * @see View#setAlpha(float)
379     * @see #getAlpha()
380     */
381    public boolean setAlpha(float alpha) {
382        return nSetAlpha(mNativeRenderNode, alpha);
383    }
384
385    /**
386     * Returns the translucency level of this display list.
387     *
388     * @return A value between 0.0f and 1.0f
389     *
390     * @see #setAlpha(float)
391     */
392    public float getAlpha() {
393        return nGetAlpha(mNativeRenderNode);
394    }
395
396    /**
397     * Sets whether the display list renders content which overlaps. Non-overlapping rendering
398     * can use a fast path for alpha that avoids rendering to an offscreen buffer. By default
399     * display lists consider they do not have overlapping content.
400     *
401     * @param hasOverlappingRendering False if the content is guaranteed to be non-overlapping,
402     *                                true otherwise.
403     *
404     * @see android.view.View#hasOverlappingRendering()
405     * @see #hasOverlappingRendering()
406     */
407    public boolean setHasOverlappingRendering(boolean hasOverlappingRendering) {
408        return nSetHasOverlappingRendering(mNativeRenderNode, hasOverlappingRendering);
409    }
410
411    /**
412     * Indicates whether the content of this display list overlaps.
413     *
414     * @return True if this display list renders content which overlaps, false otherwise.
415     *
416     * @see #setHasOverlappingRendering(boolean)
417     */
418    public boolean hasOverlappingRendering() {
419        //noinspection SimplifiableIfStatement
420        return nHasOverlappingRendering(mNativeRenderNode);
421    }
422
423    public boolean setElevation(float lift) {
424        return nSetElevation(mNativeRenderNode, lift);
425    }
426
427    public float getElevation() {
428        return nGetElevation(mNativeRenderNode);
429    }
430
431    /**
432     * Sets the translation value for the display list on the X axis.
433     *
434     * @param translationX The X axis translation value of the display list, in pixels
435     *
436     * @see View#setTranslationX(float)
437     * @see #getTranslationX()
438     */
439    public boolean setTranslationX(float translationX) {
440        return nSetTranslationX(mNativeRenderNode, translationX);
441    }
442
443    /**
444     * Returns the translation value for this display list on the X axis, in pixels.
445     *
446     * @see #setTranslationX(float)
447     */
448    public float getTranslationX() {
449        return nGetTranslationX(mNativeRenderNode);
450    }
451
452    /**
453     * Sets the translation value for the display list on the Y axis.
454     *
455     * @param translationY The Y axis translation value of the display list, in pixels
456     *
457     * @see View#setTranslationY(float)
458     * @see #getTranslationY()
459     */
460    public boolean setTranslationY(float translationY) {
461        return nSetTranslationY(mNativeRenderNode, translationY);
462    }
463
464    /**
465     * Returns the translation value for this display list on the Y axis, in pixels.
466     *
467     * @see #setTranslationY(float)
468     */
469    public float getTranslationY() {
470        return nGetTranslationY(mNativeRenderNode);
471    }
472
473    /**
474     * Sets the translation value for the display list on the Z axis.
475     *
476     * @see View#setTranslationZ(float)
477     * @see #getTranslationZ()
478     */
479    public boolean setTranslationZ(float translationZ) {
480        return nSetTranslationZ(mNativeRenderNode, translationZ);
481    }
482
483    /**
484     * Returns the translation value for this display list on the Z axis.
485     *
486     * @see #setTranslationZ(float)
487     */
488    public float getTranslationZ() {
489        return nGetTranslationZ(mNativeRenderNode);
490    }
491
492    /**
493     * Sets the rotation value for the display list around the Z axis.
494     *
495     * @param rotation The rotation value of the display list, in degrees
496     *
497     * @see View#setRotation(float)
498     * @see #getRotation()
499     */
500    public boolean setRotation(float rotation) {
501        return nSetRotation(mNativeRenderNode, rotation);
502    }
503
504    /**
505     * Returns the rotation value for this display list around the Z axis, in degrees.
506     *
507     * @see #setRotation(float)
508     */
509    public float getRotation() {
510        return nGetRotation(mNativeRenderNode);
511    }
512
513    /**
514     * Sets the rotation value for the display list around the X axis.
515     *
516     * @param rotationX The rotation value of the display list, in degrees
517     *
518     * @see View#setRotationX(float)
519     * @see #getRotationX()
520     */
521    public boolean setRotationX(float rotationX) {
522        return nSetRotationX(mNativeRenderNode, rotationX);
523    }
524
525    /**
526     * Returns the rotation value for this display list around the X axis, in degrees.
527     *
528     * @see #setRotationX(float)
529     */
530    public float getRotationX() {
531        return nGetRotationX(mNativeRenderNode);
532    }
533
534    /**
535     * Sets the rotation value for the display list around the Y axis.
536     *
537     * @param rotationY The rotation value of the display list, in degrees
538     *
539     * @see View#setRotationY(float)
540     * @see #getRotationY()
541     */
542    public boolean setRotationY(float rotationY) {
543        return nSetRotationY(mNativeRenderNode, rotationY);
544    }
545
546    /**
547     * Returns the rotation value for this display list around the Y axis, in degrees.
548     *
549     * @see #setRotationY(float)
550     */
551    public float getRotationY() {
552        return nGetRotationY(mNativeRenderNode);
553    }
554
555    /**
556     * Sets the scale value for the display list on the X axis.
557     *
558     * @param scaleX The scale value of the display list
559     *
560     * @see View#setScaleX(float)
561     * @see #getScaleX()
562     */
563    public boolean setScaleX(float scaleX) {
564        return nSetScaleX(mNativeRenderNode, scaleX);
565    }
566
567    /**
568     * Returns the scale value for this display list on the X axis.
569     *
570     * @see #setScaleX(float)
571     */
572    public float getScaleX() {
573        return nGetScaleX(mNativeRenderNode);
574    }
575
576    /**
577     * Sets the scale value for the display list on the Y axis.
578     *
579     * @param scaleY The scale value of the display list
580     *
581     * @see View#setScaleY(float)
582     * @see #getScaleY()
583     */
584    public boolean setScaleY(float scaleY) {
585        return nSetScaleY(mNativeRenderNode, scaleY);
586    }
587
588    /**
589     * Returns the scale value for this display list on the Y axis.
590     *
591     * @see #setScaleY(float)
592     */
593    public float getScaleY() {
594        return nGetScaleY(mNativeRenderNode);
595    }
596
597    /**
598     * Sets the pivot value for the display list on the X axis
599     *
600     * @param pivotX The pivot value of the display list on the X axis, in pixels
601     *
602     * @see View#setPivotX(float)
603     * @see #getPivotX()
604     */
605    public boolean setPivotX(float pivotX) {
606        return nSetPivotX(mNativeRenderNode, pivotX);
607    }
608
609    /**
610     * Returns the pivot value for this display list on the X axis, in pixels.
611     *
612     * @see #setPivotX(float)
613     */
614    public float getPivotX() {
615        return nGetPivotX(mNativeRenderNode);
616    }
617
618    /**
619     * Sets the pivot value for the display list on the Y axis
620     *
621     * @param pivotY The pivot value of the display list on the Y axis, in pixels
622     *
623     * @see View#setPivotY(float)
624     * @see #getPivotY()
625     */
626    public boolean setPivotY(float pivotY) {
627        return nSetPivotY(mNativeRenderNode, pivotY);
628    }
629
630    /**
631     * Returns the pivot value for this display list on the Y axis, in pixels.
632     *
633     * @see #setPivotY(float)
634     */
635    public float getPivotY() {
636        return nGetPivotY(mNativeRenderNode);
637    }
638
639    public boolean isPivotExplicitlySet() {
640        return nIsPivotExplicitlySet(mNativeRenderNode);
641    }
642
643    /**
644     * Sets the camera distance for the display list. Refer to
645     * {@link View#setCameraDistance(float)} for more information on how to
646     * use this property.
647     *
648     * @param distance The distance in Z of the camera of the display list
649     *
650     * @see View#setCameraDistance(float)
651     * @see #getCameraDistance()
652     */
653    public boolean setCameraDistance(float distance) {
654        return nSetCameraDistance(mNativeRenderNode, distance);
655    }
656
657    /**
658     * Returns the distance in Z of the camera of the display list.
659     *
660     * @see #setCameraDistance(float)
661     */
662    public float getCameraDistance() {
663        return nGetCameraDistance(mNativeRenderNode);
664    }
665
666    /**
667     * Sets the left position for the display list.
668     *
669     * @param left The left position, in pixels, of the display list
670     *
671     * @see View#setLeft(int)
672     */
673    public boolean setLeft(int left) {
674        return nSetLeft(mNativeRenderNode, left);
675    }
676
677    /**
678     * Sets the top position for the display list.
679     *
680     * @param top The top position, in pixels, of the display list
681     *
682     * @see View#setTop(int)
683     */
684    public boolean setTop(int top) {
685        return nSetTop(mNativeRenderNode, top);
686    }
687
688    /**
689     * Sets the right position for the display list.
690     *
691     * @param right The right position, in pixels, of the display list
692     *
693     * @see View#setRight(int)
694     */
695    public boolean setRight(int right) {
696        return nSetRight(mNativeRenderNode, right);
697    }
698
699    /**
700     * Sets the bottom position for the display list.
701     *
702     * @param bottom The bottom position, in pixels, of the display list
703     *
704     * @see View#setBottom(int)
705     */
706    public boolean setBottom(int bottom) {
707        return nSetBottom(mNativeRenderNode, bottom);
708    }
709
710    /**
711     * Sets the left and top positions for the display list
712     *
713     * @param left The left position of the display list, in pixels
714     * @param top The top position of the display list, in pixels
715     * @param right The right position of the display list, in pixels
716     * @param bottom The bottom position of the display list, in pixels
717     *
718     * @see View#setLeft(int)
719     * @see View#setTop(int)
720     * @see View#setRight(int)
721     * @see View#setBottom(int)
722     */
723    public boolean setLeftTopRightBottom(int left, int top, int right, int bottom) {
724        return nSetLeftTopRightBottom(mNativeRenderNode, left, top, right, bottom);
725    }
726
727    /**
728     * Offsets the left and right positions for the display list
729     *
730     * @param offset The amount that the left and right positions of the display
731     *               list are offset, in pixels
732     *
733     * @see View#offsetLeftAndRight(int)
734     */
735    public boolean offsetLeftAndRight(int offset) {
736        return nOffsetLeftAndRight(mNativeRenderNode, offset);
737    }
738
739    /**
740     * Offsets the top and bottom values for the display list
741     *
742     * @param offset The amount that the top and bottom positions of the display
743     *               list are offset, in pixels
744     *
745     * @see View#offsetTopAndBottom(int)
746     */
747    public boolean offsetTopAndBottom(int offset) {
748        return nOffsetTopAndBottom(mNativeRenderNode, offset);
749    }
750
751    /**
752     * Outputs the display list to the log. This method exists for use by
753     * tools to output display lists for selected nodes to the log.
754     */
755    public void output() {
756        nOutput(mNativeRenderNode);
757    }
758
759    /**
760     * Gets the size of the DisplayList for debug purposes.
761     */
762    public int getDebugSize() {
763        return nGetDebugSize(mNativeRenderNode);
764    }
765
766    /**
767     * Called by native when the passed displaylist is removed from the draw tree
768     */
769    void onRenderNodeDetached() {
770        discardDisplayList();
771        if (mOwningView != null) {
772            mOwningView.onRenderNodeDetached(this);
773        }
774    }
775
776    ///////////////////////////////////////////////////////////////////////////
777    // Animations
778    ///////////////////////////////////////////////////////////////////////////
779
780    public void addAnimator(RenderNodeAnimator animator) {
781        if (mOwningView == null || mOwningView.mAttachInfo == null) {
782            throw new IllegalStateException("Cannot start this animator on a detached view!");
783        }
784        nAddAnimator(mNativeRenderNode, animator.getNativeAnimator());
785        mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this);
786    }
787
788    public boolean isAttached() {
789        return mOwningView != null && mOwningView.mAttachInfo != null;
790    }
791
792    public void addAnimator(AnimatedVectorDrawable.VectorDrawableAnimatorRT animatorSet) {
793        if (mOwningView == null || mOwningView.mAttachInfo == null) {
794            throw new IllegalStateException("Cannot start this animator on a detached view!");
795        }
796        nAddAnimator(mNativeRenderNode, animatorSet.getAnimatorNativePtr());
797        mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this);
798    }
799
800    public void endAllAnimators() {
801        nEndAllAnimators(mNativeRenderNode);
802    }
803
804    ///////////////////////////////////////////////////////////////////////////
805    // Native methods
806    ///////////////////////////////////////////////////////////////////////////
807
808    // Intentionally not static because it acquires a reference to 'this'
809    private native long nCreate(String name);
810
811    private static native void nDestroyRenderNode(long renderNode);
812    private static native void nSetDisplayList(long renderNode, long newData);
813
814    // Matrix
815
816    private static native void nGetTransformMatrix(long renderNode, long nativeMatrix);
817    private static native void nGetInverseTransformMatrix(long renderNode, long nativeMatrix);
818    private static native boolean nHasIdentityMatrix(long renderNode);
819
820    // Properties
821
822    private static native boolean nOffsetTopAndBottom(long renderNode, int offset);
823    private static native boolean nOffsetLeftAndRight(long renderNode, int offset);
824    private static native boolean nSetLeftTopRightBottom(long renderNode, int left, int top,
825            int right, int bottom);
826    private static native boolean nSetBottom(long renderNode, int bottom);
827    private static native boolean nSetRight(long renderNode, int right);
828    private static native boolean nSetTop(long renderNode, int top);
829    private static native boolean nSetLeft(long renderNode, int left);
830    private static native boolean nSetCameraDistance(long renderNode, float distance);
831    private static native boolean nSetPivotY(long renderNode, float pivotY);
832    private static native boolean nSetPivotX(long renderNode, float pivotX);
833    private static native boolean nSetLayerType(long renderNode, int layerType);
834    private static native boolean nSetLayerPaint(long renderNode, long paint);
835    private static native boolean nSetClipToBounds(long renderNode, boolean clipToBounds);
836    private static native boolean nSetClipBounds(long renderNode, int left, int top,
837            int right, int bottom);
838    private static native boolean nSetClipBoundsEmpty(long renderNode);
839    private static native boolean nSetProjectBackwards(long renderNode, boolean shouldProject);
840    private static native boolean nSetProjectionReceiver(long renderNode, boolean shouldRecieve);
841    private static native boolean nSetOutlineRoundRect(long renderNode, int left, int top,
842            int right, int bottom, float radius, float alpha);
843    private static native boolean nSetOutlineConvexPath(long renderNode, long nativePath,
844            float alpha);
845    private static native boolean nSetOutlineEmpty(long renderNode);
846    private static native boolean nSetOutlineNone(long renderNode);
847    private static native boolean nHasShadow(long renderNode);
848    private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline);
849    private static native boolean nSetRevealClip(long renderNode,
850            boolean shouldClip, float x, float y, float radius);
851    private static native boolean nSetAlpha(long renderNode, float alpha);
852    private static native boolean nSetHasOverlappingRendering(long renderNode,
853            boolean hasOverlappingRendering);
854    private static native boolean nSetElevation(long renderNode, float lift);
855    private static native boolean nSetTranslationX(long renderNode, float translationX);
856    private static native boolean nSetTranslationY(long renderNode, float translationY);
857    private static native boolean nSetTranslationZ(long renderNode, float translationZ);
858    private static native boolean nSetRotation(long renderNode, float rotation);
859    private static native boolean nSetRotationX(long renderNode, float rotationX);
860    private static native boolean nSetRotationY(long renderNode, float rotationY);
861    private static native boolean nSetScaleX(long renderNode, float scaleX);
862    private static native boolean nSetScaleY(long renderNode, float scaleY);
863    private static native boolean nSetStaticMatrix(long renderNode, long nativeMatrix);
864    private static native boolean nSetAnimationMatrix(long renderNode, long animationMatrix);
865
866    private static native boolean nHasOverlappingRendering(long renderNode);
867    private static native boolean nGetClipToOutline(long renderNode);
868    private static native float nGetAlpha(long renderNode);
869    private static native float nGetCameraDistance(long renderNode);
870    private static native float nGetScaleX(long renderNode);
871    private static native float nGetScaleY(long renderNode);
872    private static native float nGetElevation(long renderNode);
873    private static native float nGetTranslationX(long renderNode);
874    private static native float nGetTranslationY(long renderNode);
875    private static native float nGetTranslationZ(long renderNode);
876    private static native float nGetRotation(long renderNode);
877    private static native float nGetRotationX(long renderNode);
878    private static native float nGetRotationY(long renderNode);
879    private static native boolean nIsPivotExplicitlySet(long renderNode);
880    private static native float nGetPivotX(long renderNode);
881    private static native float nGetPivotY(long renderNode);
882    private static native void nOutput(long renderNode);
883    private static native int nGetDebugSize(long renderNode);
884
885    private static native void nRequestPositionUpdates(long renderNode, SurfaceView callback);
886
887    ///////////////////////////////////////////////////////////////////////////
888    // Animations
889    ///////////////////////////////////////////////////////////////////////////
890
891    private static native void nAddAnimator(long renderNode, long animatorPtr);
892    private static native void nEndAllAnimators(long renderNode);
893
894    ///////////////////////////////////////////////////////////////////////////
895    // Finalization
896    ///////////////////////////////////////////////////////////////////////////
897
898    @Override
899    protected void finalize() throws Throwable {
900        try {
901            nDestroyRenderNode(mNativeRenderNode);
902        } finally {
903            super.finalize();
904        }
905    }
906}
907