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    /**
357     * Enables or disables clipping to the outline.
358     *
359     * @param clipToOutline true if clipping to the outline.
360     */
361    public boolean setClipToOutline(boolean clipToOutline) {
362        return nSetClipToOutline(mNativeRenderNode, clipToOutline);
363    }
364
365    public boolean getClipToOutline() {
366        return nGetClipToOutline(mNativeRenderNode);
367    }
368
369    /**
370     * Controls the RenderNode's circular reveal clip.
371     */
372    public boolean setRevealClip(boolean shouldClip,
373            float x, float y, float radius) {
374        return nSetRevealClip(mNativeRenderNode, shouldClip, x, y, radius);
375    }
376
377    /**
378     * Set the static matrix on the display list. The specified matrix is combined with other
379     * transforms (such as {@link #setScaleX(float)}, {@link #setRotation(float)}, etc.)
380     *
381     * @param matrix A transform matrix to apply to this display list
382     */
383    public boolean setStaticMatrix(Matrix matrix) {
384        return nSetStaticMatrix(mNativeRenderNode, matrix.native_instance);
385    }
386
387    /**
388     * Set the Animation matrix on the display list. This matrix exists if an Animation is
389     * currently playing on a View, and is set on the display list during at draw() time. When
390     * the Animation finishes, the matrix should be cleared by sending <code>null</code>
391     * for the matrix parameter.
392     *
393     * @param matrix The matrix, null indicates that the matrix should be cleared.
394     */
395    public boolean setAnimationMatrix(Matrix matrix) {
396        return nSetAnimationMatrix(mNativeRenderNode,
397                (matrix != null) ? matrix.native_instance : 0);
398    }
399
400    /**
401     * Sets the translucency level for the display list.
402     *
403     * @param alpha The translucency of the display list, must be a value between 0.0f and 1.0f
404     *
405     * @see View#setAlpha(float)
406     * @see #getAlpha()
407     */
408    public boolean setAlpha(float alpha) {
409        return nSetAlpha(mNativeRenderNode, alpha);
410    }
411
412    /**
413     * Returns the translucency level of this display list.
414     *
415     * @return A value between 0.0f and 1.0f
416     *
417     * @see #setAlpha(float)
418     */
419    public float getAlpha() {
420        return nGetAlpha(mNativeRenderNode);
421    }
422
423    /**
424     * Sets whether the display list renders content which overlaps. Non-overlapping rendering
425     * can use a fast path for alpha that avoids rendering to an offscreen buffer. By default
426     * display lists consider they do not have overlapping content.
427     *
428     * @param hasOverlappingRendering False if the content is guaranteed to be non-overlapping,
429     *                                true otherwise.
430     *
431     * @see android.view.View#hasOverlappingRendering()
432     * @see #hasOverlappingRendering()
433     */
434    public boolean setHasOverlappingRendering(boolean hasOverlappingRendering) {
435        return nSetHasOverlappingRendering(mNativeRenderNode, hasOverlappingRendering);
436    }
437
438    /**
439     * Indicates whether the content of this display list overlaps.
440     *
441     * @return True if this display list renders content which overlaps, false otherwise.
442     *
443     * @see #setHasOverlappingRendering(boolean)
444     */
445    public boolean hasOverlappingRendering() {
446        //noinspection SimplifiableIfStatement
447        return nHasOverlappingRendering(mNativeRenderNode);
448    }
449
450    public boolean setElevation(float lift) {
451        return nSetElevation(mNativeRenderNode, lift);
452    }
453
454    public float getElevation() {
455        return nGetElevation(mNativeRenderNode);
456    }
457
458    /**
459     * Sets the translation value for the display list on the X axis.
460     *
461     * @param translationX The X axis translation value of the display list, in pixels
462     *
463     * @see View#setTranslationX(float)
464     * @see #getTranslationX()
465     */
466    public boolean setTranslationX(float translationX) {
467        return nSetTranslationX(mNativeRenderNode, translationX);
468    }
469
470    /**
471     * Returns the translation value for this display list on the X axis, in pixels.
472     *
473     * @see #setTranslationX(float)
474     */
475    public float getTranslationX() {
476        return nGetTranslationX(mNativeRenderNode);
477    }
478
479    /**
480     * Sets the translation value for the display list on the Y axis.
481     *
482     * @param translationY The Y axis translation value of the display list, in pixels
483     *
484     * @see View#setTranslationY(float)
485     * @see #getTranslationY()
486     */
487    public boolean setTranslationY(float translationY) {
488        return nSetTranslationY(mNativeRenderNode, translationY);
489    }
490
491    /**
492     * Returns the translation value for this display list on the Y axis, in pixels.
493     *
494     * @see #setTranslationY(float)
495     */
496    public float getTranslationY() {
497        return nGetTranslationY(mNativeRenderNode);
498    }
499
500    /**
501     * Sets the translation value for the display list on the Z axis.
502     *
503     * @see View#setTranslationZ(float)
504     * @see #getTranslationZ()
505     */
506    public boolean setTranslationZ(float translationZ) {
507        return nSetTranslationZ(mNativeRenderNode, translationZ);
508    }
509
510    /**
511     * Returns the translation value for this display list on the Z axis.
512     *
513     * @see #setTranslationZ(float)
514     */
515    public float getTranslationZ() {
516        return nGetTranslationZ(mNativeRenderNode);
517    }
518
519    /**
520     * Sets the rotation value for the display list around the Z axis.
521     *
522     * @param rotation The rotation value of the display list, in degrees
523     *
524     * @see View#setRotation(float)
525     * @see #getRotation()
526     */
527    public boolean setRotation(float rotation) {
528        return nSetRotation(mNativeRenderNode, rotation);
529    }
530
531    /**
532     * Returns the rotation value for this display list around the Z axis, in degrees.
533     *
534     * @see #setRotation(float)
535     */
536    public float getRotation() {
537        return nGetRotation(mNativeRenderNode);
538    }
539
540    /**
541     * Sets the rotation value for the display list around the X axis.
542     *
543     * @param rotationX The rotation value of the display list, in degrees
544     *
545     * @see View#setRotationX(float)
546     * @see #getRotationX()
547     */
548    public boolean setRotationX(float rotationX) {
549        return nSetRotationX(mNativeRenderNode, rotationX);
550    }
551
552    /**
553     * Returns the rotation value for this display list around the X axis, in degrees.
554     *
555     * @see #setRotationX(float)
556     */
557    public float getRotationX() {
558        return nGetRotationX(mNativeRenderNode);
559    }
560
561    /**
562     * Sets the rotation value for the display list around the Y axis.
563     *
564     * @param rotationY The rotation value of the display list, in degrees
565     *
566     * @see View#setRotationY(float)
567     * @see #getRotationY()
568     */
569    public boolean setRotationY(float rotationY) {
570        return nSetRotationY(mNativeRenderNode, rotationY);
571    }
572
573    /**
574     * Returns the rotation value for this display list around the Y axis, in degrees.
575     *
576     * @see #setRotationY(float)
577     */
578    public float getRotationY() {
579        return nGetRotationY(mNativeRenderNode);
580    }
581
582    /**
583     * Sets the scale value for the display list on the X axis.
584     *
585     * @param scaleX The scale value of the display list
586     *
587     * @see View#setScaleX(float)
588     * @see #getScaleX()
589     */
590    public boolean setScaleX(float scaleX) {
591        return nSetScaleX(mNativeRenderNode, scaleX);
592    }
593
594    /**
595     * Returns the scale value for this display list on the X axis.
596     *
597     * @see #setScaleX(float)
598     */
599    public float getScaleX() {
600        return nGetScaleX(mNativeRenderNode);
601    }
602
603    /**
604     * Sets the scale value for the display list on the Y axis.
605     *
606     * @param scaleY The scale value of the display list
607     *
608     * @see View#setScaleY(float)
609     * @see #getScaleY()
610     */
611    public boolean setScaleY(float scaleY) {
612        return nSetScaleY(mNativeRenderNode, scaleY);
613    }
614
615    /**
616     * Returns the scale value for this display list on the Y axis.
617     *
618     * @see #setScaleY(float)
619     */
620    public float getScaleY() {
621        return nGetScaleY(mNativeRenderNode);
622    }
623
624    /**
625     * Sets the pivot value for the display list on the X axis
626     *
627     * @param pivotX The pivot value of the display list on the X axis, in pixels
628     *
629     * @see View#setPivotX(float)
630     * @see #getPivotX()
631     */
632    public boolean setPivotX(float pivotX) {
633        return nSetPivotX(mNativeRenderNode, pivotX);
634    }
635
636    /**
637     * Returns the pivot value for this display list on the X axis, in pixels.
638     *
639     * @see #setPivotX(float)
640     */
641    public float getPivotX() {
642        return nGetPivotX(mNativeRenderNode);
643    }
644
645    /**
646     * Sets the pivot value for the display list on the Y axis
647     *
648     * @param pivotY The pivot value of the display list on the Y axis, in pixels
649     *
650     * @see View#setPivotY(float)
651     * @see #getPivotY()
652     */
653    public boolean setPivotY(float pivotY) {
654        return nSetPivotY(mNativeRenderNode, pivotY);
655    }
656
657    /**
658     * Returns the pivot value for this display list on the Y axis, in pixels.
659     *
660     * @see #setPivotY(float)
661     */
662    public float getPivotY() {
663        return nGetPivotY(mNativeRenderNode);
664    }
665
666    public boolean isPivotExplicitlySet() {
667        return nIsPivotExplicitlySet(mNativeRenderNode);
668    }
669
670    /**
671     * Sets the camera distance for the display list. Refer to
672     * {@link View#setCameraDistance(float)} for more information on how to
673     * use this property.
674     *
675     * @param distance The distance in Z of the camera of the display list
676     *
677     * @see View#setCameraDistance(float)
678     * @see #getCameraDistance()
679     */
680    public boolean setCameraDistance(float distance) {
681        return nSetCameraDistance(mNativeRenderNode, distance);
682    }
683
684    /**
685     * Returns the distance in Z of the camera of the display list.
686     *
687     * @see #setCameraDistance(float)
688     */
689    public float getCameraDistance() {
690        return nGetCameraDistance(mNativeRenderNode);
691    }
692
693    /**
694     * Sets the left position for the display list.
695     *
696     * @param left The left position, in pixels, of the display list
697     *
698     * @see View#setLeft(int)
699     */
700    public boolean setLeft(int left) {
701        return nSetLeft(mNativeRenderNode, left);
702    }
703
704    /**
705     * Sets the top position for the display list.
706     *
707     * @param top The top position, in pixels, of the display list
708     *
709     * @see View#setTop(int)
710     */
711    public boolean setTop(int top) {
712        return nSetTop(mNativeRenderNode, top);
713    }
714
715    /**
716     * Sets the right position for the display list.
717     *
718     * @param right The right position, in pixels, of the display list
719     *
720     * @see View#setRight(int)
721     */
722    public boolean setRight(int right) {
723        return nSetRight(mNativeRenderNode, right);
724    }
725
726    /**
727     * Sets the bottom position for the display list.
728     *
729     * @param bottom The bottom position, in pixels, of the display list
730     *
731     * @see View#setBottom(int)
732     */
733    public boolean setBottom(int bottom) {
734        return nSetBottom(mNativeRenderNode, bottom);
735    }
736
737    /**
738     * Sets the left and top positions for the display list
739     *
740     * @param left The left position of the display list, in pixels
741     * @param top The top position of the display list, in pixels
742     * @param right The right position of the display list, in pixels
743     * @param bottom The bottom position of the display list, in pixels
744     *
745     * @see View#setLeft(int)
746     * @see View#setTop(int)
747     * @see View#setRight(int)
748     * @see View#setBottom(int)
749     */
750    public boolean setLeftTopRightBottom(int left, int top, int right, int bottom) {
751        return nSetLeftTopRightBottom(mNativeRenderNode, left, top, right, bottom);
752    }
753
754    /**
755     * Offsets the left and right positions for the display list
756     *
757     * @param offset The amount that the left and right positions of the display
758     *               list are offset, in pixels
759     *
760     * @see View#offsetLeftAndRight(int)
761     */
762    public boolean offsetLeftAndRight(int offset) {
763        return nOffsetLeftAndRight(mNativeRenderNode, offset);
764    }
765
766    /**
767     * Offsets the top and bottom values for the display list
768     *
769     * @param offset The amount that the top and bottom positions of the display
770     *               list are offset, in pixels
771     *
772     * @see View#offsetTopAndBottom(int)
773     */
774    public boolean offsetTopAndBottom(int offset) {
775        return nOffsetTopAndBottom(mNativeRenderNode, offset);
776    }
777
778    /**
779     * Outputs the display list to the log. This method exists for use by
780     * tools to output display lists for selected nodes to the log.
781     */
782    public void output() {
783        nOutput(mNativeRenderNode);
784    }
785
786    /**
787     * Gets the size of the DisplayList for debug purposes.
788     */
789    public int getDebugSize() {
790        return nGetDebugSize(mNativeRenderNode);
791    }
792
793    ///////////////////////////////////////////////////////////////////////////
794    // Animations
795    ///////////////////////////////////////////////////////////////////////////
796
797    public void addAnimator(RenderNodeAnimator animator) {
798        if (mOwningView == null || mOwningView.mAttachInfo == null) {
799            throw new IllegalStateException("Cannot start this animator on a detached view!");
800        }
801        nAddAnimator(mNativeRenderNode, animator.getNativeAnimator());
802        mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this);
803    }
804
805    public boolean isAttached() {
806        return mOwningView != null && mOwningView.mAttachInfo != null;
807    }
808
809    public void registerVectorDrawableAnimator(
810            AnimatedVectorDrawable.VectorDrawableAnimatorRT animatorSet) {
811        if (mOwningView == null || mOwningView.mAttachInfo == null) {
812            throw new IllegalStateException("Cannot start this animator on a detached view!");
813        }
814        mOwningView.mAttachInfo.mViewRootImpl.registerVectorDrawableAnimator(animatorSet);
815    }
816
817    public void endAllAnimators() {
818        nEndAllAnimators(mNativeRenderNode);
819    }
820
821    ///////////////////////////////////////////////////////////////////////////
822    // Regular JNI methods
823    ///////////////////////////////////////////////////////////////////////////
824
825    private static native long nCreate(String name);
826
827    private static native long nGetNativeFinalizer();
828    private static native void nOutput(long renderNode);
829    private static native int nGetDebugSize(long renderNode);
830    private static native void nRequestPositionUpdates(long renderNode, SurfaceView callback);
831
832    // Animations
833
834    private static native void nAddAnimator(long renderNode, long animatorPtr);
835    private static native void nEndAllAnimators(long renderNode);
836
837
838    ///////////////////////////////////////////////////////////////////////////
839    // @FastNative methods
840    ///////////////////////////////////////////////////////////////////////////
841
842    @FastNative
843    private static native void nSetDisplayList(long renderNode, long newData);
844
845
846    ///////////////////////////////////////////////////////////////////////////
847    // @CriticalNative methods
848    ///////////////////////////////////////////////////////////////////////////
849
850    @CriticalNative
851    private static native boolean nIsValid(long renderNode);
852
853    // Matrix
854
855    @CriticalNative
856    private static native void nGetTransformMatrix(long renderNode, long nativeMatrix);
857    @CriticalNative
858    private static native void nGetInverseTransformMatrix(long renderNode, long nativeMatrix);
859    @CriticalNative
860    private static native boolean nHasIdentityMatrix(long renderNode);
861
862    // Properties
863
864    @CriticalNative
865    private static native boolean nOffsetTopAndBottom(long renderNode, int offset);
866    @CriticalNative
867    private static native boolean nOffsetLeftAndRight(long renderNode, int offset);
868    @CriticalNative
869    private static native boolean nSetLeftTopRightBottom(long renderNode, int left, int top,
870            int right, int bottom);
871    @CriticalNative
872    private static native boolean nSetBottom(long renderNode, int bottom);
873    @CriticalNative
874    private static native boolean nSetRight(long renderNode, int right);
875    @CriticalNative
876    private static native boolean nSetTop(long renderNode, int top);
877    @CriticalNative
878    private static native boolean nSetLeft(long renderNode, int left);
879    @CriticalNative
880    private static native boolean nSetCameraDistance(long renderNode, float distance);
881    @CriticalNative
882    private static native boolean nSetPivotY(long renderNode, float pivotY);
883    @CriticalNative
884    private static native boolean nSetPivotX(long renderNode, float pivotX);
885    @CriticalNative
886    private static native boolean nSetLayerType(long renderNode, int layerType);
887    @CriticalNative
888    private static native boolean nSetLayerPaint(long renderNode, long paint);
889    @CriticalNative
890    private static native boolean nSetClipToBounds(long renderNode, boolean clipToBounds);
891    @CriticalNative
892    private static native boolean nSetClipBounds(long renderNode, int left, int top,
893            int right, int bottom);
894    @CriticalNative
895    private static native boolean nSetClipBoundsEmpty(long renderNode);
896    @CriticalNative
897    private static native boolean nSetProjectBackwards(long renderNode, boolean shouldProject);
898    @CriticalNative
899    private static native boolean nSetProjectionReceiver(long renderNode, boolean shouldRecieve);
900    @CriticalNative
901    private static native boolean nSetOutlineRoundRect(long renderNode, int left, int top,
902            int right, int bottom, float radius, float alpha);
903    @CriticalNative
904    private static native boolean nSetOutlineConvexPath(long renderNode, long nativePath,
905            float alpha);
906    @CriticalNative
907    private static native boolean nSetOutlineEmpty(long renderNode);
908    @CriticalNative
909    private static native boolean nSetOutlineNone(long renderNode);
910    @CriticalNative
911    private static native boolean nHasShadow(long renderNode);
912    @CriticalNative
913    private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline);
914    @CriticalNative
915    private static native boolean nSetRevealClip(long renderNode,
916            boolean shouldClip, float x, float y, float radius);
917    @CriticalNative
918    private static native boolean nSetAlpha(long renderNode, float alpha);
919    @CriticalNative
920    private static native boolean nSetHasOverlappingRendering(long renderNode,
921            boolean hasOverlappingRendering);
922    @CriticalNative
923    private static native boolean nSetElevation(long renderNode, float lift);
924    @CriticalNative
925    private static native boolean nSetTranslationX(long renderNode, float translationX);
926    @CriticalNative
927    private static native boolean nSetTranslationY(long renderNode, float translationY);
928    @CriticalNative
929    private static native boolean nSetTranslationZ(long renderNode, float translationZ);
930    @CriticalNative
931    private static native boolean nSetRotation(long renderNode, float rotation);
932    @CriticalNative
933    private static native boolean nSetRotationX(long renderNode, float rotationX);
934    @CriticalNative
935    private static native boolean nSetRotationY(long renderNode, float rotationY);
936    @CriticalNative
937    private static native boolean nSetScaleX(long renderNode, float scaleX);
938    @CriticalNative
939    private static native boolean nSetScaleY(long renderNode, float scaleY);
940    @CriticalNative
941    private static native boolean nSetStaticMatrix(long renderNode, long nativeMatrix);
942    @CriticalNative
943    private static native boolean nSetAnimationMatrix(long renderNode, long animationMatrix);
944
945    @CriticalNative
946    private static native boolean nHasOverlappingRendering(long renderNode);
947    @CriticalNative
948    private static native boolean nGetClipToOutline(long renderNode);
949    @CriticalNative
950    private static native float nGetAlpha(long renderNode);
951    @CriticalNative
952    private static native float nGetCameraDistance(long renderNode);
953    @CriticalNative
954    private static native float nGetScaleX(long renderNode);
955    @CriticalNative
956    private static native float nGetScaleY(long renderNode);
957    @CriticalNative
958    private static native float nGetElevation(long renderNode);
959    @CriticalNative
960    private static native float nGetTranslationX(long renderNode);
961    @CriticalNative
962    private static native float nGetTranslationY(long renderNode);
963    @CriticalNative
964    private static native float nGetTranslationZ(long renderNode);
965    @CriticalNative
966    private static native float nGetRotation(long renderNode);
967    @CriticalNative
968    private static native float nGetRotationX(long renderNode);
969    @CriticalNative
970    private static native float nGetRotationY(long renderNode);
971    @CriticalNative
972    private static native boolean nIsPivotExplicitlySet(long renderNode);
973    @CriticalNative
974    private static native float nGetPivotX(long renderNode);
975    @CriticalNative
976    private static native float nGetPivotY(long renderNode);
977}
978