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 HardwareCanvas}. 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 HardwareCanvas}. 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 *         HardwareCanvas 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 *             HardwareCanvas hardwareCanvas = (HardwareCanvas) canvas;
71 *             hardwareCanvas.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 *         HardwareCanvas 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 *             HardwareCanvas hardwareCanvas = (HardwareCanvas) canvas;
109 *             hardwareCanvas.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     * Flag used when calling
131     * {@link HardwareCanvas#drawRenderNode(RenderNode, android.graphics.Rect, int)}
132     * When this flag is set, draw operations lying outside of the bounds of the
133     * display list will be culled early. It is recommeneded to always set this
134     * flag.
135     */
136    public static final int FLAG_CLIP_CHILDREN = 0x1;
137
138    // NOTE: The STATUS_* values *must* match the enum in DrawGlInfo.h
139
140    /**
141     * Indicates that the display list is done drawing.
142     *
143     * @see HardwareCanvas#drawRenderNode(RenderNode, android.graphics.Rect, int)
144     */
145    public static final int STATUS_DONE = 0x0;
146
147    /**
148     * Indicates that the display list needs another drawing pass.
149     *
150     * @see HardwareCanvas#drawRenderNode(RenderNode, android.graphics.Rect, int)
151     */
152    public static final int STATUS_DRAW = 0x1;
153
154    /**
155     * Indicates that the display list needs to re-execute its GL functors.
156     *
157     * @see HardwareCanvas#drawRenderNode(RenderNode, android.graphics.Rect, int)
158     * @see HardwareCanvas#callDrawGLFunction(long)
159     */
160    public static final int STATUS_INVOKE = 0x2;
161
162    /**
163     * Indicates that the display list performed GL drawing operations.
164     *
165     * @see HardwareCanvas#drawRenderNode(RenderNode, android.graphics.Rect, int)
166     */
167    public static final int STATUS_DREW = 0x4;
168
169    private boolean mValid;
170    // Do not access directly unless you are ThreadedRenderer
171    final long mNativeRenderNode;
172    private final View mOwningView;
173
174    private RenderNode(String name, View owningView) {
175        mNativeRenderNode = nCreate(name);
176        mOwningView = owningView;
177    }
178
179    /**
180     * @see RenderNode#adopt(long)
181     */
182    private RenderNode(long nativePtr) {
183        mNativeRenderNode = nativePtr;
184        mOwningView = null;
185    }
186
187    /**
188     * Creates a new RenderNode that can be used to record batches of
189     * drawing operations, and store / apply render properties when drawn.
190     *
191     * @param name The name of the RenderNode, used for debugging purpose. May be null.
192     *
193     * @return A new RenderNode.
194     */
195    public static RenderNode create(String name, @Nullable View owningView) {
196        return new RenderNode(name, owningView);
197    }
198
199    /**
200     * Adopts an existing native render node.
201     *
202     * Note: This will *NOT* incRef() on the native object, however it will
203     * decRef() when it is destroyed. The caller should have already incRef'd it
204     */
205    public static RenderNode adopt(long nativePtr) {
206        return new RenderNode(nativePtr);
207    }
208
209
210    /**
211     * Starts recording a display list for the render node. All
212     * operations performed on the returned canvas are recorded and
213     * stored in this display list.
214     *
215     * Calling this method will mark the render node invalid until
216     * {@link #end(HardwareCanvas)} is called.
217     * Only valid render nodes can be replayed.
218     *
219     * @param width The width of the recording viewport
220     * @param height The height of the recording viewport
221     *
222     * @return A canvas to record drawing operations.
223     *
224     * @see #end(HardwareCanvas)
225     * @see #isValid()
226     */
227    public HardwareCanvas start(int width, int height) {
228        HardwareCanvas canvas = GLES20RecordingCanvas.obtain(this);
229        canvas.setViewport(width, height);
230        // The dirty rect should always be null for a display list
231        canvas.onPreDraw(null);
232        return canvas;
233    }
234
235    /**
236     * Ends the recording for this display list. A display list cannot be
237     * replayed if recording is not finished. Calling this method marks
238     * the display list valid and {@link #isValid()} will return true.
239     *
240     * @see #start(int, int)
241     * @see #isValid()
242     */
243    public void end(HardwareCanvas endCanvas) {
244        if (!(endCanvas instanceof GLES20RecordingCanvas)) {
245            throw new IllegalArgumentException("Passed an invalid canvas to end!");
246        }
247
248        GLES20RecordingCanvas canvas = (GLES20RecordingCanvas) endCanvas;
249        canvas.onPostDraw();
250        long renderNodeData = canvas.finishRecording();
251        nSetDisplayListData(mNativeRenderNode, renderNodeData);
252        canvas.recycle();
253        mValid = true;
254    }
255
256    /**
257     * Reset native resources. This is called when cleaning up the state of display lists
258     * during destruction of hardware resources, to ensure that we do not hold onto
259     * obsolete resources after related resources are gone.
260     */
261    public void destroyDisplayListData() {
262        if (!mValid) return;
263
264        nSetDisplayListData(mNativeRenderNode, 0);
265        mValid = false;
266    }
267
268    /**
269     * Returns whether the RenderNode's display list content is currently usable.
270     * If this returns false, the display list should be re-recorded prior to replaying it.
271     *
272     * @return boolean true if the display list is able to be replayed, false otherwise.
273     */
274    public boolean isValid() { return mValid; }
275
276    long getNativeDisplayList() {
277        if (!mValid) {
278            throw new IllegalStateException("The display list is not valid.");
279        }
280        return mNativeRenderNode;
281    }
282
283    ///////////////////////////////////////////////////////////////////////////
284    // Matrix manipulation
285    ///////////////////////////////////////////////////////////////////////////
286
287    public boolean hasIdentityMatrix() {
288        return nHasIdentityMatrix(mNativeRenderNode);
289    }
290
291    public void getMatrix(@NonNull Matrix outMatrix) {
292        nGetTransformMatrix(mNativeRenderNode, outMatrix.native_instance);
293    }
294
295    public void getInverseMatrix(@NonNull Matrix outMatrix) {
296        nGetInverseTransformMatrix(mNativeRenderNode, outMatrix.native_instance);
297    }
298
299    ///////////////////////////////////////////////////////////////////////////
300    // RenderProperty Setters
301    ///////////////////////////////////////////////////////////////////////////
302
303    public boolean setLayerType(int layerType) {
304        return nSetLayerType(mNativeRenderNode, layerType);
305    }
306
307    public boolean setLayerPaint(Paint paint) {
308        return nSetLayerPaint(mNativeRenderNode, paint != null ? paint.mNativePaint : 0);
309    }
310
311    public boolean setClipBounds(@Nullable Rect rect) {
312        if (rect == null) {
313            return nSetClipBoundsEmpty(mNativeRenderNode);
314        } else {
315            return nSetClipBounds(mNativeRenderNode, rect.left, rect.top, rect.right, rect.bottom);
316        }
317    }
318
319    /**
320     * Set whether the Render node should clip itself to its bounds. This property is controlled by
321     * the view's parent.
322     *
323     * @param clipToBounds true if the display list should clip to its bounds
324     */
325    public boolean setClipToBounds(boolean clipToBounds) {
326        return nSetClipToBounds(mNativeRenderNode, clipToBounds);
327    }
328
329    /**
330     * Sets whether the display list should be drawn immediately after the
331     * closest ancestor display list containing a projection receiver.
332     *
333     * @param shouldProject true if the display list should be projected onto a
334     *            containing volume.
335     */
336    public boolean setProjectBackwards(boolean shouldProject) {
337        return nSetProjectBackwards(mNativeRenderNode, shouldProject);
338    }
339
340    /**
341     * Sets whether the display list is a projection receiver - that its parent
342     * DisplayList should draw any descendent DisplayLists with
343     * ProjectBackwards=true directly on top of it. Default value is false.
344     */
345    public boolean setProjectionReceiver(boolean shouldRecieve) {
346        return nSetProjectionReceiver(mNativeRenderNode, shouldRecieve);
347    }
348
349    /**
350     * Sets the outline, defining the shape that casts a shadow, and the path to
351     * be clipped if setClipToOutline is set.
352     *
353     * Deep copies the data into native to simplify reference ownership.
354     */
355    public boolean setOutline(Outline outline) {
356        if (outline == null) {
357            return nSetOutlineNone(mNativeRenderNode);
358        } else if (outline.isEmpty()) {
359            return nSetOutlineEmpty(mNativeRenderNode);
360        } else if (outline.mRect != null) {
361            return nSetOutlineRoundRect(mNativeRenderNode, outline.mRect.left, outline.mRect.top,
362                    outline.mRect.right, outline.mRect.bottom, outline.mRadius, outline.mAlpha);
363        } else if (outline.mPath != null) {
364            return nSetOutlineConvexPath(mNativeRenderNode, outline.mPath.mNativePath,
365                    outline.mAlpha);
366        }
367        throw new IllegalArgumentException("Unrecognized outline?");
368    }
369
370    public boolean hasShadow() {
371        return nHasShadow(mNativeRenderNode);
372    }
373
374    /**
375     * Enables or disables clipping to the outline.
376     *
377     * @param clipToOutline true if clipping to the outline.
378     */
379    public boolean setClipToOutline(boolean clipToOutline) {
380        return nSetClipToOutline(mNativeRenderNode, clipToOutline);
381    }
382
383    public boolean getClipToOutline() {
384        return nGetClipToOutline(mNativeRenderNode);
385    }
386
387    /**
388     * Controls the RenderNode's circular reveal clip.
389     */
390    public boolean setRevealClip(boolean shouldClip,
391            float x, float y, float radius) {
392        return nSetRevealClip(mNativeRenderNode, shouldClip, x, y, radius);
393    }
394
395    /**
396     * Set the static matrix on the display list. The specified matrix is combined with other
397     * transforms (such as {@link #setScaleX(float)}, {@link #setRotation(float)}, etc.)
398     *
399     * @param matrix A transform matrix to apply to this display list
400     */
401    public boolean setStaticMatrix(Matrix matrix) {
402        return nSetStaticMatrix(mNativeRenderNode, matrix.native_instance);
403    }
404
405    /**
406     * Set the Animation matrix on the display list. This matrix exists if an Animation is
407     * currently playing on a View, and is set on the display list during at draw() time. When
408     * the Animation finishes, the matrix should be cleared by sending <code>null</code>
409     * for the matrix parameter.
410     *
411     * @param matrix The matrix, null indicates that the matrix should be cleared.
412     */
413    public boolean setAnimationMatrix(Matrix matrix) {
414        return nSetAnimationMatrix(mNativeRenderNode,
415                (matrix != null) ? matrix.native_instance : 0);
416    }
417
418    /**
419     * Sets the translucency level for the display list.
420     *
421     * @param alpha The translucency of the display list, must be a value between 0.0f and 1.0f
422     *
423     * @see View#setAlpha(float)
424     * @see #getAlpha()
425     */
426    public boolean setAlpha(float alpha) {
427        return nSetAlpha(mNativeRenderNode, alpha);
428    }
429
430    /**
431     * Returns the translucency level of this display list.
432     *
433     * @return A value between 0.0f and 1.0f
434     *
435     * @see #setAlpha(float)
436     */
437    public float getAlpha() {
438        return nGetAlpha(mNativeRenderNode);
439    }
440
441    /**
442     * Sets whether the display list renders content which overlaps. Non-overlapping rendering
443     * can use a fast path for alpha that avoids rendering to an offscreen buffer. By default
444     * display lists consider they do not have overlapping content.
445     *
446     * @param hasOverlappingRendering False if the content is guaranteed to be non-overlapping,
447     *                                true otherwise.
448     *
449     * @see android.view.View#hasOverlappingRendering()
450     * @see #hasOverlappingRendering()
451     */
452    public boolean setHasOverlappingRendering(boolean hasOverlappingRendering) {
453        return nSetHasOverlappingRendering(mNativeRenderNode, hasOverlappingRendering);
454    }
455
456    /**
457     * Indicates whether the content of this display list overlaps.
458     *
459     * @return True if this display list renders content which overlaps, false otherwise.
460     *
461     * @see #setHasOverlappingRendering(boolean)
462     */
463    public boolean hasOverlappingRendering() {
464        //noinspection SimplifiableIfStatement
465        return nHasOverlappingRendering(mNativeRenderNode);
466    }
467
468    public boolean setElevation(float lift) {
469        return nSetElevation(mNativeRenderNode, lift);
470    }
471
472    public float getElevation() {
473        return nGetElevation(mNativeRenderNode);
474    }
475
476    /**
477     * Sets the translation value for the display list on the X axis.
478     *
479     * @param translationX The X axis translation value of the display list, in pixels
480     *
481     * @see View#setTranslationX(float)
482     * @see #getTranslationX()
483     */
484    public boolean setTranslationX(float translationX) {
485        return nSetTranslationX(mNativeRenderNode, translationX);
486    }
487
488    /**
489     * Returns the translation value for this display list on the X axis, in pixels.
490     *
491     * @see #setTranslationX(float)
492     */
493    public float getTranslationX() {
494        return nGetTranslationX(mNativeRenderNode);
495    }
496
497    /**
498     * Sets the translation value for the display list on the Y axis.
499     *
500     * @param translationY The Y axis translation value of the display list, in pixels
501     *
502     * @see View#setTranslationY(float)
503     * @see #getTranslationY()
504     */
505    public boolean setTranslationY(float translationY) {
506        return nSetTranslationY(mNativeRenderNode, translationY);
507    }
508
509    /**
510     * Returns the translation value for this display list on the Y axis, in pixels.
511     *
512     * @see #setTranslationY(float)
513     */
514    public float getTranslationY() {
515        return nGetTranslationY(mNativeRenderNode);
516    }
517
518    /**
519     * Sets the translation value for the display list on the Z axis.
520     *
521     * @see View#setTranslationZ(float)
522     * @see #getTranslationZ()
523     */
524    public boolean setTranslationZ(float translationZ) {
525        return nSetTranslationZ(mNativeRenderNode, translationZ);
526    }
527
528    /**
529     * Returns the translation value for this display list on the Z axis.
530     *
531     * @see #setTranslationZ(float)
532     */
533    public float getTranslationZ() {
534        return nGetTranslationZ(mNativeRenderNode);
535    }
536
537    /**
538     * Sets the rotation value for the display list around the Z axis.
539     *
540     * @param rotation The rotation value of the display list, in degrees
541     *
542     * @see View#setRotation(float)
543     * @see #getRotation()
544     */
545    public boolean setRotation(float rotation) {
546        return nSetRotation(mNativeRenderNode, rotation);
547    }
548
549    /**
550     * Returns the rotation value for this display list around the Z axis, in degrees.
551     *
552     * @see #setRotation(float)
553     */
554    public float getRotation() {
555        return nGetRotation(mNativeRenderNode);
556    }
557
558    /**
559     * Sets the rotation value for the display list around the X axis.
560     *
561     * @param rotationX The rotation value of the display list, in degrees
562     *
563     * @see View#setRotationX(float)
564     * @see #getRotationX()
565     */
566    public boolean setRotationX(float rotationX) {
567        return nSetRotationX(mNativeRenderNode, rotationX);
568    }
569
570    /**
571     * Returns the rotation value for this display list around the X axis, in degrees.
572     *
573     * @see #setRotationX(float)
574     */
575    public float getRotationX() {
576        return nGetRotationX(mNativeRenderNode);
577    }
578
579    /**
580     * Sets the rotation value for the display list around the Y axis.
581     *
582     * @param rotationY The rotation value of the display list, in degrees
583     *
584     * @see View#setRotationY(float)
585     * @see #getRotationY()
586     */
587    public boolean setRotationY(float rotationY) {
588        return nSetRotationY(mNativeRenderNode, rotationY);
589    }
590
591    /**
592     * Returns the rotation value for this display list around the Y axis, in degrees.
593     *
594     * @see #setRotationY(float)
595     */
596    public float getRotationY() {
597        return nGetRotationY(mNativeRenderNode);
598    }
599
600    /**
601     * Sets the scale value for the display list on the X axis.
602     *
603     * @param scaleX The scale value of the display list
604     *
605     * @see View#setScaleX(float)
606     * @see #getScaleX()
607     */
608    public boolean setScaleX(float scaleX) {
609        return nSetScaleX(mNativeRenderNode, scaleX);
610    }
611
612    /**
613     * Returns the scale value for this display list on the X axis.
614     *
615     * @see #setScaleX(float)
616     */
617    public float getScaleX() {
618        return nGetScaleX(mNativeRenderNode);
619    }
620
621    /**
622     * Sets the scale value for the display list on the Y axis.
623     *
624     * @param scaleY The scale value of the display list
625     *
626     * @see View#setScaleY(float)
627     * @see #getScaleY()
628     */
629    public boolean setScaleY(float scaleY) {
630        return nSetScaleY(mNativeRenderNode, scaleY);
631    }
632
633    /**
634     * Returns the scale value for this display list on the Y axis.
635     *
636     * @see #setScaleY(float)
637     */
638    public float getScaleY() {
639        return nGetScaleY(mNativeRenderNode);
640    }
641
642    /**
643     * Sets the pivot value for the display list on the X axis
644     *
645     * @param pivotX The pivot value of the display list on the X axis, in pixels
646     *
647     * @see View#setPivotX(float)
648     * @see #getPivotX()
649     */
650    public boolean setPivotX(float pivotX) {
651        return nSetPivotX(mNativeRenderNode, pivotX);
652    }
653
654    /**
655     * Returns the pivot value for this display list on the X axis, in pixels.
656     *
657     * @see #setPivotX(float)
658     */
659    public float getPivotX() {
660        return nGetPivotX(mNativeRenderNode);
661    }
662
663    /**
664     * Sets the pivot value for the display list on the Y axis
665     *
666     * @param pivotY The pivot value of the display list on the Y axis, in pixels
667     *
668     * @see View#setPivotY(float)
669     * @see #getPivotY()
670     */
671    public boolean setPivotY(float pivotY) {
672        return nSetPivotY(mNativeRenderNode, pivotY);
673    }
674
675    /**
676     * Returns the pivot value for this display list on the Y axis, in pixels.
677     *
678     * @see #setPivotY(float)
679     */
680    public float getPivotY() {
681        return nGetPivotY(mNativeRenderNode);
682    }
683
684    public boolean isPivotExplicitlySet() {
685        return nIsPivotExplicitlySet(mNativeRenderNode);
686    }
687
688    /**
689     * Sets the camera distance for the display list. Refer to
690     * {@link View#setCameraDistance(float)} for more information on how to
691     * use this property.
692     *
693     * @param distance The distance in Z of the camera of the display list
694     *
695     * @see View#setCameraDistance(float)
696     * @see #getCameraDistance()
697     */
698    public boolean setCameraDistance(float distance) {
699        return nSetCameraDistance(mNativeRenderNode, distance);
700    }
701
702    /**
703     * Returns the distance in Z of the camera of the display list.
704     *
705     * @see #setCameraDistance(float)
706     */
707    public float getCameraDistance() {
708        return nGetCameraDistance(mNativeRenderNode);
709    }
710
711    /**
712     * Sets the left position for the display list.
713     *
714     * @param left The left position, in pixels, of the display list
715     *
716     * @see View#setLeft(int)
717     */
718    public boolean setLeft(int left) {
719        return nSetLeft(mNativeRenderNode, left);
720    }
721
722    /**
723     * Sets the top position for the display list.
724     *
725     * @param top The top position, in pixels, of the display list
726     *
727     * @see View#setTop(int)
728     */
729    public boolean setTop(int top) {
730        return nSetTop(mNativeRenderNode, top);
731    }
732
733    /**
734     * Sets the right position for the display list.
735     *
736     * @param right The right position, in pixels, of the display list
737     *
738     * @see View#setRight(int)
739     */
740    public boolean setRight(int right) {
741        return nSetRight(mNativeRenderNode, right);
742    }
743
744    /**
745     * Sets the bottom position for the display list.
746     *
747     * @param bottom The bottom position, in pixels, of the display list
748     *
749     * @see View#setBottom(int)
750     */
751    public boolean setBottom(int bottom) {
752        return nSetBottom(mNativeRenderNode, bottom);
753    }
754
755    /**
756     * Sets the left and top positions for the display list
757     *
758     * @param left The left position of the display list, in pixels
759     * @param top The top position of the display list, in pixels
760     * @param right The right position of the display list, in pixels
761     * @param bottom The bottom position of the display list, in pixels
762     *
763     * @see View#setLeft(int)
764     * @see View#setTop(int)
765     * @see View#setRight(int)
766     * @see View#setBottom(int)
767     */
768    public boolean setLeftTopRightBottom(int left, int top, int right, int bottom) {
769        return nSetLeftTopRightBottom(mNativeRenderNode, left, top, right, bottom);
770    }
771
772    /**
773     * Offsets the left and right positions for the display list
774     *
775     * @param offset The amount that the left and right positions of the display
776     *               list are offset, in pixels
777     *
778     * @see View#offsetLeftAndRight(int)
779     */
780    public boolean offsetLeftAndRight(int offset) {
781        return nOffsetLeftAndRight(mNativeRenderNode, offset);
782    }
783
784    /**
785     * Offsets the top and bottom values for the display list
786     *
787     * @param offset The amount that the top and bottom positions of the display
788     *               list are offset, in pixels
789     *
790     * @see View#offsetTopAndBottom(int)
791     */
792    public boolean offsetTopAndBottom(int offset) {
793        return nOffsetTopAndBottom(mNativeRenderNode, offset);
794    }
795
796    /**
797     * Outputs the display list to the log. This method exists for use by
798     * tools to output display lists for selected nodes to the log.
799     */
800    public void output() {
801        nOutput(mNativeRenderNode);
802    }
803
804    /**
805     * Gets the size of the DisplayList for debug purposes.
806     */
807    public int getDebugSize() {
808        return nGetDebugSize(mNativeRenderNode);
809    }
810
811    ///////////////////////////////////////////////////////////////////////////
812    // Animations
813    ///////////////////////////////////////////////////////////////////////////
814
815    public void addAnimator(RenderNodeAnimator animator) {
816        if (mOwningView == null || mOwningView.mAttachInfo == null) {
817            throw new IllegalStateException("Cannot start this animator on a detached view!");
818        }
819        nAddAnimator(mNativeRenderNode, animator.getNativeAnimator());
820        mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this);
821    }
822
823    public void endAllAnimators() {
824        nEndAllAnimators(mNativeRenderNode);
825    }
826
827    ///////////////////////////////////////////////////////////////////////////
828    // Native methods
829    ///////////////////////////////////////////////////////////////////////////
830
831    private static native long nCreate(String name);
832    private static native void nDestroyRenderNode(long renderNode);
833    private static native void nSetDisplayListData(long renderNode, long newData);
834
835    // Matrix
836
837    private static native void nGetTransformMatrix(long renderNode, long nativeMatrix);
838    private static native void nGetInverseTransformMatrix(long renderNode, long nativeMatrix);
839    private static native boolean nHasIdentityMatrix(long renderNode);
840
841    // Properties
842
843    private static native boolean nOffsetTopAndBottom(long renderNode, int offset);
844    private static native boolean nOffsetLeftAndRight(long renderNode, int offset);
845    private static native boolean nSetLeftTopRightBottom(long renderNode, int left, int top,
846            int right, int bottom);
847    private static native boolean nSetBottom(long renderNode, int bottom);
848    private static native boolean nSetRight(long renderNode, int right);
849    private static native boolean nSetTop(long renderNode, int top);
850    private static native boolean nSetLeft(long renderNode, int left);
851    private static native boolean nSetCameraDistance(long renderNode, float distance);
852    private static native boolean nSetPivotY(long renderNode, float pivotY);
853    private static native boolean nSetPivotX(long renderNode, float pivotX);
854    private static native boolean nSetLayerType(long renderNode, int layerType);
855    private static native boolean nSetLayerPaint(long renderNode, long paint);
856    private static native boolean nSetClipToBounds(long renderNode, boolean clipToBounds);
857    private static native boolean nSetClipBounds(long renderNode, int left, int top,
858            int right, int bottom);
859    private static native boolean nSetClipBoundsEmpty(long renderNode);
860    private static native boolean nSetProjectBackwards(long renderNode, boolean shouldProject);
861    private static native boolean nSetProjectionReceiver(long renderNode, boolean shouldRecieve);
862    private static native boolean nSetOutlineRoundRect(long renderNode, int left, int top,
863            int right, int bottom, float radius, float alpha);
864    private static native boolean nSetOutlineConvexPath(long renderNode, long nativePath,
865            float alpha);
866    private static native boolean nSetOutlineEmpty(long renderNode);
867    private static native boolean nSetOutlineNone(long renderNode);
868    private static native boolean nHasShadow(long renderNode);
869    private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline);
870    private static native boolean nSetRevealClip(long renderNode,
871            boolean shouldClip, float x, float y, float radius);
872    private static native boolean nSetAlpha(long renderNode, float alpha);
873    private static native boolean nSetHasOverlappingRendering(long renderNode,
874            boolean hasOverlappingRendering);
875    private static native boolean nSetElevation(long renderNode, float lift);
876    private static native boolean nSetTranslationX(long renderNode, float translationX);
877    private static native boolean nSetTranslationY(long renderNode, float translationY);
878    private static native boolean nSetTranslationZ(long renderNode, float translationZ);
879    private static native boolean nSetRotation(long renderNode, float rotation);
880    private static native boolean nSetRotationX(long renderNode, float rotationX);
881    private static native boolean nSetRotationY(long renderNode, float rotationY);
882    private static native boolean nSetScaleX(long renderNode, float scaleX);
883    private static native boolean nSetScaleY(long renderNode, float scaleY);
884    private static native boolean nSetStaticMatrix(long renderNode, long nativeMatrix);
885    private static native boolean nSetAnimationMatrix(long renderNode, long animationMatrix);
886
887    private static native boolean nHasOverlappingRendering(long renderNode);
888    private static native boolean nGetClipToOutline(long renderNode);
889    private static native float nGetAlpha(long renderNode);
890    private static native float nGetCameraDistance(long renderNode);
891    private static native float nGetScaleX(long renderNode);
892    private static native float nGetScaleY(long renderNode);
893    private static native float nGetElevation(long renderNode);
894    private static native float nGetTranslationX(long renderNode);
895    private static native float nGetTranslationY(long renderNode);
896    private static native float nGetTranslationZ(long renderNode);
897    private static native float nGetRotation(long renderNode);
898    private static native float nGetRotationX(long renderNode);
899    private static native float nGetRotationY(long renderNode);
900    private static native boolean nIsPivotExplicitlySet(long renderNode);
901    private static native float nGetPivotX(long renderNode);
902    private static native float nGetPivotY(long renderNode);
903    private static native void nOutput(long renderNode);
904    private static native int nGetDebugSize(long renderNode);
905
906    ///////////////////////////////////////////////////////////////////////////
907    // Animations
908    ///////////////////////////////////////////////////////////////////////////
909
910    private static native void nAddAnimator(long renderNode, long animatorPtr);
911    private static native void nEndAllAnimators(long renderNode);
912
913    ///////////////////////////////////////////////////////////////////////////
914    // Finalization
915    ///////////////////////////////////////////////////////////////////////////
916
917    @Override
918    protected void finalize() throws Throwable {
919        try {
920            nDestroyRenderNode(mNativeRenderNode);
921        } finally {
922            super.finalize();
923        }
924    }
925}
926