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