Canvas.java revision bfa0b29883d56edfc2ec217962290d3c94f9fc2a
1/*
2 * Copyright (C) 2006 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.graphics;
18
19import android.annotation.ColorInt;
20import android.annotation.IntDef;
21import android.annotation.NonNull;
22import android.annotation.Nullable;
23import android.annotation.Size;
24
25import dalvik.annotation.optimization.CriticalNative;
26import dalvik.annotation.optimization.FastNative;
27
28import libcore.util.NativeAllocationRegistry;
29
30import java.lang.annotation.Retention;
31import java.lang.annotation.RetentionPolicy;
32
33import javax.microedition.khronos.opengles.GL;
34
35/**
36 * The Canvas class holds the "draw" calls. To draw something, you need
37 * 4 basic components: A Bitmap to hold the pixels, a Canvas to host
38 * the draw calls (writing into the bitmap), a drawing primitive (e.g. Rect,
39 * Path, text, Bitmap), and a paint (to describe the colors and styles for the
40 * drawing).
41 *
42 * <div class="special reference">
43 * <h3>Developer Guides</h3>
44 * <p>For more information about how to use Canvas, read the
45 * <a href="{@docRoot}guide/topics/graphics/2d-graphics.html">
46 * Canvas and Drawables</a> developer guide.</p></div>
47 */
48public class Canvas extends BaseCanvas {
49    /** @hide */
50    public static boolean sCompatibilityRestore = false;
51
52    /** @hide */
53    public long getNativeCanvasWrapper() {
54        return mNativeCanvasWrapper;
55    }
56
57    /** @hide */
58    public boolean isRecordingFor(Object o) { return false; }
59
60    // may be null
61    private Bitmap mBitmap;
62
63    // optional field set by the caller
64    private DrawFilter mDrawFilter;
65
66    // Maximum bitmap size as defined in Skia's native code
67    // (see SkCanvas.cpp, SkDraw.cpp)
68    private static final int MAXMIMUM_BITMAP_SIZE = 32766;
69
70    // The approximate size of the native allocation associated with
71    // a Canvas object.
72    private static final long NATIVE_ALLOCATION_SIZE = 525;
73
74    // Use a Holder to allow static initialization of Canvas in the boot image.
75    private static class NoImagePreloadHolder {
76        public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
77                Canvas.class.getClassLoader(), nGetNativeFinalizer(), NATIVE_ALLOCATION_SIZE);
78    }
79
80    // This field is used to finalize the native Canvas properly
81    private Runnable mFinalizer;
82
83    /**
84     * Construct an empty raster canvas. Use setBitmap() to specify a bitmap to
85     * draw into.  The initial target density is {@link Bitmap#DENSITY_NONE};
86     * this will typically be replaced when a target bitmap is set for the
87     * canvas.
88     */
89    public Canvas() {
90        if (!isHardwareAccelerated()) {
91            // 0 means no native bitmap
92            mNativeCanvasWrapper = nInitRaster(null);
93            mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
94                    this, mNativeCanvasWrapper);
95        } else {
96            mFinalizer = null;
97        }
98    }
99
100    /**
101     * Construct a canvas with the specified bitmap to draw into. The bitmap
102     * must be mutable.
103     *
104     * <p>The initial target density of the canvas is the same as the given
105     * bitmap's density.
106     *
107     * @param bitmap Specifies a mutable bitmap for the canvas to draw into.
108     */
109    public Canvas(@NonNull Bitmap bitmap) {
110        if (!bitmap.isMutable()) {
111            throw new IllegalStateException("Immutable bitmap passed to Canvas constructor");
112        }
113        throwIfCannotDraw(bitmap);
114        mNativeCanvasWrapper = nInitRaster(bitmap);
115        mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
116                this, mNativeCanvasWrapper);
117        mBitmap = bitmap;
118        mDensity = bitmap.mDensity;
119    }
120
121    /** @hide */
122    public Canvas(long nativeCanvas) {
123        if (nativeCanvas == 0) {
124            throw new IllegalStateException();
125        }
126        mNativeCanvasWrapper = nativeCanvas;
127        mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
128                this, mNativeCanvasWrapper);
129        mDensity = Bitmap.getDefaultDensity();
130    }
131
132    /**
133     * Returns null.
134     *
135     * @deprecated This method is not supported and should not be invoked.
136     *
137     * @hide
138     */
139    @Deprecated
140    protected GL getGL() {
141        return null;
142    }
143
144    /**
145     * Indicates whether this Canvas uses hardware acceleration.
146     *
147     * Note that this method does not define what type of hardware acceleration
148     * may or may not be used.
149     *
150     * @return True if drawing operations are hardware accelerated,
151     *         false otherwise.
152     */
153    public boolean isHardwareAccelerated() {
154        return false;
155    }
156
157    /**
158     * Specify a bitmap for the canvas to draw into. All canvas state such as
159     * layers, filters, and the save/restore stack are reset with the exception
160     * of the current matrix and clip stack. Additionally, as a side-effect
161     * the canvas' target density is updated to match that of the bitmap.
162     *
163     * @param bitmap Specifies a mutable bitmap for the canvas to draw into.
164     * @see #setDensity(int)
165     * @see #getDensity()
166     */
167    public void setBitmap(@Nullable Bitmap bitmap) {
168        if (isHardwareAccelerated()) {
169            throw new RuntimeException("Can't set a bitmap device on a HW accelerated canvas");
170        }
171
172        if (bitmap == null) {
173            nSetBitmap(mNativeCanvasWrapper, null);
174            mDensity = Bitmap.DENSITY_NONE;
175        } else {
176            if (!bitmap.isMutable()) {
177                throw new IllegalStateException();
178            }
179            throwIfCannotDraw(bitmap);
180
181            nSetBitmap(mNativeCanvasWrapper, bitmap);
182            mDensity = bitmap.mDensity;
183        }
184
185        mBitmap = bitmap;
186    }
187
188    /** @hide */
189    public void setHighContrastText(boolean highContrastText) {
190        nSetHighContrastText(mNativeCanvasWrapper, highContrastText);
191    }
192
193    /** @hide */
194    public void insertReorderBarrier() {}
195
196    /** @hide */
197    public void insertInorderBarrier() {}
198
199    /**
200     * Return true if the device that the current layer draws into is opaque
201     * (i.e. does not support per-pixel alpha).
202     *
203     * @return true if the device that the current layer draws into is opaque
204     */
205    public boolean isOpaque() {
206        return nIsOpaque(mNativeCanvasWrapper);
207    }
208
209    /**
210     * Returns the width of the current drawing layer
211     *
212     * @return the width of the current drawing layer
213     */
214    public int getWidth() {
215        return nGetWidth(mNativeCanvasWrapper);
216    }
217
218    /**
219     * Returns the height of the current drawing layer
220     *
221     * @return the height of the current drawing layer
222     */
223    public int getHeight() {
224        return nGetHeight(mNativeCanvasWrapper);
225    }
226
227    /**
228     * <p>Returns the target density of the canvas.  The default density is
229     * derived from the density of its backing bitmap, or
230     * {@link Bitmap#DENSITY_NONE} if there is not one.</p>
231     *
232     * @return Returns the current target density of the canvas, which is used
233     * to determine the scaling factor when drawing a bitmap into it.
234     *
235     * @see #setDensity(int)
236     * @see Bitmap#getDensity()
237     */
238    public int getDensity() {
239        return mDensity;
240    }
241
242    /**
243     * <p>Specifies the density for this Canvas' backing bitmap.  This modifies
244     * the target density of the canvas itself, as well as the density of its
245     * backing bitmap via {@link Bitmap#setDensity(int) Bitmap.setDensity(int)}.
246     *
247     * @param density The new target density of the canvas, which is used
248     * to determine the scaling factor when drawing a bitmap into it.  Use
249     * {@link Bitmap#DENSITY_NONE} to disable bitmap scaling.
250     *
251     * @see #getDensity()
252     * @see Bitmap#setDensity(int)
253     */
254    public void setDensity(int density) {
255        if (mBitmap != null) {
256            mBitmap.setDensity(density);
257        }
258        mDensity = density;
259    }
260
261    /** @hide */
262    public void setScreenDensity(int density) {
263        mScreenDensity = density;
264    }
265
266    /**
267     * Returns the maximum allowed width for bitmaps drawn with this canvas.
268     * Attempting to draw with a bitmap wider than this value will result
269     * in an error.
270     *
271     * @see #getMaximumBitmapHeight()
272     */
273    public int getMaximumBitmapWidth() {
274        return MAXMIMUM_BITMAP_SIZE;
275    }
276
277    /**
278     * Returns the maximum allowed height for bitmaps drawn with this canvas.
279     * Attempting to draw with a bitmap taller than this value will result
280     * in an error.
281     *
282     * @see #getMaximumBitmapWidth()
283     */
284    public int getMaximumBitmapHeight() {
285        return MAXMIMUM_BITMAP_SIZE;
286    }
287
288    // the SAVE_FLAG constants must match their native equivalents
289
290    /** @hide */
291    @IntDef(flag = true,
292            value = {
293                MATRIX_SAVE_FLAG,
294                CLIP_SAVE_FLAG,
295                HAS_ALPHA_LAYER_SAVE_FLAG,
296                FULL_COLOR_LAYER_SAVE_FLAG,
297                CLIP_TO_LAYER_SAVE_FLAG,
298                ALL_SAVE_FLAG
299            })
300    @Retention(RetentionPolicy.SOURCE)
301    public @interface Saveflags {}
302
303    /**
304     * Restore the current matrix when restore() is called.
305     */
306    public static final int MATRIX_SAVE_FLAG = 0x01;
307
308    /**
309     * Restore the current clip when restore() is called.
310     */
311    public static final int CLIP_SAVE_FLAG = 0x02;
312
313    /**
314     * The layer requires a per-pixel alpha channel.
315     */
316    public static final int HAS_ALPHA_LAYER_SAVE_FLAG = 0x04;
317
318    /**
319     * The layer requires full 8-bit precision for each color channel.
320     */
321    public static final int FULL_COLOR_LAYER_SAVE_FLAG = 0x08;
322
323    /**
324     * Clip drawing to the bounds of the offscreen layer, omit at your own peril.
325     * <p class="note"><strong>Note:</strong> it is strongly recommended to not
326     * omit this flag for any call to <code>saveLayer()</code> and
327     * <code>saveLayerAlpha()</code> variants. Not passing this flag generally
328     * triggers extremely poor performance with hardware accelerated rendering.
329     */
330    public static final int CLIP_TO_LAYER_SAVE_FLAG = 0x10;
331
332    /**
333     * Restore everything when restore() is called (standard save flags).
334     * <p class="note"><strong>Note:</strong> for performance reasons, it is
335     * strongly recommended to pass this - the complete set of flags - to any
336     * call to <code>saveLayer()</code> and <code>saveLayerAlpha()</code>
337     * variants.
338     */
339    public static final int ALL_SAVE_FLAG = 0x1F;
340
341    /**
342     * Saves the current matrix and clip onto a private stack.
343     * <p>
344     * Subsequent calls to translate,scale,rotate,skew,concat or clipRect,
345     * clipPath will all operate as usual, but when the balancing call to
346     * restore() is made, those calls will be forgotten, and the settings that
347     * existed before the save() will be reinstated.
348     *
349     * @return The value to pass to restoreToCount() to balance this save()
350     */
351    public int save() {
352        return nSave(mNativeCanvasWrapper, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
353    }
354
355    /**
356     * Based on saveFlags, can save the current matrix and clip onto a private
357     * stack.
358     * <p class="note"><strong>Note:</strong> if possible, use the
359     * parameter-less save(). It is simpler and faster than individually
360     * disabling the saving of matrix or clip with this method.
361     * <p>
362     * Subsequent calls to translate,scale,rotate,skew,concat or clipRect,
363     * clipPath will all operate as usual, but when the balancing call to
364     * restore() is made, those calls will be forgotten, and the settings that
365     * existed before the save() will be reinstated.
366     *
367     * @param saveFlags flag bits that specify which parts of the Canvas state
368     *                  to save/restore
369     * @return The value to pass to restoreToCount() to balance this save()
370     */
371    public int save(@Saveflags int saveFlags) {
372        return nSave(mNativeCanvasWrapper, saveFlags);
373    }
374
375    /**
376     * This behaves the same as save(), but in addition it allocates and
377     * redirects drawing to an offscreen bitmap.
378     * <p class="note"><strong>Note:</strong> this method is very expensive,
379     * incurring more than double rendering cost for contained content. Avoid
380     * using this method, especially if the bounds provided are large, or if
381     * the {@link #CLIP_TO_LAYER_SAVE_FLAG} is omitted from the
382     * {@code saveFlags} parameter. It is recommended to use a
383     * {@link android.view.View#LAYER_TYPE_HARDWARE hardware layer} on a View
384     * to apply an xfermode, color filter, or alpha, as it will perform much
385     * better than this method.
386     * <p>
387     * All drawing calls are directed to a newly allocated offscreen bitmap.
388     * Only when the balancing call to restore() is made, is that offscreen
389     * buffer drawn back to the current target of the Canvas (either the
390     * screen, it's target Bitmap, or the previous layer).
391     * <p>
392     * Attributes of the Paint - {@link Paint#getAlpha() alpha},
393     * {@link Paint#getXfermode() Xfermode}, and
394     * {@link Paint#getColorFilter() ColorFilter} are applied when the
395     * offscreen bitmap is drawn back when restore() is called.
396     *
397     * @param bounds May be null. The maximum size the offscreen bitmap
398     *               needs to be (in local coordinates)
399     * @param paint  This is copied, and is applied to the offscreen when
400     *               restore() is called.
401     * @param saveFlags see _SAVE_FLAG constants, generally {@link #ALL_SAVE_FLAG} is recommended
402     *               for performance reasons.
403     * @return       value to pass to restoreToCount() to balance this save()
404     */
405    public int saveLayer(@Nullable RectF bounds, @Nullable Paint paint, @Saveflags int saveFlags) {
406        if (bounds == null) {
407            bounds = new RectF(getClipBounds());
408        }
409        return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
410    }
411
412    /**
413     * Convenience for saveLayer(bounds, paint, {@link #ALL_SAVE_FLAG})
414     */
415    public int saveLayer(@Nullable RectF bounds, @Nullable Paint paint) {
416        return saveLayer(bounds, paint, ALL_SAVE_FLAG);
417    }
418
419    /**
420     * Helper version of saveLayer() that takes 4 values rather than a RectF.
421     */
422    public int saveLayer(float left, float top, float right, float bottom, @Nullable Paint paint,
423            @Saveflags int saveFlags) {
424        return nSaveLayer(mNativeCanvasWrapper, left, top, right, bottom,
425                paint != null ? paint.getNativeInstance() : 0,
426                saveFlags);
427    }
428
429    /**
430     * Convenience for saveLayer(left, top, right, bottom, paint, {@link #ALL_SAVE_FLAG})
431     */
432    public int saveLayer(float left, float top, float right, float bottom, @Nullable Paint paint) {
433        return saveLayer(left, top, right, bottom, paint, ALL_SAVE_FLAG);
434    }
435
436    /**
437     * This behaves the same as save(), but in addition it allocates and
438     * redirects drawing to an offscreen bitmap.
439     * <p class="note"><strong>Note:</strong> this method is very expensive,
440     * incurring more than double rendering cost for contained content. Avoid
441     * using this method, especially if the bounds provided are large, or if
442     * the {@link #CLIP_TO_LAYER_SAVE_FLAG} is omitted from the
443     * {@code saveFlags} parameter. It is recommended to use a
444     * {@link android.view.View#LAYER_TYPE_HARDWARE hardware layer} on a View
445     * to apply an xfermode, color filter, or alpha, as it will perform much
446     * better than this method.
447     * <p>
448     * All drawing calls are directed to a newly allocated offscreen bitmap.
449     * Only when the balancing call to restore() is made, is that offscreen
450     * buffer drawn back to the current target of the Canvas (either the
451     * screen, it's target Bitmap, or the previous layer).
452     * <p>
453     * The {@code alpha} parameter is applied when the offscreen bitmap is
454     * drawn back when restore() is called.
455     *
456     * @param bounds    The maximum size the offscreen bitmap needs to be
457     *                  (in local coordinates)
458     * @param alpha     The alpha to apply to the offscreen when it is
459                        drawn during restore()
460     * @param saveFlags see _SAVE_FLAG constants, generally {@link #ALL_SAVE_FLAG} is recommended
461     *                  for performance reasons.
462     * @return          value to pass to restoreToCount() to balance this call
463     */
464    public int saveLayerAlpha(@Nullable RectF bounds, int alpha, @Saveflags int saveFlags) {
465        if (bounds == null) {
466            bounds = new RectF(getClipBounds());
467        }
468        return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom, alpha, saveFlags);
469    }
470
471    /**
472     * Convenience for saveLayerAlpha(bounds, alpha, {@link #ALL_SAVE_FLAG})
473     */
474    public int saveLayerAlpha(@Nullable RectF bounds, int alpha) {
475        return saveLayerAlpha(bounds, alpha, ALL_SAVE_FLAG);
476    }
477
478    /**
479     * Helper for saveLayerAlpha() that takes 4 values instead of a RectF.
480     */
481    public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
482            @Saveflags int saveFlags) {
483        alpha = Math.min(255, Math.max(0, alpha));
484        return nSaveLayerAlpha(mNativeCanvasWrapper, left, top, right, bottom,
485                                     alpha, saveFlags);
486    }
487
488    /**
489     * Helper for saveLayerAlpha(left, top, right, bottom, alpha, {@link #ALL_SAVE_FLAG})
490     */
491    public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha) {
492        return saveLayerAlpha(left, top, right, bottom, alpha, ALL_SAVE_FLAG);
493    }
494
495    /**
496     * This call balances a previous call to save(), and is used to remove all
497     * modifications to the matrix/clip state since the last save call. It is
498     * an error to call restore() more times than save() was called.
499     */
500    public void restore() {
501        if (!nRestore(mNativeCanvasWrapper)
502                && (!sCompatibilityRestore || !isHardwareAccelerated())) {
503            throw new IllegalStateException("Underflow in restore - more restores than saves");
504        }
505    }
506
507    /**
508     * Returns the number of matrix/clip states on the Canvas' private stack.
509     * This will equal # save() calls - # restore() calls.
510     */
511    public int getSaveCount() {
512        return nGetSaveCount(mNativeCanvasWrapper);
513    }
514
515    /**
516     * Efficient way to pop any calls to save() that happened after the save
517     * count reached saveCount. It is an error for saveCount to be less than 1.
518     *
519     * Example:
520     *    int count = canvas.save();
521     *    ... // more calls potentially to save()
522     *    canvas.restoreToCount(count);
523     *    // now the canvas is back in the same state it was before the initial
524     *    // call to save().
525     *
526     * @param saveCount The save level to restore to.
527     */
528    public void restoreToCount(int saveCount) {
529        if (saveCount < 1) {
530            if (!sCompatibilityRestore || !isHardwareAccelerated()) {
531                // do nothing and throw without restoring
532                throw new IllegalArgumentException(
533                        "Underflow in restoreToCount - more restores than saves");
534            }
535            // compat behavior - restore as far as possible
536            saveCount = 1;
537        }
538        nRestoreToCount(mNativeCanvasWrapper, saveCount);
539    }
540
541    /**
542     * Preconcat the current matrix with the specified translation
543     *
544     * @param dx The distance to translate in X
545     * @param dy The distance to translate in Y
546    */
547    public void translate(float dx, float dy) {
548        if (dx == 0.0f && dy == 0.0f) return;
549        nTranslate(mNativeCanvasWrapper, dx, dy);
550    }
551
552    /**
553     * Preconcat the current matrix with the specified scale.
554     *
555     * @param sx The amount to scale in X
556     * @param sy The amount to scale in Y
557     */
558    public void scale(float sx, float sy) {
559        if (sx == 1.0f && sy == 1.0f) return;
560        nScale(mNativeCanvasWrapper, sx, sy);
561    }
562
563    /**
564     * Preconcat the current matrix with the specified scale.
565     *
566     * @param sx The amount to scale in X
567     * @param sy The amount to scale in Y
568     * @param px The x-coord for the pivot point (unchanged by the scale)
569     * @param py The y-coord for the pivot point (unchanged by the scale)
570     */
571    public final void scale(float sx, float sy, float px, float py) {
572        if (sx == 1.0f && sy == 1.0f) return;
573        translate(px, py);
574        scale(sx, sy);
575        translate(-px, -py);
576    }
577
578    /**
579     * Preconcat the current matrix with the specified rotation.
580     *
581     * @param degrees The amount to rotate, in degrees
582     */
583    public void rotate(float degrees) {
584        if (degrees == 0.0f) return;
585        nRotate(mNativeCanvasWrapper, degrees);
586    }
587
588    /**
589     * Preconcat the current matrix with the specified rotation.
590     *
591     * @param degrees The amount to rotate, in degrees
592     * @param px The x-coord for the pivot point (unchanged by the rotation)
593     * @param py The y-coord for the pivot point (unchanged by the rotation)
594     */
595    public final void rotate(float degrees, float px, float py) {
596        if (degrees == 0.0f) return;
597        translate(px, py);
598        rotate(degrees);
599        translate(-px, -py);
600    }
601
602    /**
603     * Preconcat the current matrix with the specified skew.
604     *
605     * @param sx The amount to skew in X
606     * @param sy The amount to skew in Y
607     */
608    public void skew(float sx, float sy) {
609        if (sx == 0.0f && sy == 0.0f) return;
610        nSkew(mNativeCanvasWrapper, sx, sy);
611    }
612
613    /**
614     * Preconcat the current matrix with the specified matrix. If the specified
615     * matrix is null, this method does nothing.
616     *
617     * @param matrix The matrix to preconcatenate with the current matrix
618     */
619    public void concat(@Nullable Matrix matrix) {
620        if (matrix != null) nConcat(mNativeCanvasWrapper, matrix.native_instance);
621    }
622
623    /**
624     * Completely replace the current matrix with the specified matrix. If the
625     * matrix parameter is null, then the current matrix is reset to identity.
626     *
627     * <strong>Note:</strong> it is recommended to use {@link #concat(Matrix)},
628     * {@link #scale(float, float)}, {@link #translate(float, float)} and
629     * {@link #rotate(float)} instead of this method.
630     *
631     * @param matrix The matrix to replace the current matrix with. If it is
632     *               null, set the current matrix to identity.
633     *
634     * @see #concat(Matrix)
635     */
636    public void setMatrix(@Nullable Matrix matrix) {
637        nSetMatrix(mNativeCanvasWrapper,
638                         matrix == null ? 0 : matrix.native_instance);
639    }
640
641    /**
642     * Return, in ctm, the current transformation matrix. This does not alter
643     * the matrix in the canvas, but just returns a copy of it.
644     *
645     * @deprecated {@link #isHardwareAccelerated() Hardware accelerated} canvases may have any
646     * matrix when passed to a View or Drawable, as it is implementation defined where in the
647     * hierarchy such canvases are created. It is recommended in such cases to either draw contents
648     * irrespective of the current matrix, or to track relevant transform state outside of the
649     * canvas.
650     */
651    @Deprecated
652    public void getMatrix(@NonNull Matrix ctm) {
653        nGetMatrix(mNativeCanvasWrapper, ctm.native_instance);
654    }
655
656    /**
657     * Return a new matrix with a copy of the canvas' current transformation
658     * matrix.
659     *
660     * @deprecated {@link #isHardwareAccelerated() Hardware accelerated} canvases may have any
661     * matrix when passed to a View or Drawable, as it is implementation defined where in the
662     * hierarchy such canvases are created. It is recommended in such cases to either draw contents
663     * irrespective of the current matrix, or to track relevant transform state outside of the
664     * canvas.
665     */
666    @Deprecated
667    public final @NonNull Matrix getMatrix() {
668        Matrix m = new Matrix();
669        //noinspection deprecation
670        getMatrix(m);
671        return m;
672    }
673
674    /**
675     * Modify the current clip with the specified rectangle.
676     *
677     * @param rect The rect to intersect with the current clip
678     * @param op How the clip is modified
679     * @return true if the resulting clip is non-empty
680     */
681    public boolean clipRect(@NonNull RectF rect, @NonNull Region.Op op) {
682        return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
683                op.nativeInt);
684    }
685
686    /**
687     * Modify the current clip with the specified rectangle, which is
688     * expressed in local coordinates.
689     *
690     * @param rect The rectangle to intersect with the current clip.
691     * @param op How the clip is modified
692     * @return true if the resulting clip is non-empty
693     */
694    public boolean clipRect(@NonNull Rect rect, @NonNull Region.Op op) {
695        return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
696                op.nativeInt);
697    }
698
699    /**
700     * Intersect the current clip with the specified rectangle, which is
701     * expressed in local coordinates.
702     *
703     * @param rect The rectangle to intersect with the current clip.
704     * @return true if the resulting clip is non-empty
705     */
706    public boolean clipRect(@NonNull RectF rect) {
707        return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
708                Region.Op.INTERSECT.nativeInt);
709    }
710
711    /**
712     * Intersect the current clip with the specified rectangle, which is
713     * expressed in local coordinates.
714     *
715     * @param rect The rectangle to intersect with the current clip.
716     * @return true if the resulting clip is non-empty
717     */
718    public boolean clipRect(@NonNull Rect rect) {
719        return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
720                Region.Op.INTERSECT.nativeInt);
721    }
722
723    /**
724     * Modify the current clip with the specified rectangle, which is
725     * expressed in local coordinates.
726     *
727     * @param left   The left side of the rectangle to intersect with the
728     *               current clip
729     * @param top    The top of the rectangle to intersect with the current
730     *               clip
731     * @param right  The right side of the rectangle to intersect with the
732     *               current clip
733     * @param bottom The bottom of the rectangle to intersect with the current
734     *               clip
735     * @param op     How the clip is modified
736     * @return       true if the resulting clip is non-empty
737     */
738    public boolean clipRect(float left, float top, float right, float bottom,
739            @NonNull Region.Op op) {
740        return nClipRect(mNativeCanvasWrapper, left, top, right, bottom, op.nativeInt);
741    }
742
743    /**
744     * Intersect the current clip with the specified rectangle, which is
745     * expressed in local coordinates.
746     *
747     * @param left   The left side of the rectangle to intersect with the
748     *               current clip
749     * @param top    The top of the rectangle to intersect with the current clip
750     * @param right  The right side of the rectangle to intersect with the
751     *               current clip
752     * @param bottom The bottom of the rectangle to intersect with the current
753     *               clip
754     * @return       true if the resulting clip is non-empty
755     */
756    public boolean clipRect(float left, float top, float right, float bottom) {
757        return nClipRect(mNativeCanvasWrapper, left, top, right, bottom,
758                Region.Op.INTERSECT.nativeInt);
759    }
760
761    /**
762     * Intersect the current clip with the specified rectangle, which is
763     * expressed in local coordinates.
764     *
765     * @param left   The left side of the rectangle to intersect with the
766     *               current clip
767     * @param top    The top of the rectangle to intersect with the current clip
768     * @param right  The right side of the rectangle to intersect with the
769     *               current clip
770     * @param bottom The bottom of the rectangle to intersect with the current
771     *               clip
772     * @return       true if the resulting clip is non-empty
773     */
774    public boolean clipRect(int left, int top, int right, int bottom) {
775        return nClipRect(mNativeCanvasWrapper, left, top, right, bottom,
776                Region.Op.INTERSECT.nativeInt);
777    }
778
779    /**
780        * Modify the current clip with the specified path.
781     *
782     * @param path The path to operate on the current clip
783     * @param op   How the clip is modified
784     * @return     true if the resulting is non-empty
785     */
786    public boolean clipPath(@NonNull Path path, @NonNull Region.Op op) {
787        return nClipPath(mNativeCanvasWrapper, path.readOnlyNI(), op.nativeInt);
788    }
789
790    /**
791     * Intersect the current clip with the specified path.
792     *
793     * @param path The path to intersect with the current clip
794     * @return     true if the resulting is non-empty
795     */
796    public boolean clipPath(@NonNull Path path) {
797        return clipPath(path, Region.Op.INTERSECT);
798    }
799
800    /**
801     * Modify the current clip with the specified region. Note that unlike
802     * clipRect() and clipPath() which transform their arguments by the
803     * current matrix, clipRegion() assumes its argument is already in the
804     * coordinate system of the current layer's bitmap, and so not
805     * transformation is performed.
806     *
807     * @param region The region to operate on the current clip, based on op
808     * @param op How the clip is modified
809     * @return true if the resulting is non-empty
810     *
811     * @removed
812     * @deprecated Unlike all other clip calls this API does not respect the
813     *             current matrix. Use {@link #clipRect(Rect)} as an alternative.
814     */
815    @Deprecated
816    public boolean clipRegion(@NonNull Region region, @NonNull Region.Op op) {
817        return false;
818    }
819
820    /**
821     * Intersect the current clip with the specified region. Note that unlike
822     * clipRect() and clipPath() which transform their arguments by the
823     * current matrix, clipRegion() assumes its argument is already in the
824     * coordinate system of the current layer's bitmap, and so not
825     * transformation is performed.
826     *
827     * @param region The region to operate on the current clip, based on op
828     * @return true if the resulting is non-empty
829     *
830     * @removed
831     * @deprecated Unlike all other clip calls this API does not respect the
832     *             current matrix. Use {@link #clipRect(Rect)} as an alternative.
833     */
834    @Deprecated
835    public boolean clipRegion(@NonNull Region region) {
836        return false;
837    }
838
839    public @Nullable DrawFilter getDrawFilter() {
840        return mDrawFilter;
841    }
842
843    public void setDrawFilter(@Nullable DrawFilter filter) {
844        long nativeFilter = 0;
845        if (filter != null) {
846            nativeFilter = filter.mNativeInt;
847        }
848        mDrawFilter = filter;
849        nSetDrawFilter(mNativeCanvasWrapper, nativeFilter);
850    }
851
852    /**
853     * Constant values used as parameters to {@code quickReject()} calls. These values
854     * specify how much space around the shape should be accounted for, depending on whether
855     * the shaped area is antialiased or not.
856     *
857     * @see #quickReject(float, float, float, float, EdgeType)
858     * @see #quickReject(Path, EdgeType)
859     * @see #quickReject(RectF, EdgeType)
860     */
861    public enum EdgeType {
862
863        /**
864         * Black-and-White: Treat edges by just rounding to nearest pixel boundary
865         */
866        BW(0),  //!< treat edges by just rounding to nearest pixel boundary
867
868        /**
869         * Antialiased: Treat edges by rounding-out, since they may be antialiased
870         */
871        AA(1);
872
873        EdgeType(int nativeInt) {
874            this.nativeInt = nativeInt;
875        }
876
877        /**
878         * @hide
879         */
880        public final int nativeInt;
881    }
882
883    /**
884     * Return true if the specified rectangle, after being transformed by the
885     * current matrix, would lie completely outside of the current clip. Call
886     * this to check if an area you intend to draw into is clipped out (and
887     * therefore you can skip making the draw calls).
888     *
889     * @param rect  the rect to compare with the current clip
890     * @param type  {@link Canvas.EdgeType#AA} if the path should be considered antialiased,
891     *              since that means it may affect a larger area (more pixels) than
892     *              non-antialiased ({@link Canvas.EdgeType#BW}).
893     * @return      true if the rect (transformed by the canvas' matrix)
894     *              does not intersect with the canvas' clip
895     */
896    public boolean quickReject(@NonNull RectF rect, @NonNull EdgeType type) {
897        return nQuickReject(mNativeCanvasWrapper,
898                rect.left, rect.top, rect.right, rect.bottom);
899    }
900
901    /**
902     * Return true if the specified path, after being transformed by the
903     * current matrix, would lie completely outside of the current clip. Call
904     * this to check if an area you intend to draw into is clipped out (and
905     * therefore you can skip making the draw calls). Note: for speed it may
906     * return false even if the path itself might not intersect the clip
907     * (i.e. the bounds of the path intersects, but the path does not).
908     *
909     * @param path        The path to compare with the current clip
910     * @param type        {@link Canvas.EdgeType#AA} if the path should be considered antialiased,
911     *                    since that means it may affect a larger area (more pixels) than
912     *                    non-antialiased ({@link Canvas.EdgeType#BW}).
913     * @return            true if the path (transformed by the canvas' matrix)
914     *                    does not intersect with the canvas' clip
915     */
916    public boolean quickReject(@NonNull Path path, @NonNull EdgeType type) {
917        return nQuickReject(mNativeCanvasWrapper, path.readOnlyNI());
918    }
919
920    /**
921     * Return true if the specified rectangle, after being transformed by the
922     * current matrix, would lie completely outside of the current clip. Call
923     * this to check if an area you intend to draw into is clipped out (and
924     * therefore you can skip making the draw calls).
925     *
926     * @param left        The left side of the rectangle to compare with the
927     *                    current clip
928     * @param top         The top of the rectangle to compare with the current
929     *                    clip
930     * @param right       The right side of the rectangle to compare with the
931     *                    current clip
932     * @param bottom      The bottom of the rectangle to compare with the
933     *                    current clip
934     * @param type        {@link Canvas.EdgeType#AA} if the path should be considered antialiased,
935     *                    since that means it may affect a larger area (more pixels) than
936     *                    non-antialiased ({@link Canvas.EdgeType#BW}).
937     * @return            true if the rect (transformed by the canvas' matrix)
938     *                    does not intersect with the canvas' clip
939     */
940    public boolean quickReject(float left, float top, float right, float bottom,
941            @NonNull EdgeType type) {
942        return nQuickReject(mNativeCanvasWrapper, left, top, right, bottom);
943    }
944
945    /**
946     * Return the bounds of the current clip (in local coordinates) in the
947     * bounds parameter, and return true if it is non-empty. This can be useful
948     * in a way similar to quickReject, in that it tells you that drawing
949     * outside of these bounds will be clipped out.
950     *
951     * @param bounds Return the clip bounds here. If it is null, ignore it but
952     *               still return true if the current clip is non-empty.
953     * @return true if the current clip is non-empty.
954     */
955    public boolean getClipBounds(@Nullable Rect bounds) {
956        return nGetClipBounds(mNativeCanvasWrapper, bounds);
957    }
958
959    /**
960     * Retrieve the bounds of the current clip (in local coordinates).
961     *
962     * @return the clip bounds, or [0, 0, 0, 0] if the clip is empty.
963     */
964    public final @NonNull Rect getClipBounds() {
965        Rect r = new Rect();
966        getClipBounds(r);
967        return r;
968    }
969
970    /**
971     * Save the canvas state, draw the picture, and restore the canvas state.
972     * This differs from picture.draw(canvas), which does not perform any
973     * save/restore.
974     *
975     * <p>
976     * <strong>Note:</strong> This forces the picture to internally call
977     * {@link Picture#endRecording} in order to prepare for playback.
978     *
979     * @param picture  The picture to be drawn
980     */
981    public void drawPicture(@NonNull Picture picture) {
982        picture.endRecording();
983        int restoreCount = save();
984        picture.draw(this);
985        restoreToCount(restoreCount);
986    }
987
988    /**
989     * Draw the picture, stretched to fit into the dst rectangle.
990     */
991    public void drawPicture(@NonNull Picture picture, @NonNull RectF dst) {
992        save();
993        translate(dst.left, dst.top);
994        if (picture.getWidth() > 0 && picture.getHeight() > 0) {
995            scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
996        }
997        drawPicture(picture);
998        restore();
999    }
1000
1001    /**
1002     * Draw the picture, stretched to fit into the dst rectangle.
1003     */
1004    public void drawPicture(@NonNull Picture picture, @NonNull Rect dst) {
1005        save();
1006        translate(dst.left, dst.top);
1007        if (picture.getWidth() > 0 && picture.getHeight() > 0) {
1008            scale((float) dst.width() / picture.getWidth(),
1009                    (float) dst.height() / picture.getHeight());
1010        }
1011        drawPicture(picture);
1012        restore();
1013    }
1014
1015    public enum VertexMode {
1016        TRIANGLES(0),
1017        TRIANGLE_STRIP(1),
1018        TRIANGLE_FAN(2);
1019
1020        VertexMode(int nativeInt) {
1021            this.nativeInt = nativeInt;
1022        }
1023
1024        /**
1025         * @hide
1026         */
1027        public final int nativeInt;
1028    }
1029
1030    /**
1031     * Releases the resources associated with this canvas.
1032     *
1033     * @hide
1034     */
1035    public void release() {
1036        mNativeCanvasWrapper = 0;
1037        if (mFinalizer != null) {
1038            mFinalizer.run();
1039            mFinalizer = null;
1040        }
1041    }
1042
1043    /**
1044     * Free up as much memory as possible from private caches (e.g. fonts, images)
1045     *
1046     * @hide
1047     */
1048    public static void freeCaches() {
1049        nFreeCaches();
1050    }
1051
1052    /**
1053     * Free up text layout caches
1054     *
1055     * @hide
1056     */
1057    public static void freeTextLayoutCaches() {
1058        nFreeTextLayoutCaches();
1059    }
1060
1061    private static native void nFreeCaches();
1062    private static native void nFreeTextLayoutCaches();
1063    private static native long nInitRaster(Bitmap bitmap);
1064    private static native long nGetNativeFinalizer();
1065
1066    // ---------------- @FastNative -------------------
1067
1068    @FastNative
1069    private static native void nSetBitmap(long canvasHandle, Bitmap bitmap);
1070
1071    @FastNative
1072    private static native boolean nGetClipBounds(long nativeCanvas, Rect bounds);
1073
1074    // ---------------- @CriticalNative -------------------
1075
1076    @CriticalNative
1077    private static native boolean nIsOpaque(long canvasHandle);
1078    @CriticalNative
1079    private static native void nSetHighContrastText(long renderer, boolean highContrastText);
1080    @CriticalNative
1081    private static native int nGetWidth(long canvasHandle);
1082    @CriticalNative
1083    private static native int nGetHeight(long canvasHandle);
1084
1085    @CriticalNative
1086    private static native int nSave(long canvasHandle, int saveFlags);
1087    @CriticalNative
1088    private static native int nSaveLayer(long nativeCanvas, float l, float t, float r, float b,
1089            long nativePaint, int layerFlags);
1090    @CriticalNative
1091    private static native int nSaveLayerAlpha(long nativeCanvas, float l, float t, float r, float b,
1092            int alpha, int layerFlags);
1093    @CriticalNative
1094    private static native boolean nRestore(long canvasHandle);
1095    @CriticalNative
1096    private static native void nRestoreToCount(long canvasHandle, int saveCount);
1097    @CriticalNative
1098    private static native int nGetSaveCount(long canvasHandle);
1099
1100    @CriticalNative
1101    private static native void nTranslate(long canvasHandle, float dx, float dy);
1102    @CriticalNative
1103    private static native void nScale(long canvasHandle, float sx, float sy);
1104    @CriticalNative
1105    private static native void nRotate(long canvasHandle, float degrees);
1106    @CriticalNative
1107    private static native void nSkew(long canvasHandle, float sx, float sy);
1108    @CriticalNative
1109    private static native void nConcat(long nativeCanvas, long nativeMatrix);
1110    @CriticalNative
1111    private static native void nSetMatrix(long nativeCanvas, long nativeMatrix);
1112    @CriticalNative
1113    private static native boolean nClipRect(long nativeCanvas,
1114            float left, float top, float right, float bottom, int regionOp);
1115    @CriticalNative
1116    private static native boolean nClipPath(long nativeCanvas, long nativePath, int regionOp);
1117    @CriticalNative
1118    private static native void nSetDrawFilter(long nativeCanvas, long nativeFilter);
1119    @CriticalNative
1120    private static native void nGetMatrix(long nativeCanvas, long nativeMatrix);
1121    @CriticalNative
1122    private static native boolean nQuickReject(long nativeCanvas, long nativePath);
1123    @CriticalNative
1124    private static native boolean nQuickReject(long nativeCanvas, float left, float top,
1125            float right, float bottom);
1126
1127
1128    // ---------------- Draw Methods -------------------
1129
1130    /**
1131     * <p>
1132     * Draw the specified arc, which will be scaled to fit inside the specified oval.
1133     * </p>
1134     * <p>
1135     * If the start angle is negative or >= 360, the start angle is treated as start angle modulo
1136     * 360.
1137     * </p>
1138     * <p>
1139     * If the sweep angle is >= 360, then the oval is drawn completely. Note that this differs
1140     * slightly from SkPath::arcTo, which treats the sweep angle modulo 360. If the sweep angle is
1141     * negative, the sweep angle is treated as sweep angle modulo 360
1142     * </p>
1143     * <p>
1144     * The arc is drawn clockwise. An angle of 0 degrees correspond to the geometric angle of 0
1145     * degrees (3 o'clock on a watch.)
1146     * </p>
1147     *
1148     * @param oval The bounds of oval used to define the shape and size of the arc
1149     * @param startAngle Starting angle (in degrees) where the arc begins
1150     * @param sweepAngle Sweep angle (in degrees) measured clockwise
1151     * @param useCenter If true, include the center of the oval in the arc, and close it if it is
1152     *            being stroked. This will draw a wedge
1153     * @param paint The paint used to draw the arc
1154     */
1155    public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,
1156            @NonNull Paint paint) {
1157        super.drawArc(oval, startAngle, sweepAngle, useCenter, paint);
1158    }
1159
1160    /**
1161     * <p>
1162     * Draw the specified arc, which will be scaled to fit inside the specified oval.
1163     * </p>
1164     * <p>
1165     * If the start angle is negative or >= 360, the start angle is treated as start angle modulo
1166     * 360.
1167     * </p>
1168     * <p>
1169     * If the sweep angle is >= 360, then the oval is drawn completely. Note that this differs
1170     * slightly from SkPath::arcTo, which treats the sweep angle modulo 360. If the sweep angle is
1171     * negative, the sweep angle is treated as sweep angle modulo 360
1172     * </p>
1173     * <p>
1174     * The arc is drawn clockwise. An angle of 0 degrees correspond to the geometric angle of 0
1175     * degrees (3 o'clock on a watch.)
1176     * </p>
1177     *
1178     * @param startAngle Starting angle (in degrees) where the arc begins
1179     * @param sweepAngle Sweep angle (in degrees) measured clockwise
1180     * @param useCenter If true, include the center of the oval in the arc, and close it if it is
1181     *            being stroked. This will draw a wedge
1182     * @param paint The paint used to draw the arc
1183     */
1184    public void drawArc(float left, float top, float right, float bottom, float startAngle,
1185            float sweepAngle, boolean useCenter, @NonNull Paint paint) {
1186        super.drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
1187    }
1188
1189    /**
1190     * Fill the entire canvas' bitmap (restricted to the current clip) with the specified ARGB
1191     * color, using srcover porterduff mode.
1192     *
1193     * @param a alpha component (0..255) of the color to draw onto the canvas
1194     * @param r red component (0..255) of the color to draw onto the canvas
1195     * @param g green component (0..255) of the color to draw onto the canvas
1196     * @param b blue component (0..255) of the color to draw onto the canvas
1197     */
1198    public void drawARGB(int a, int r, int g, int b) {
1199        super.drawARGB(a, r, g, b);
1200    }
1201
1202    /**
1203     * Draw the specified bitmap, with its top/left corner at (x,y), using the specified paint,
1204     * transformed by the current matrix.
1205     * <p>
1206     * Note: if the paint contains a maskfilter that generates a mask which extends beyond the
1207     * bitmap's original width/height (e.g. BlurMaskFilter), then the bitmap will be drawn as if it
1208     * were in a Shader with CLAMP mode. Thus the color outside of the original width/height will be
1209     * the edge color replicated.
1210     * <p>
1211     * If the bitmap and canvas have different densities, this function will take care of
1212     * automatically scaling the bitmap to draw at the same density as the canvas.
1213     *
1214     * @param bitmap The bitmap to be drawn
1215     * @param left The position of the left side of the bitmap being drawn
1216     * @param top The position of the top side of the bitmap being drawn
1217     * @param paint The paint used to draw the bitmap (may be null)
1218     */
1219    public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) {
1220        super.drawBitmap(bitmap, left, top, paint);
1221    }
1222
1223    /**
1224     * Draw the specified bitmap, scaling/translating automatically to fill the destination
1225     * rectangle. If the source rectangle is not null, it specifies the subset of the bitmap to
1226     * draw.
1227     * <p>
1228     * Note: if the paint contains a maskfilter that generates a mask which extends beyond the
1229     * bitmap's original width/height (e.g. BlurMaskFilter), then the bitmap will be drawn as if it
1230     * were in a Shader with CLAMP mode. Thus the color outside of the original width/height will be
1231     * the edge color replicated.
1232     * <p>
1233     * This function <em>ignores the density associated with the bitmap</em>. This is because the
1234     * source and destination rectangle coordinate spaces are in their respective densities, so must
1235     * already have the appropriate scaling factor applied.
1236     *
1237     * @param bitmap The bitmap to be drawn
1238     * @param src May be null. The subset of the bitmap to be drawn
1239     * @param dst The rectangle that the bitmap will be scaled/translated to fit into
1240     * @param paint May be null. The paint used to draw the bitmap
1241     */
1242    public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst,
1243            @Nullable Paint paint) {
1244        super.drawBitmap(bitmap, src, dst, paint);
1245    }
1246
1247    /**
1248     * Draw the specified bitmap, scaling/translating automatically to fill the destination
1249     * rectangle. If the source rectangle is not null, it specifies the subset of the bitmap to
1250     * draw.
1251     * <p>
1252     * Note: if the paint contains a maskfilter that generates a mask which extends beyond the
1253     * bitmap's original width/height (e.g. BlurMaskFilter), then the bitmap will be drawn as if it
1254     * were in a Shader with CLAMP mode. Thus the color outside of the original width/height will be
1255     * the edge color replicated.
1256     * <p>
1257     * This function <em>ignores the density associated with the bitmap</em>. This is because the
1258     * source and destination rectangle coordinate spaces are in their respective densities, so must
1259     * already have the appropriate scaling factor applied.
1260     *
1261     * @param bitmap The bitmap to be drawn
1262     * @param src May be null. The subset of the bitmap to be drawn
1263     * @param dst The rectangle that the bitmap will be scaled/translated to fit into
1264     * @param paint May be null. The paint used to draw the bitmap
1265     */
1266    public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst,
1267            @Nullable Paint paint) {
1268        super.drawBitmap(bitmap, src, dst, paint);
1269    }
1270
1271    /**
1272     * Treat the specified array of colors as a bitmap, and draw it. This gives the same result as
1273     * first creating a bitmap from the array, and then drawing it, but this method avoids
1274     * explicitly creating a bitmap object which can be more efficient if the colors are changing
1275     * often.
1276     *
1277     * @param colors Array of colors representing the pixels of the bitmap
1278     * @param offset Offset into the array of colors for the first pixel
1279     * @param stride The number of colors in the array between rows (must be >= width or <= -width).
1280     * @param x The X coordinate for where to draw the bitmap
1281     * @param y The Y coordinate for where to draw the bitmap
1282     * @param width The width of the bitmap
1283     * @param height The height of the bitmap
1284     * @param hasAlpha True if the alpha channel of the colors contains valid values. If false, the
1285     *            alpha byte is ignored (assumed to be 0xFF for every pixel).
1286     * @param paint May be null. The paint used to draw the bitmap
1287     * @deprecated Usage with a {@link #isHardwareAccelerated() hardware accelerated} canvas
1288     *             requires an internal copy of color buffer contents every time this method is
1289     *             called. Using a Bitmap avoids this copy, and allows the application to more
1290     *             explicitly control the lifetime and copies of pixel data.
1291     */
1292    @Deprecated
1293    public void drawBitmap(@NonNull int[] colors, int offset, int stride, float x, float y,
1294            int width, int height, boolean hasAlpha, @Nullable Paint paint) {
1295        super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint);
1296    }
1297
1298    /**
1299     * Legacy version of drawBitmap(int[] colors, ...) that took ints for x,y
1300     *
1301     * @deprecated Usage with a {@link #isHardwareAccelerated() hardware accelerated} canvas
1302     *             requires an internal copy of color buffer contents every time this method is
1303     *             called. Using a Bitmap avoids this copy, and allows the application to more
1304     *             explicitly control the lifetime and copies of pixel data.
1305     */
1306    @Deprecated
1307    public void drawBitmap(@NonNull int[] colors, int offset, int stride, int x, int y,
1308            int width, int height, boolean hasAlpha, @Nullable Paint paint) {
1309        super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint);
1310    }
1311
1312    /**
1313     * Draw the bitmap using the specified matrix.
1314     *
1315     * @param bitmap The bitmap to draw
1316     * @param matrix The matrix used to transform the bitmap when it is drawn
1317     * @param paint May be null. The paint used to draw the bitmap
1318     */
1319    public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) {
1320        super.drawBitmap(bitmap, matrix, paint);
1321    }
1322
1323    /**
1324     * Draw the bitmap through the mesh, where mesh vertices are evenly distributed across the
1325     * bitmap. There are meshWidth+1 vertices across, and meshHeight+1 vertices down. The verts
1326     * array is accessed in row-major order, so that the first meshWidth+1 vertices are distributed
1327     * across the top of the bitmap from left to right. A more general version of this method is
1328     * drawVertices().
1329     *
1330     * @param bitmap The bitmap to draw using the mesh
1331     * @param meshWidth The number of columns in the mesh. Nothing is drawn if this is 0
1332     * @param meshHeight The number of rows in the mesh. Nothing is drawn if this is 0
1333     * @param verts Array of x,y pairs, specifying where the mesh should be drawn. There must be at
1334     *            least (meshWidth+1) * (meshHeight+1) * 2 + vertOffset values in the array
1335     * @param vertOffset Number of verts elements to skip before drawing
1336     * @param colors May be null. Specifies a color at each vertex, which is interpolated across the
1337     *            cell, and whose values are multiplied by the corresponding bitmap colors. If not
1338     *            null, there must be at least (meshWidth+1) * (meshHeight+1) + colorOffset values
1339     *            in the array.
1340     * @param colorOffset Number of color elements to skip before drawing
1341     * @param paint May be null. The paint used to draw the bitmap
1342     */
1343    public void drawBitmapMesh(@NonNull Bitmap bitmap, int meshWidth, int meshHeight,
1344            @NonNull float[] verts, int vertOffset, @Nullable int[] colors, int colorOffset,
1345            @Nullable Paint paint) {
1346        super.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset, colors, colorOffset,
1347                paint);
1348    }
1349
1350    /**
1351     * Draw the specified circle using the specified paint. If radius is <= 0, then nothing will be
1352     * drawn. The circle will be filled or framed based on the Style in the paint.
1353     *
1354     * @param cx The x-coordinate of the center of the cirle to be drawn
1355     * @param cy The y-coordinate of the center of the cirle to be drawn
1356     * @param radius The radius of the cirle to be drawn
1357     * @param paint The paint used to draw the circle
1358     */
1359    public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
1360        super.drawCircle(cx, cy, radius, paint);
1361    }
1362
1363    /**
1364     * Fill the entire canvas' bitmap (restricted to the current clip) with the specified color,
1365     * using srcover porterduff mode.
1366     *
1367     * @param color the color to draw onto the canvas
1368     */
1369    public void drawColor(@ColorInt int color) {
1370        super.drawColor(color);
1371    }
1372
1373    /**
1374     * Fill the entire canvas' bitmap (restricted to the current clip) with the specified color and
1375     * porter-duff xfermode.
1376     *
1377     * @param color the color to draw with
1378     * @param mode the porter-duff mode to apply to the color
1379     */
1380    public void drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
1381        super.drawColor(color, mode);
1382    }
1383
1384    /**
1385     * Draw a line segment with the specified start and stop x,y coordinates, using the specified
1386     * paint.
1387     * <p>
1388     * Note that since a line is always "framed", the Style is ignored in the paint.
1389     * </p>
1390     * <p>
1391     * Degenerate lines (length is 0) will not be drawn.
1392     * </p>
1393     *
1394     * @param startX The x-coordinate of the start point of the line
1395     * @param startY The y-coordinate of the start point of the line
1396     * @param paint The paint used to draw the line
1397     */
1398    public void drawLine(float startX, float startY, float stopX, float stopY,
1399            @NonNull Paint paint) {
1400        super.drawLine(startX, startY, stopX, stopY, paint);
1401    }
1402
1403    /**
1404     * Draw a series of lines. Each line is taken from 4 consecutive values in the pts array. Thus
1405     * to draw 1 line, the array must contain at least 4 values. This is logically the same as
1406     * drawing the array as follows: drawLine(pts[0], pts[1], pts[2], pts[3]) followed by
1407     * drawLine(pts[4], pts[5], pts[6], pts[7]) and so on.
1408     *
1409     * @param pts Array of points to draw [x0 y0 x1 y1 x2 y2 ...]
1410     * @param offset Number of values in the array to skip before drawing.
1411     * @param count The number of values in the array to process, after skipping "offset" of them.
1412     *            Since each line uses 4 values, the number of "lines" that are drawn is really
1413     *            (count >> 2).
1414     * @param paint The paint used to draw the points
1415     */
1416    public void drawLines(@Size(multiple = 4) @NonNull float[] pts, int offset, int count,
1417            @NonNull Paint paint) {
1418        super.drawLines(pts, offset, count, paint);
1419    }
1420
1421    public void drawLines(@Size(multiple = 4) @NonNull float[] pts, @NonNull Paint paint) {
1422        super.drawLines(pts, paint);
1423    }
1424
1425    /**
1426     * Draw the specified oval using the specified paint. The oval will be filled or framed based on
1427     * the Style in the paint.
1428     *
1429     * @param oval The rectangle bounds of the oval to be drawn
1430     */
1431    public void drawOval(@NonNull RectF oval, @NonNull Paint paint) {
1432        super.drawOval(oval, paint);
1433    }
1434
1435    /**
1436     * Draw the specified oval using the specified paint. The oval will be filled or framed based on
1437     * the Style in the paint.
1438     */
1439    public void drawOval(float left, float top, float right, float bottom, @NonNull Paint paint) {
1440        super.drawOval(left, top, right, bottom, paint);
1441    }
1442
1443    /**
1444     * Fill the entire canvas' bitmap (restricted to the current clip) with the specified paint.
1445     * This is equivalent (but faster) to drawing an infinitely large rectangle with the specified
1446     * paint.
1447     *
1448     * @param paint The paint used to draw onto the canvas
1449     */
1450    public void drawPaint(@NonNull Paint paint) {
1451        super.drawPaint(paint);
1452    }
1453
1454    /**
1455     * Draws the specified bitmap as an N-patch (most often, a 9-patches.)
1456     *
1457     * @param patch The ninepatch object to render
1458     * @param dst The destination rectangle.
1459     * @param paint The paint to draw the bitmap with. may be null
1460     * @hide
1461     */
1462    public void drawPatch(@NonNull NinePatch patch, @NonNull Rect dst, @Nullable Paint paint) {
1463        super.drawPatch(patch, dst, paint);
1464    }
1465
1466    /**
1467     * Draws the specified bitmap as an N-patch (most often, a 9-patches.)
1468     *
1469     * @param patch The ninepatch object to render
1470     * @param dst The destination rectangle.
1471     * @param paint The paint to draw the bitmap with. may be null
1472     * @hide
1473     */
1474    public void drawPatch(@NonNull NinePatch patch, @NonNull RectF dst, @Nullable Paint paint) {
1475        super.drawPatch(patch, dst, paint);
1476    }
1477
1478    /**
1479     * Draw the specified path using the specified paint. The path will be filled or framed based on
1480     * the Style in the paint.
1481     *
1482     * @param path The path to be drawn
1483     * @param paint The paint used to draw the path
1484     */
1485    public void drawPath(@NonNull Path path, @NonNull Paint paint) {
1486        super.drawPath(path, paint);
1487    }
1488
1489    /**
1490     * Helper for drawPoints() for drawing a single point.
1491     */
1492    public void drawPoint(float x, float y, @NonNull Paint paint) {
1493        super.drawPoint(x, y, paint);
1494    }
1495
1496    /**
1497     * Draw a series of points. Each point is centered at the coordinate specified by pts[], and its
1498     * diameter is specified by the paint's stroke width (as transformed by the canvas' CTM), with
1499     * special treatment for a stroke width of 0, which always draws exactly 1 pixel (or at most 4
1500     * if antialiasing is enabled). The shape of the point is controlled by the paint's Cap type.
1501     * The shape is a square, unless the cap type is Round, in which case the shape is a circle.
1502     *
1503     * @param pts Array of points to draw [x0 y0 x1 y1 x2 y2 ...]
1504     * @param offset Number of values to skip before starting to draw.
1505     * @param count The number of values to process, after skipping offset of them. Since one point
1506     *            uses two values, the number of "points" that are drawn is really (count >> 1).
1507     * @param paint The paint used to draw the points
1508     */
1509    public void drawPoints(@Size(multiple = 2) float[] pts, int offset, int count,
1510            @NonNull Paint paint) {
1511        super.drawPoints(pts, offset, count, paint);
1512    }
1513
1514    /**
1515     * Helper for drawPoints() that assumes you want to draw the entire array
1516     */
1517    public void drawPoints(@Size(multiple = 2) @NonNull float[] pts, @NonNull Paint paint) {
1518        super.drawPoints(pts, paint);
1519    }
1520
1521    /**
1522     * Draw the text in the array, with each character's origin specified by the pos array.
1523     *
1524     * @param text The text to be drawn
1525     * @param index The index of the first character to draw
1526     * @param count The number of characters to draw, starting from index.
1527     * @param pos Array of [x,y] positions, used to position each character
1528     * @param paint The paint used for the text (e.g. color, size, style)
1529     * @deprecated This method does not support glyph composition and decomposition and should
1530     *             therefore not be used to render complex scripts. It also doesn't handle
1531     *             supplementary characters (eg emoji).
1532     */
1533    @Deprecated
1534    public void drawPosText(@NonNull char[] text, int index, int count,
1535            @NonNull @Size(multiple = 2) float[] pos,
1536            @NonNull Paint paint) {
1537        super.drawPosText(text, index, count, pos, paint);
1538    }
1539
1540    /**
1541     * Draw the text in the array, with each character's origin specified by the pos array.
1542     *
1543     * @param text The text to be drawn
1544     * @param pos Array of [x,y] positions, used to position each character
1545     * @param paint The paint used for the text (e.g. color, size, style)
1546     * @deprecated This method does not support glyph composition and decomposition and should
1547     *             therefore not be used to render complex scripts. It also doesn't handle
1548     *             supplementary characters (eg emoji).
1549     */
1550    @Deprecated
1551    public void drawPosText(@NonNull String text, @NonNull @Size(multiple = 2) float[] pos,
1552            @NonNull Paint paint) {
1553        super.drawPosText(text, pos, paint);
1554    }
1555
1556    /**
1557     * Draw the specified Rect using the specified paint. The rectangle will be filled or framed
1558     * based on the Style in the paint.
1559     *
1560     * @param rect The rect to be drawn
1561     * @param paint The paint used to draw the rect
1562     */
1563    public void drawRect(@NonNull RectF rect, @NonNull Paint paint) {
1564        super.drawRect(rect, paint);
1565    }
1566
1567    /**
1568     * Draw the specified Rect using the specified Paint. The rectangle will be filled or framed
1569     * based on the Style in the paint.
1570     *
1571     * @param r The rectangle to be drawn.
1572     * @param paint The paint used to draw the rectangle
1573     */
1574    public void drawRect(@NonNull Rect r, @NonNull Paint paint) {
1575        super.drawRect(r, paint);
1576    }
1577
1578    /**
1579     * Draw the specified Rect using the specified paint. The rectangle will be filled or framed
1580     * based on the Style in the paint.
1581     *
1582     * @param left The left side of the rectangle to be drawn
1583     * @param top The top side of the rectangle to be drawn
1584     * @param right The right side of the rectangle to be drawn
1585     * @param bottom The bottom side of the rectangle to be drawn
1586     * @param paint The paint used to draw the rect
1587     */
1588    public void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint) {
1589        super.drawRect(left, top, right, bottom, paint);
1590    }
1591
1592    /**
1593     * Fill the entire canvas' bitmap (restricted to the current clip) with the specified RGB color,
1594     * using srcover porterduff mode.
1595     *
1596     * @param r red component (0..255) of the color to draw onto the canvas
1597     * @param g green component (0..255) of the color to draw onto the canvas
1598     * @param b blue component (0..255) of the color to draw onto the canvas
1599     */
1600    public void drawRGB(int r, int g, int b) {
1601        super.drawRGB(r, g, b);
1602    }
1603
1604    /**
1605     * Draw the specified round-rect using the specified paint. The roundrect will be filled or
1606     * framed based on the Style in the paint.
1607     *
1608     * @param rect The rectangular bounds of the roundRect to be drawn
1609     * @param rx The x-radius of the oval used to round the corners
1610     * @param ry The y-radius of the oval used to round the corners
1611     * @param paint The paint used to draw the roundRect
1612     */
1613    public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) {
1614        super.drawRoundRect(rect, rx, ry, paint);
1615    }
1616
1617    /**
1618     * Draw the specified round-rect using the specified paint. The roundrect will be filled or
1619     * framed based on the Style in the paint.
1620     *
1621     * @param rx The x-radius of the oval used to round the corners
1622     * @param ry The y-radius of the oval used to round the corners
1623     * @param paint The paint used to draw the roundRect
1624     */
1625    public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
1626            @NonNull Paint paint) {
1627        super.drawRoundRect(left, top, right, bottom, rx, ry, paint);
1628    }
1629
1630    /**
1631     * Draw the text, with origin at (x,y), using the specified paint. The origin is interpreted
1632     * based on the Align setting in the paint.
1633     *
1634     * @param text The text to be drawn
1635     * @param x The x-coordinate of the origin of the text being drawn
1636     * @param y The y-coordinate of the baseline of the text being drawn
1637     * @param paint The paint used for the text (e.g. color, size, style)
1638     */
1639    public void drawText(@NonNull char[] text, int index, int count, float x, float y,
1640            @NonNull Paint paint) {
1641        super.drawText(text, index, count, x, y, paint);
1642    }
1643
1644    /**
1645     * Draw the text, with origin at (x,y), using the specified paint. The origin is interpreted
1646     * based on the Align setting in the paint.
1647     *
1648     * @param text The text to be drawn
1649     * @param x The x-coordinate of the origin of the text being drawn
1650     * @param y The y-coordinate of the baseline of the text being drawn
1651     * @param paint The paint used for the text (e.g. color, size, style)
1652     */
1653    public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
1654        super.drawText(text, x, y, paint);
1655    }
1656
1657    /**
1658     * Draw the text, with origin at (x,y), using the specified paint. The origin is interpreted
1659     * based on the Align setting in the paint.
1660     *
1661     * @param text The text to be drawn
1662     * @param start The index of the first character in text to draw
1663     * @param end (end - 1) is the index of the last character in text to draw
1664     * @param x The x-coordinate of the origin of the text being drawn
1665     * @param y The y-coordinate of the baseline of the text being drawn
1666     * @param paint The paint used for the text (e.g. color, size, style)
1667     */
1668    public void drawText(@NonNull String text, int start, int end, float x, float y,
1669            @NonNull Paint paint) {
1670        super.drawText(text, start, end, x, y, paint);
1671    }
1672
1673    /**
1674     * Draw the specified range of text, specified by start/end, with its origin at (x,y), in the
1675     * specified Paint. The origin is interpreted based on the Align setting in the Paint.
1676     *
1677     * @param text The text to be drawn
1678     * @param start The index of the first character in text to draw
1679     * @param end (end - 1) is the index of the last character in text to draw
1680     * @param x The x-coordinate of origin for where to draw the text
1681     * @param y The y-coordinate of origin for where to draw the text
1682     * @param paint The paint used for the text (e.g. color, size, style)
1683     */
1684    public void drawText(@NonNull CharSequence text, int start, int end, float x, float y,
1685            @NonNull Paint paint) {
1686        super.drawText(text, start, end, x, y, paint);
1687    }
1688
1689    /**
1690     * Draw the text, with origin at (x,y), using the specified paint, along the specified path. The
1691     * paint's Align setting determins where along the path to start the text.
1692     *
1693     * @param text The text to be drawn
1694     * @param path The path the text should follow for its baseline
1695     * @param hOffset The distance along the path to add to the text's starting position
1696     * @param vOffset The distance above(-) or below(+) the path to position the text
1697     * @param paint The paint used for the text (e.g. color, size, style)
1698     */
1699    public void drawTextOnPath(@NonNull char[] text, int index, int count, @NonNull Path path,
1700            float hOffset, float vOffset, @NonNull Paint paint) {
1701        super.drawTextOnPath(text, index, count, path, hOffset, vOffset, paint);
1702    }
1703
1704    /**
1705     * Draw the text, with origin at (x,y), using the specified paint, along the specified path. The
1706     * paint's Align setting determins where along the path to start the text.
1707     *
1708     * @param text The text to be drawn
1709     * @param path The path the text should follow for its baseline
1710     * @param hOffset The distance along the path to add to the text's starting position
1711     * @param vOffset The distance above(-) or below(+) the path to position the text
1712     * @param paint The paint used for the text (e.g. color, size, style)
1713     */
1714    public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,
1715            float vOffset, @NonNull Paint paint) {
1716        super.drawTextOnPath(text, path, hOffset, vOffset, paint);
1717    }
1718
1719    /**
1720     * Draw a run of text, all in a single direction, with optional context for complex text
1721     * shaping.
1722     * <p>
1723     * See {@link #drawTextRun(CharSequence, int, int, int, int, float, float, boolean, Paint)} for
1724     * more details. This method uses a character array rather than CharSequence to represent the
1725     * string. Also, to be consistent with the pattern established in {@link #drawText}, in this
1726     * method {@code count} and {@code contextCount} are used rather than offsets of the end
1727     * position; {@code count = end - start, contextCount = contextEnd -
1728     * contextStart}.
1729     *
1730     * @param text the text to render
1731     * @param index the start of the text to render
1732     * @param count the count of chars to render
1733     * @param contextIndex the start of the context for shaping. Must be no greater than index.
1734     * @param contextCount the number of characters in the context for shaping. contexIndex +
1735     *            contextCount must be no less than index + count.
1736     * @param x the x position at which to draw the text
1737     * @param y the y position at which to draw the text
1738     * @param isRtl whether the run is in RTL direction
1739     * @param paint the paint
1740     */
1741    public void drawTextRun(@NonNull char[] text, int index, int count, int contextIndex,
1742            int contextCount, float x, float y, boolean isRtl, @NonNull Paint paint) {
1743        super.drawTextRun(text, index, count, contextIndex, contextCount, x, y, isRtl, paint);
1744    }
1745
1746    /**
1747     * Draw a run of text, all in a single direction, with optional context for complex text
1748     * shaping.
1749     * <p>
1750     * The run of text includes the characters from {@code start} to {@code end} in the text. In
1751     * addition, the range {@code contextStart} to {@code contextEnd} is used as context for the
1752     * purpose of complex text shaping, such as Arabic text potentially shaped differently based on
1753     * the text next to it.
1754     * <p>
1755     * All text outside the range {@code contextStart..contextEnd} is ignored. The text between
1756     * {@code start} and {@code end} will be laid out and drawn.
1757     * <p>
1758     * The direction of the run is explicitly specified by {@code isRtl}. Thus, this method is
1759     * suitable only for runs of a single direction. Alignment of the text is as determined by the
1760     * Paint's TextAlign value. Further, {@code 0 <= contextStart <= start <= end <= contextEnd
1761     * <= text.length} must hold on entry.
1762     * <p>
1763     * Also see {@link android.graphics.Paint#getRunAdvance} for a corresponding method to measure
1764     * the text; the advance width of the text drawn matches the value obtained from that method.
1765     *
1766     * @param text the text to render
1767     * @param start the start of the text to render. Data before this position can be used for
1768     *            shaping context.
1769     * @param end the end of the text to render. Data at or after this position can be used for
1770     *            shaping context.
1771     * @param contextStart the index of the start of the shaping context
1772     * @param contextEnd the index of the end of the shaping context
1773     * @param x the x position at which to draw the text
1774     * @param y the y position at which to draw the text
1775     * @param isRtl whether the run is in RTL direction
1776     * @param paint the paint
1777     * @see #drawTextRun(char[], int, int, int, int, float, float, boolean, Paint)
1778     */
1779    public void drawTextRun(@NonNull CharSequence text, int start, int end, int contextStart,
1780            int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) {
1781        super.drawTextRun(text, start, end, contextStart, contextEnd, x, y, isRtl, paint);
1782    }
1783
1784    /**
1785     * Draw the array of vertices, interpreted as triangles (based on mode). The verts array is
1786     * required, and specifies the x,y pairs for each vertex. If texs is non-null, then it is used
1787     * to specify the coordinate in shader coordinates to use at each vertex (the paint must have a
1788     * shader in this case). If there is no texs array, but there is a color array, then each color
1789     * is interpolated across its corresponding triangle in a gradient. If both texs and colors
1790     * arrays are present, then they behave as before, but the resulting color at each pixels is the
1791     * result of multiplying the colors from the shader and the color-gradient together. The indices
1792     * array is optional, but if it is present, then it is used to specify the index of each
1793     * triangle, rather than just walking through the arrays in order.
1794     *
1795     * @param mode How to interpret the array of vertices
1796     * @param vertexCount The number of values in the vertices array (and corresponding texs and
1797     *            colors arrays if non-null). Each logical vertex is two values (x, y), vertexCount
1798     *            must be a multiple of 2.
1799     * @param verts Array of vertices for the mesh
1800     * @param vertOffset Number of values in the verts to skip before drawing.
1801     * @param texs May be null. If not null, specifies the coordinates to sample into the current
1802     *            shader (e.g. bitmap tile or gradient)
1803     * @param texOffset Number of values in texs to skip before drawing.
1804     * @param colors May be null. If not null, specifies a color for each vertex, to be interpolated
1805     *            across the triangle.
1806     * @param colorOffset Number of values in colors to skip before drawing.
1807     * @param indices If not null, array of indices to reference into the vertex (texs, colors)
1808     *            array.
1809     * @param indexCount number of entries in the indices array (if not null).
1810     * @param paint Specifies the shader to use if the texs array is non-null.
1811     */
1812    public void drawVertices(@NonNull VertexMode mode, int vertexCount, @NonNull float[] verts,
1813            int vertOffset, @Nullable float[] texs, int texOffset, @Nullable int[] colors,
1814            int colorOffset, @Nullable short[] indices, int indexOffset, int indexCount,
1815            @NonNull Paint paint) {
1816        super.drawVertices(mode, vertexCount, verts, vertOffset, texs, texOffset,
1817                colors, colorOffset, indices, indexOffset, indexCount, paint);
1818    }
1819}
1820