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