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