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