Canvas.java revision 8c5759624c71ef701cba6751a030328481b4a83c
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     * @deprecated Region.Op values other than {@link Region.Op#INTERSECT} and
682     * {@link Region.Op#DIFFERENCE} have the ability to expand the clip. The canvas clipping APIs
683     * are intended to only expand the clip as a result of a restore operation. This enables a view
684     * parent to clip a canvas to clearly define the maximal drawing area of its children. The
685     * recommended alternative calls are {@link #clipRect(RectF)} and {@link #clipOutRect(RectF)};
686     */
687    @Deprecated
688    public boolean clipRect(@NonNull RectF rect, @NonNull Region.Op op) {
689        return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
690                op.nativeInt);
691    }
692
693    /**
694     * Modify the current clip with the specified rectangle, which is
695     * expressed in local coordinates.
696     *
697     * @param rect The rectangle to intersect with the current clip.
698     * @param op How the clip is modified
699     * @return true if the resulting clip is non-empty
700     *
701     * @deprecated Region.Op values other than {@link Region.Op#INTERSECT} and
702     * {@link Region.Op#DIFFERENCE} have the ability to expand the clip. The canvas clipping APIs
703     * are intended to only expand the clip as a result of a restore operation. This enables a view
704     * parent to clip a canvas to clearly define the maximal drawing area of its children. The
705     * recommended alternative calls are {@link #clipRect(Rect)} and {@link #clipOutRect(Rect)};
706     */
707    @Deprecated
708    public boolean clipRect(@NonNull Rect rect, @NonNull Region.Op op) {
709        return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
710                op.nativeInt);
711    }
712
713    /**
714     * Intersect the current clip with the specified rectangle, which is
715     * expressed in local coordinates.
716     *
717     * @param rect The rectangle to intersect with the current clip.
718     * @return true if the resulting clip is non-empty
719     */
720    public boolean clipRect(@NonNull RectF rect) {
721        return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
722                Region.Op.INTERSECT.nativeInt);
723    }
724
725    /**
726     * Set the clip to the difference of the current clip and the specified rectangle, which is
727     * expressed in local coordinates.
728     *
729     * @param rect The rectangle to perform a difference op with the current clip.
730     * @return true if the resulting clip is non-empty
731     */
732    public boolean clipOutRect(@NonNull RectF rect) {
733        return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
734                Region.Op.DIFFERENCE.nativeInt);
735    }
736
737    /**
738     * Intersect the current clip with the specified rectangle, which is
739     * expressed in local coordinates.
740     *
741     * @param rect The rectangle to intersect with the current clip.
742     * @return true if the resulting clip is non-empty
743     */
744    public boolean clipRect(@NonNull Rect rect) {
745        return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
746                Region.Op.INTERSECT.nativeInt);
747    }
748
749    /**
750     * Set the clip to the difference of the current clip and the specified rectangle, which is
751     * expressed in local coordinates.
752     *
753     * @param rect The rectangle to perform a difference op with the current clip.
754     * @return true if the resulting clip is non-empty
755     */
756    public boolean clipOutRect(@NonNull Rect rect) {
757        return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
758                Region.Op.DIFFERENCE.nativeInt);
759    }
760
761    /**
762     * Modify 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
768     *               clip
769     * @param right  The right side of the rectangle to intersect with the
770     *               current clip
771     * @param bottom The bottom of the rectangle to intersect with the current
772     *               clip
773     * @param op     How the clip is modified
774     * @return       true if the resulting clip is non-empty
775     *
776     * @deprecated Region.Op values other than {@link Region.Op#INTERSECT} and
777     * {@link Region.Op#DIFFERENCE} have the ability to expand the clip. The canvas clipping APIs
778     * are intended to only expand the clip as a result of a restore operation. This enables a view
779     * parent to clip a canvas to clearly define the maximal drawing area of its children. The
780     * recommended alternative calls are {@link #clipRect(float,float,float,float)} and
781     * {@link #clipOutRect(float,float,float,float)};
782     */
783    @Deprecated
784    public boolean clipRect(float left, float top, float right, float bottom,
785            @NonNull Region.Op op) {
786        return nClipRect(mNativeCanvasWrapper, left, top, right, bottom, op.nativeInt);
787    }
788
789    /**
790     * Intersect the current clip with the specified rectangle, which is
791     * expressed in local coordinates.
792     *
793     * @param left   The left side of the rectangle to intersect with the
794     *               current clip
795     * @param top    The top of the rectangle to intersect with the current clip
796     * @param right  The right side of the rectangle to intersect with the
797     *               current clip
798     * @param bottom The bottom of the rectangle to intersect with the current
799     *               clip
800     * @return       true if the resulting clip is non-empty
801     */
802    public boolean clipRect(float left, float top, float right, float bottom) {
803        return nClipRect(mNativeCanvasWrapper, left, top, right, bottom,
804                Region.Op.INTERSECT.nativeInt);
805    }
806
807    /**
808     * Set the clip to the difference of the current clip and the specified rectangle, which is
809     * expressed in local coordinates.
810     *
811     * @param left   The left side of the rectangle used in the difference operation
812     * @param top    The top of the rectangle used in the difference operation
813     * @param right  The right side of the rectangle used in the difference operation
814     * @param bottom The bottom of the rectangle used in the difference operation
815     * @return       true if the resulting clip is non-empty
816     */
817    public boolean clipOutRect(float left, float top, float right, float bottom) {
818        return nClipRect(mNativeCanvasWrapper, left, top, right, bottom,
819                Region.Op.DIFFERENCE.nativeInt);
820    }
821
822    /**
823     * Intersect the current clip with the specified rectangle, which is
824     * expressed in local coordinates.
825     *
826     * @param left   The left side of the rectangle to intersect with the
827     *               current clip
828     * @param top    The top of the rectangle to intersect with the current clip
829     * @param right  The right side of the rectangle to intersect with the
830     *               current clip
831     * @param bottom The bottom of the rectangle to intersect with the current
832     *               clip
833     * @return       true if the resulting clip is non-empty
834     */
835    public boolean clipRect(int left, int top, int right, int bottom) {
836        return nClipRect(mNativeCanvasWrapper, left, top, right, bottom,
837                Region.Op.INTERSECT.nativeInt);
838    }
839
840    /**
841     * Set the clip to the difference of the current clip and the specified rectangle, which is
842     * expressed in local coordinates.
843     *
844     * @param left   The left side of the rectangle used in the difference operation
845     * @param top    The top of the rectangle used in the difference operation
846     * @param right  The right side of the rectangle used in the difference operation
847     * @param bottom The bottom of the rectangle used in the difference operation
848     * @return       true if the resulting clip is non-empty
849     */
850    public boolean clipOutRect(int left, int top, int right, int bottom) {
851        return nClipRect(mNativeCanvasWrapper, left, top, right, bottom,
852                Region.Op.DIFFERENCE.nativeInt);
853    }
854
855    /**
856        * Modify the current clip with the specified path.
857     *
858     * @param path The path to operate on the current clip
859     * @param op   How the clip is modified
860     * @return     true if the resulting is non-empty
861     *
862     * @deprecated Region.Op values other than {@link Region.Op#INTERSECT} and
863     * {@link Region.Op#DIFFERENCE} have the ability to expand the clip. The canvas clipping APIs
864     * are intended to only expand the clip as a result of a restore operation. This enables a view
865     * parent to clip a canvas to clearly define the maximal drawing area of its children. The
866     * recommended alternative calls are {@link #clipPath(Path)} and
867     * {@link #clipOutPath(Path)};
868     */
869    @Deprecated
870    public boolean clipPath(@NonNull Path path, @NonNull Region.Op op) {
871        return nClipPath(mNativeCanvasWrapper, path.readOnlyNI(), op.nativeInt);
872    }
873
874    /**
875     * Intersect the current clip with the specified path.
876     *
877     * @param path The path to intersect with the current clip
878     * @return     true if the resulting clip is non-empty
879     */
880    public boolean clipPath(@NonNull Path path) {
881        return clipPath(path, Region.Op.INTERSECT);
882    }
883
884    /**
885     * Set the clip to the difference of the current clip and the specified path.
886     *
887     * @param path The path used in the difference operation
888     * @return     true if the resulting clip is non-empty
889     */
890    public boolean clipOutPath(@NonNull Path path) {
891        return clipPath(path, Region.Op.DIFFERENCE);
892    }
893
894    /**
895     * Modify the current clip with the specified region. Note that unlike
896     * clipRect() and clipPath() which transform their arguments by the
897     * current matrix, clipRegion() assumes its argument is already in the
898     * coordinate system of the current layer's bitmap, and so not
899     * transformation is performed.
900     *
901     * @param region The region to operate on the current clip, based on op
902     * @param op How the clip is modified
903     * @return true if the resulting is non-empty
904     *
905     * @removed
906     * @deprecated Unlike all other clip calls this API does not respect the
907     *             current matrix. Use {@link #clipRect(Rect)} as an alternative.
908     */
909    @Deprecated
910    public boolean clipRegion(@NonNull Region region, @NonNull Region.Op op) {
911        return false;
912    }
913
914    /**
915     * Intersect the current clip with the specified region. Note that unlike
916     * clipRect() and clipPath() which transform their arguments by the
917     * current matrix, clipRegion() assumes its argument is already in the
918     * coordinate system of the current layer's bitmap, and so not
919     * transformation is performed.
920     *
921     * @param region The region to operate on the current clip, based on op
922     * @return true if the resulting is non-empty
923     *
924     * @removed
925     * @deprecated Unlike all other clip calls this API does not respect the
926     *             current matrix. Use {@link #clipRect(Rect)} as an alternative.
927     */
928    @Deprecated
929    public boolean clipRegion(@NonNull Region region) {
930        return false;
931    }
932
933    public @Nullable DrawFilter getDrawFilter() {
934        return mDrawFilter;
935    }
936
937    public void setDrawFilter(@Nullable DrawFilter filter) {
938        long nativeFilter = 0;
939        if (filter != null) {
940            nativeFilter = filter.mNativeInt;
941        }
942        mDrawFilter = filter;
943        nSetDrawFilter(mNativeCanvasWrapper, nativeFilter);
944    }
945
946    /**
947     * Constant values used as parameters to {@code quickReject()} calls. These values
948     * specify how much space around the shape should be accounted for, depending on whether
949     * the shaped area is antialiased or not.
950     *
951     * @see #quickReject(float, float, float, float, EdgeType)
952     * @see #quickReject(Path, EdgeType)
953     * @see #quickReject(RectF, EdgeType)
954     */
955    public enum EdgeType {
956
957        /**
958         * Black-and-White: Treat edges by just rounding to nearest pixel boundary
959         */
960        BW(0),  //!< treat edges by just rounding to nearest pixel boundary
961
962        /**
963         * Antialiased: Treat edges by rounding-out, since they may be antialiased
964         */
965        AA(1);
966
967        EdgeType(int nativeInt) {
968            this.nativeInt = nativeInt;
969        }
970
971        /**
972         * @hide
973         */
974        public final int nativeInt;
975    }
976
977    /**
978     * Return true if the specified rectangle, after being transformed by the
979     * current matrix, would lie completely outside of the current clip. Call
980     * this to check if an area you intend to draw into is clipped out (and
981     * therefore you can skip making the draw calls).
982     *
983     * @param rect  the rect to compare with the current clip
984     * @param type  {@link Canvas.EdgeType#AA} if the path should be considered antialiased,
985     *              since that means it may affect a larger area (more pixels) than
986     *              non-antialiased ({@link Canvas.EdgeType#BW}).
987     * @return      true if the rect (transformed by the canvas' matrix)
988     *              does not intersect with the canvas' clip
989     */
990    public boolean quickReject(@NonNull RectF rect, @NonNull EdgeType type) {
991        return nQuickReject(mNativeCanvasWrapper,
992                rect.left, rect.top, rect.right, rect.bottom);
993    }
994
995    /**
996     * Return true if the specified path, after being transformed by the
997     * current matrix, would lie completely outside of the current clip. Call
998     * this to check if an area you intend to draw into is clipped out (and
999     * therefore you can skip making the draw calls). Note: for speed it may
1000     * return false even if the path itself might not intersect the clip
1001     * (i.e. the bounds of the path intersects, but the path does not).
1002     *
1003     * @param path        The path to compare with the current clip
1004     * @param type        {@link Canvas.EdgeType#AA} if the path should be considered antialiased,
1005     *                    since that means it may affect a larger area (more pixels) than
1006     *                    non-antialiased ({@link Canvas.EdgeType#BW}).
1007     * @return            true if the path (transformed by the canvas' matrix)
1008     *                    does not intersect with the canvas' clip
1009     */
1010    public boolean quickReject(@NonNull Path path, @NonNull EdgeType type) {
1011        return nQuickReject(mNativeCanvasWrapper, path.readOnlyNI());
1012    }
1013
1014    /**
1015     * Return true if the specified rectangle, after being transformed by the
1016     * current matrix, would lie completely outside of the current clip. Call
1017     * this to check if an area you intend to draw into is clipped out (and
1018     * therefore you can skip making the draw calls).
1019     *
1020     * @param left        The left side of the rectangle to compare with the
1021     *                    current clip
1022     * @param top         The top of the rectangle to compare with the current
1023     *                    clip
1024     * @param right       The right side of the rectangle to compare with the
1025     *                    current clip
1026     * @param bottom      The bottom of the rectangle to compare with the
1027     *                    current clip
1028     * @param type        {@link Canvas.EdgeType#AA} if the path should be considered antialiased,
1029     *                    since that means it may affect a larger area (more pixels) than
1030     *                    non-antialiased ({@link Canvas.EdgeType#BW}).
1031     * @return            true if the rect (transformed by the canvas' matrix)
1032     *                    does not intersect with the canvas' clip
1033     */
1034    public boolean quickReject(float left, float top, float right, float bottom,
1035            @NonNull EdgeType type) {
1036        return nQuickReject(mNativeCanvasWrapper, left, top, right, bottom);
1037    }
1038
1039    /**
1040     * Return the bounds of the current clip (in local coordinates) in the
1041     * bounds parameter, and return true if it is non-empty. This can be useful
1042     * in a way similar to quickReject, in that it tells you that drawing
1043     * outside of these bounds will be clipped out.
1044     *
1045     * @param bounds Return the clip bounds here. If it is null, ignore it but
1046     *               still return true if the current clip is non-empty.
1047     * @return true if the current clip is non-empty.
1048     */
1049    public boolean getClipBounds(@Nullable Rect bounds) {
1050        return nGetClipBounds(mNativeCanvasWrapper, bounds);
1051    }
1052
1053    /**
1054     * Retrieve the bounds of the current clip (in local coordinates).
1055     *
1056     * @return the clip bounds, or [0, 0, 0, 0] if the clip is empty.
1057     */
1058    public final @NonNull Rect getClipBounds() {
1059        Rect r = new Rect();
1060        getClipBounds(r);
1061        return r;
1062    }
1063
1064    /**
1065     * Save the canvas state, draw the picture, and restore the canvas state.
1066     * This differs from picture.draw(canvas), which does not perform any
1067     * save/restore.
1068     *
1069     * <p>
1070     * <strong>Note:</strong> This forces the picture to internally call
1071     * {@link Picture#endRecording} in order to prepare for playback.
1072     *
1073     * @param picture  The picture to be drawn
1074     */
1075    public void drawPicture(@NonNull Picture picture) {
1076        picture.endRecording();
1077        int restoreCount = save();
1078        picture.draw(this);
1079        restoreToCount(restoreCount);
1080    }
1081
1082    /**
1083     * Draw the picture, stretched to fit into the dst rectangle.
1084     */
1085    public void drawPicture(@NonNull Picture picture, @NonNull RectF dst) {
1086        save();
1087        translate(dst.left, dst.top);
1088        if (picture.getWidth() > 0 && picture.getHeight() > 0) {
1089            scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
1090        }
1091        drawPicture(picture);
1092        restore();
1093    }
1094
1095    /**
1096     * Draw the picture, stretched to fit into the dst rectangle.
1097     */
1098    public void drawPicture(@NonNull Picture picture, @NonNull Rect dst) {
1099        save();
1100        translate(dst.left, dst.top);
1101        if (picture.getWidth() > 0 && picture.getHeight() > 0) {
1102            scale((float) dst.width() / picture.getWidth(),
1103                    (float) dst.height() / picture.getHeight());
1104        }
1105        drawPicture(picture);
1106        restore();
1107    }
1108
1109    public enum VertexMode {
1110        TRIANGLES(0),
1111        TRIANGLE_STRIP(1),
1112        TRIANGLE_FAN(2);
1113
1114        VertexMode(int nativeInt) {
1115            this.nativeInt = nativeInt;
1116        }
1117
1118        /**
1119         * @hide
1120         */
1121        public final int nativeInt;
1122    }
1123
1124    /**
1125     * Releases the resources associated with this canvas.
1126     *
1127     * @hide
1128     */
1129    public void release() {
1130        mNativeCanvasWrapper = 0;
1131        if (mFinalizer != null) {
1132            mFinalizer.run();
1133            mFinalizer = null;
1134        }
1135    }
1136
1137    /**
1138     * Free up as much memory as possible from private caches (e.g. fonts, images)
1139     *
1140     * @hide
1141     */
1142    public static void freeCaches() {
1143        nFreeCaches();
1144    }
1145
1146    /**
1147     * Free up text layout caches
1148     *
1149     * @hide
1150     */
1151    public static void freeTextLayoutCaches() {
1152        nFreeTextLayoutCaches();
1153    }
1154
1155    private static native void nFreeCaches();
1156    private static native void nFreeTextLayoutCaches();
1157    private static native long nInitRaster(Bitmap bitmap);
1158    private static native long nGetNativeFinalizer();
1159
1160    // ---------------- @FastNative -------------------
1161
1162    @FastNative
1163    private static native void nSetBitmap(long canvasHandle, Bitmap bitmap);
1164
1165    @FastNative
1166    private static native boolean nGetClipBounds(long nativeCanvas, Rect bounds);
1167
1168    // ---------------- @CriticalNative -------------------
1169
1170    @CriticalNative
1171    private static native boolean nIsOpaque(long canvasHandle);
1172    @CriticalNative
1173    private static native void nSetHighContrastText(long renderer, boolean highContrastText);
1174    @CriticalNative
1175    private static native int nGetWidth(long canvasHandle);
1176    @CriticalNative
1177    private static native int nGetHeight(long canvasHandle);
1178
1179    @CriticalNative
1180    private static native int nSave(long canvasHandle, int saveFlags);
1181    @CriticalNative
1182    private static native int nSaveLayer(long nativeCanvas, float l, float t, float r, float b,
1183            long nativePaint, int layerFlags);
1184    @CriticalNative
1185    private static native int nSaveLayerAlpha(long nativeCanvas, float l, float t, float r, float b,
1186            int alpha, int layerFlags);
1187    @CriticalNative
1188    private static native boolean nRestore(long canvasHandle);
1189    @CriticalNative
1190    private static native void nRestoreToCount(long canvasHandle, int saveCount);
1191    @CriticalNative
1192    private static native int nGetSaveCount(long canvasHandle);
1193
1194    @CriticalNative
1195    private static native void nTranslate(long canvasHandle, float dx, float dy);
1196    @CriticalNative
1197    private static native void nScale(long canvasHandle, float sx, float sy);
1198    @CriticalNative
1199    private static native void nRotate(long canvasHandle, float degrees);
1200    @CriticalNative
1201    private static native void nSkew(long canvasHandle, float sx, float sy);
1202    @CriticalNative
1203    private static native void nConcat(long nativeCanvas, long nativeMatrix);
1204    @CriticalNative
1205    private static native void nSetMatrix(long nativeCanvas, long nativeMatrix);
1206    @CriticalNative
1207    private static native boolean nClipRect(long nativeCanvas,
1208            float left, float top, float right, float bottom, int regionOp);
1209    @CriticalNative
1210    private static native boolean nClipPath(long nativeCanvas, long nativePath, int regionOp);
1211    @CriticalNative
1212    private static native void nSetDrawFilter(long nativeCanvas, long nativeFilter);
1213    @CriticalNative
1214    private static native void nGetMatrix(long nativeCanvas, long nativeMatrix);
1215    @CriticalNative
1216    private static native boolean nQuickReject(long nativeCanvas, long nativePath);
1217    @CriticalNative
1218    private static native boolean nQuickReject(long nativeCanvas, float left, float top,
1219            float right, float bottom);
1220
1221
1222    // ---------------- Draw Methods -------------------
1223
1224    /**
1225     * <p>
1226     * Draw the specified arc, which will be scaled to fit inside the specified oval.
1227     * </p>
1228     * <p>
1229     * If the start angle is negative or >= 360, the start angle is treated as start angle modulo
1230     * 360.
1231     * </p>
1232     * <p>
1233     * If the sweep angle is >= 360, then the oval is drawn completely. Note that this differs
1234     * slightly from SkPath::arcTo, which treats the sweep angle modulo 360. If the sweep angle is
1235     * negative, the sweep angle is treated as sweep angle modulo 360
1236     * </p>
1237     * <p>
1238     * The arc is drawn clockwise. An angle of 0 degrees correspond to the geometric angle of 0
1239     * degrees (3 o'clock on a watch.)
1240     * </p>
1241     *
1242     * @param oval The bounds of oval used to define the shape and size of the arc
1243     * @param startAngle Starting angle (in degrees) where the arc begins
1244     * @param sweepAngle Sweep angle (in degrees) measured clockwise
1245     * @param useCenter If true, include the center of the oval in the arc, and close it if it is
1246     *            being stroked. This will draw a wedge
1247     * @param paint The paint used to draw the arc
1248     */
1249    public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,
1250            @NonNull Paint paint) {
1251        super.drawArc(oval, startAngle, sweepAngle, useCenter, paint);
1252    }
1253
1254    /**
1255     * <p>
1256     * Draw the specified arc, which will be scaled to fit inside the specified oval.
1257     * </p>
1258     * <p>
1259     * If the start angle is negative or >= 360, the start angle is treated as start angle modulo
1260     * 360.
1261     * </p>
1262     * <p>
1263     * If the sweep angle is >= 360, then the oval is drawn completely. Note that this differs
1264     * slightly from SkPath::arcTo, which treats the sweep angle modulo 360. If the sweep angle is
1265     * negative, the sweep angle is treated as sweep angle modulo 360
1266     * </p>
1267     * <p>
1268     * The arc is drawn clockwise. An angle of 0 degrees correspond to the geometric angle of 0
1269     * degrees (3 o'clock on a watch.)
1270     * </p>
1271     *
1272     * @param startAngle Starting angle (in degrees) where the arc begins
1273     * @param sweepAngle Sweep angle (in degrees) measured clockwise
1274     * @param useCenter If true, include the center of the oval in the arc, and close it if it is
1275     *            being stroked. This will draw a wedge
1276     * @param paint The paint used to draw the arc
1277     */
1278    public void drawArc(float left, float top, float right, float bottom, float startAngle,
1279            float sweepAngle, boolean useCenter, @NonNull Paint paint) {
1280        super.drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
1281    }
1282
1283    /**
1284     * Fill the entire canvas' bitmap (restricted to the current clip) with the specified ARGB
1285     * color, using srcover porterduff mode.
1286     *
1287     * @param a alpha component (0..255) of the color to draw onto the canvas
1288     * @param r red component (0..255) of the color to draw onto the canvas
1289     * @param g green component (0..255) of the color to draw onto the canvas
1290     * @param b blue component (0..255) of the color to draw onto the canvas
1291     */
1292    public void drawARGB(int a, int r, int g, int b) {
1293        super.drawARGB(a, r, g, b);
1294    }
1295
1296    /**
1297     * Draw the specified bitmap, with its top/left corner at (x,y), using the specified paint,
1298     * transformed by the current matrix.
1299     * <p>
1300     * Note: if the paint contains a maskfilter that generates a mask which extends beyond the
1301     * bitmap's original width/height (e.g. BlurMaskFilter), then the bitmap will be drawn as if it
1302     * were in a Shader with CLAMP mode. Thus the color outside of the original width/height will be
1303     * the edge color replicated.
1304     * <p>
1305     * If the bitmap and canvas have different densities, this function will take care of
1306     * automatically scaling the bitmap to draw at the same density as the canvas.
1307     *
1308     * @param bitmap The bitmap to be drawn
1309     * @param left The position of the left side of the bitmap being drawn
1310     * @param top The position of the top side of the bitmap being drawn
1311     * @param paint The paint used to draw the bitmap (may be null)
1312     */
1313    public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) {
1314        super.drawBitmap(bitmap, left, top, paint);
1315    }
1316
1317    /**
1318     * Draw the specified bitmap, scaling/translating automatically to fill the destination
1319     * rectangle. If the source rectangle is not null, it specifies the subset of the bitmap to
1320     * draw.
1321     * <p>
1322     * Note: if the paint contains a maskfilter that generates a mask which extends beyond the
1323     * bitmap's original width/height (e.g. BlurMaskFilter), then the bitmap will be drawn as if it
1324     * were in a Shader with CLAMP mode. Thus the color outside of the original width/height will be
1325     * the edge color replicated.
1326     * <p>
1327     * This function <em>ignores the density associated with the bitmap</em>. This is because the
1328     * source and destination rectangle coordinate spaces are in their respective densities, so must
1329     * already have the appropriate scaling factor applied.
1330     *
1331     * @param bitmap The bitmap to be drawn
1332     * @param src May be null. The subset of the bitmap to be drawn
1333     * @param dst The rectangle that the bitmap will be scaled/translated to fit into
1334     * @param paint May be null. The paint used to draw the bitmap
1335     */
1336    public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst,
1337            @Nullable Paint paint) {
1338        super.drawBitmap(bitmap, src, dst, paint);
1339    }
1340
1341    /**
1342     * Draw the specified bitmap, scaling/translating automatically to fill the destination
1343     * rectangle. If the source rectangle is not null, it specifies the subset of the bitmap to
1344     * draw.
1345     * <p>
1346     * Note: if the paint contains a maskfilter that generates a mask which extends beyond the
1347     * bitmap's original width/height (e.g. BlurMaskFilter), then the bitmap will be drawn as if it
1348     * were in a Shader with CLAMP mode. Thus the color outside of the original width/height will be
1349     * the edge color replicated.
1350     * <p>
1351     * This function <em>ignores the density associated with the bitmap</em>. This is because the
1352     * source and destination rectangle coordinate spaces are in their respective densities, so must
1353     * already have the appropriate scaling factor applied.
1354     *
1355     * @param bitmap The bitmap to be drawn
1356     * @param src May be null. The subset of the bitmap to be drawn
1357     * @param dst The rectangle that the bitmap will be scaled/translated to fit into
1358     * @param paint May be null. The paint used to draw the bitmap
1359     */
1360    public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst,
1361            @Nullable Paint paint) {
1362        super.drawBitmap(bitmap, src, dst, paint);
1363    }
1364
1365    /**
1366     * Treat the specified array of colors as a bitmap, and draw it. This gives the same result as
1367     * first creating a bitmap from the array, and then drawing it, but this method avoids
1368     * explicitly creating a bitmap object which can be more efficient if the colors are changing
1369     * often.
1370     *
1371     * @param colors Array of colors representing the pixels of the bitmap
1372     * @param offset Offset into the array of colors for the first pixel
1373     * @param stride The number of colors in the array between rows (must be >= width or <= -width).
1374     * @param x The X coordinate for where to draw the bitmap
1375     * @param y The Y coordinate for where to draw the bitmap
1376     * @param width The width of the bitmap
1377     * @param height The height of the bitmap
1378     * @param hasAlpha True if the alpha channel of the colors contains valid values. If false, the
1379     *            alpha byte is ignored (assumed to be 0xFF for every pixel).
1380     * @param paint May be null. The paint used to draw the bitmap
1381     * @deprecated Usage with a {@link #isHardwareAccelerated() hardware accelerated} canvas
1382     *             requires an internal copy of color buffer contents every time this method is
1383     *             called. Using a Bitmap avoids this copy, and allows the application to more
1384     *             explicitly control the lifetime and copies of pixel data.
1385     */
1386    @Deprecated
1387    public void drawBitmap(@NonNull int[] colors, int offset, int stride, float x, float y,
1388            int width, int height, boolean hasAlpha, @Nullable Paint paint) {
1389        super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint);
1390    }
1391
1392    /**
1393     * Legacy version of drawBitmap(int[] colors, ...) that took ints for x,y
1394     *
1395     * @deprecated Usage with a {@link #isHardwareAccelerated() hardware accelerated} canvas
1396     *             requires an internal copy of color buffer contents every time this method is
1397     *             called. Using a Bitmap avoids this copy, and allows the application to more
1398     *             explicitly control the lifetime and copies of pixel data.
1399     */
1400    @Deprecated
1401    public void drawBitmap(@NonNull int[] colors, int offset, int stride, int x, int y,
1402            int width, int height, boolean hasAlpha, @Nullable Paint paint) {
1403        super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint);
1404    }
1405
1406    /**
1407     * Draw the bitmap using the specified matrix.
1408     *
1409     * @param bitmap The bitmap to draw
1410     * @param matrix The matrix used to transform the bitmap when it is drawn
1411     * @param paint May be null. The paint used to draw the bitmap
1412     */
1413    public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) {
1414        super.drawBitmap(bitmap, matrix, paint);
1415    }
1416
1417    /**
1418     * Draw the bitmap through the mesh, where mesh vertices are evenly distributed across the
1419     * bitmap. There are meshWidth+1 vertices across, and meshHeight+1 vertices down. The verts
1420     * array is accessed in row-major order, so that the first meshWidth+1 vertices are distributed
1421     * across the top of the bitmap from left to right. A more general version of this method is
1422     * drawVertices().
1423     *
1424     * @param bitmap The bitmap to draw using the mesh
1425     * @param meshWidth The number of columns in the mesh. Nothing is drawn if this is 0
1426     * @param meshHeight The number of rows in the mesh. Nothing is drawn if this is 0
1427     * @param verts Array of x,y pairs, specifying where the mesh should be drawn. There must be at
1428     *            least (meshWidth+1) * (meshHeight+1) * 2 + vertOffset values in the array
1429     * @param vertOffset Number of verts elements to skip before drawing
1430     * @param colors May be null. Specifies a color at each vertex, which is interpolated across the
1431     *            cell, and whose values are multiplied by the corresponding bitmap colors. If not
1432     *            null, there must be at least (meshWidth+1) * (meshHeight+1) + colorOffset values
1433     *            in the array.
1434     * @param colorOffset Number of color elements to skip before drawing
1435     * @param paint May be null. The paint used to draw the bitmap
1436     */
1437    public void drawBitmapMesh(@NonNull Bitmap bitmap, int meshWidth, int meshHeight,
1438            @NonNull float[] verts, int vertOffset, @Nullable int[] colors, int colorOffset,
1439            @Nullable Paint paint) {
1440        super.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset, colors, colorOffset,
1441                paint);
1442    }
1443
1444    /**
1445     * Draw the specified circle using the specified paint. If radius is <= 0, then nothing will be
1446     * drawn. The circle will be filled or framed based on the Style in the paint.
1447     *
1448     * @param cx The x-coordinate of the center of the cirle to be drawn
1449     * @param cy The y-coordinate of the center of the cirle to be drawn
1450     * @param radius The radius of the cirle to be drawn
1451     * @param paint The paint used to draw the circle
1452     */
1453    public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
1454        super.drawCircle(cx, cy, radius, paint);
1455    }
1456
1457    /**
1458     * Fill the entire canvas' bitmap (restricted to the current clip) with the specified color,
1459     * using srcover porterduff mode.
1460     *
1461     * @param color the color to draw onto the canvas
1462     */
1463    public void drawColor(@ColorInt int color) {
1464        super.drawColor(color);
1465    }
1466
1467    /**
1468     * Fill the entire canvas' bitmap (restricted to the current clip) with the specified color and
1469     * porter-duff xfermode.
1470     *
1471     * @param color the color to draw with
1472     * @param mode the porter-duff mode to apply to the color
1473     */
1474    public void drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
1475        super.drawColor(color, mode);
1476    }
1477
1478    /**
1479     * Draw a line segment with the specified start and stop x,y coordinates, using the specified
1480     * paint.
1481     * <p>
1482     * Note that since a line is always "framed", the Style is ignored in the paint.
1483     * </p>
1484     * <p>
1485     * Degenerate lines (length is 0) will not be drawn.
1486     * </p>
1487     *
1488     * @param startX The x-coordinate of the start point of the line
1489     * @param startY The y-coordinate of the start point of the line
1490     * @param paint The paint used to draw the line
1491     */
1492    public void drawLine(float startX, float startY, float stopX, float stopY,
1493            @NonNull Paint paint) {
1494        super.drawLine(startX, startY, stopX, stopY, paint);
1495    }
1496
1497    /**
1498     * Draw a series of lines. Each line is taken from 4 consecutive values in the pts array. Thus
1499     * to draw 1 line, the array must contain at least 4 values. This is logically the same as
1500     * drawing the array as follows: drawLine(pts[0], pts[1], pts[2], pts[3]) followed by
1501     * drawLine(pts[4], pts[5], pts[6], pts[7]) and so on.
1502     *
1503     * @param pts Array of points to draw [x0 y0 x1 y1 x2 y2 ...]
1504     * @param offset Number of values in the array to skip before drawing.
1505     * @param count The number of values in the array to process, after skipping "offset" of them.
1506     *            Since each line uses 4 values, the number of "lines" that are drawn is really
1507     *            (count >> 2).
1508     * @param paint The paint used to draw the points
1509     */
1510    public void drawLines(@Size(multiple = 4) @NonNull float[] pts, int offset, int count,
1511            @NonNull Paint paint) {
1512        super.drawLines(pts, offset, count, paint);
1513    }
1514
1515    public void drawLines(@Size(multiple = 4) @NonNull float[] pts, @NonNull Paint paint) {
1516        super.drawLines(pts, paint);
1517    }
1518
1519    /**
1520     * Draw the specified oval using the specified paint. The oval will be filled or framed based on
1521     * the Style in the paint.
1522     *
1523     * @param oval The rectangle bounds of the oval to be drawn
1524     */
1525    public void drawOval(@NonNull RectF oval, @NonNull Paint paint) {
1526        super.drawOval(oval, paint);
1527    }
1528
1529    /**
1530     * Draw the specified oval using the specified paint. The oval will be filled or framed based on
1531     * the Style in the paint.
1532     */
1533    public void drawOval(float left, float top, float right, float bottom, @NonNull Paint paint) {
1534        super.drawOval(left, top, right, bottom, paint);
1535    }
1536
1537    /**
1538     * Fill the entire canvas' bitmap (restricted to the current clip) with the specified paint.
1539     * This is equivalent (but faster) to drawing an infinitely large rectangle with the specified
1540     * paint.
1541     *
1542     * @param paint The paint used to draw onto the canvas
1543     */
1544    public void drawPaint(@NonNull Paint paint) {
1545        super.drawPaint(paint);
1546    }
1547
1548    /**
1549     * Draws the specified bitmap as an N-patch (most often, a 9-patches.)
1550     *
1551     * @param patch The ninepatch object to render
1552     * @param dst The destination rectangle.
1553     * @param paint The paint to draw the bitmap with. may be null
1554     * @hide
1555     */
1556    public void drawPatch(@NonNull NinePatch patch, @NonNull Rect dst, @Nullable Paint paint) {
1557        super.drawPatch(patch, dst, paint);
1558    }
1559
1560    /**
1561     * Draws the specified bitmap as an N-patch (most often, a 9-patches.)
1562     *
1563     * @param patch The ninepatch object to render
1564     * @param dst The destination rectangle.
1565     * @param paint The paint to draw the bitmap with. may be null
1566     * @hide
1567     */
1568    public void drawPatch(@NonNull NinePatch patch, @NonNull RectF dst, @Nullable Paint paint) {
1569        super.drawPatch(patch, dst, paint);
1570    }
1571
1572    /**
1573     * Draw the specified path using the specified paint. The path will be filled or framed based on
1574     * the Style in the paint.
1575     *
1576     * @param path The path to be drawn
1577     * @param paint The paint used to draw the path
1578     */
1579    public void drawPath(@NonNull Path path, @NonNull Paint paint) {
1580        super.drawPath(path, paint);
1581    }
1582
1583    /**
1584     * Helper for drawPoints() for drawing a single point.
1585     */
1586    public void drawPoint(float x, float y, @NonNull Paint paint) {
1587        super.drawPoint(x, y, paint);
1588    }
1589
1590    /**
1591     * Draw a series of points. Each point is centered at the coordinate specified by pts[], and its
1592     * diameter is specified by the paint's stroke width (as transformed by the canvas' CTM), with
1593     * special treatment for a stroke width of 0, which always draws exactly 1 pixel (or at most 4
1594     * if antialiasing is enabled). The shape of the point is controlled by the paint's Cap type.
1595     * The shape is a square, unless the cap type is Round, in which case the shape is a circle.
1596     *
1597     * @param pts Array of points to draw [x0 y0 x1 y1 x2 y2 ...]
1598     * @param offset Number of values to skip before starting to draw.
1599     * @param count The number of values to process, after skipping offset of them. Since one point
1600     *            uses two values, the number of "points" that are drawn is really (count >> 1).
1601     * @param paint The paint used to draw the points
1602     */
1603    public void drawPoints(@Size(multiple = 2) float[] pts, int offset, int count,
1604            @NonNull Paint paint) {
1605        super.drawPoints(pts, offset, count, paint);
1606    }
1607
1608    /**
1609     * Helper for drawPoints() that assumes you want to draw the entire array
1610     */
1611    public void drawPoints(@Size(multiple = 2) @NonNull float[] pts, @NonNull Paint paint) {
1612        super.drawPoints(pts, paint);
1613    }
1614
1615    /**
1616     * Draw the text in the array, with each character's origin specified by the pos array.
1617     *
1618     * @param text The text to be drawn
1619     * @param index The index of the first character to draw
1620     * @param count The number of characters to draw, starting from index.
1621     * @param pos Array of [x,y] positions, used to position each character
1622     * @param paint The paint used for the text (e.g. color, size, style)
1623     * @deprecated This method does not support glyph composition and decomposition and should
1624     *             therefore not be used to render complex scripts. It also doesn't handle
1625     *             supplementary characters (eg emoji).
1626     */
1627    @Deprecated
1628    public void drawPosText(@NonNull char[] text, int index, int count,
1629            @NonNull @Size(multiple = 2) float[] pos,
1630            @NonNull Paint paint) {
1631        super.drawPosText(text, index, count, pos, paint);
1632    }
1633
1634    /**
1635     * Draw the text in the array, with each character's origin specified by the pos array.
1636     *
1637     * @param text The text to be drawn
1638     * @param pos Array of [x,y] positions, used to position each character
1639     * @param paint The paint used for the text (e.g. color, size, style)
1640     * @deprecated This method does not support glyph composition and decomposition and should
1641     *             therefore not be used to render complex scripts. It also doesn't handle
1642     *             supplementary characters (eg emoji).
1643     */
1644    @Deprecated
1645    public void drawPosText(@NonNull String text, @NonNull @Size(multiple = 2) float[] pos,
1646            @NonNull Paint paint) {
1647        super.drawPosText(text, pos, paint);
1648    }
1649
1650    /**
1651     * Draw the specified Rect using the specified paint. The rectangle will be filled or framed
1652     * based on the Style in the paint.
1653     *
1654     * @param rect The rect to be drawn
1655     * @param paint The paint used to draw the rect
1656     */
1657    public void drawRect(@NonNull RectF rect, @NonNull Paint paint) {
1658        super.drawRect(rect, paint);
1659    }
1660
1661    /**
1662     * Draw the specified Rect using the specified Paint. The rectangle will be filled or framed
1663     * based on the Style in the paint.
1664     *
1665     * @param r The rectangle to be drawn.
1666     * @param paint The paint used to draw the rectangle
1667     */
1668    public void drawRect(@NonNull Rect r, @NonNull Paint paint) {
1669        super.drawRect(r, paint);
1670    }
1671
1672    /**
1673     * Draw the specified Rect using the specified paint. The rectangle will be filled or framed
1674     * based on the Style in the paint.
1675     *
1676     * @param left The left side of the rectangle to be drawn
1677     * @param top The top side of the rectangle to be drawn
1678     * @param right The right side of the rectangle to be drawn
1679     * @param bottom The bottom side of the rectangle to be drawn
1680     * @param paint The paint used to draw the rect
1681     */
1682    public void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint) {
1683        super.drawRect(left, top, right, bottom, paint);
1684    }
1685
1686    /**
1687     * Fill the entire canvas' bitmap (restricted to the current clip) with the specified RGB color,
1688     * using srcover porterduff mode.
1689     *
1690     * @param r red component (0..255) of the color to draw onto the canvas
1691     * @param g green component (0..255) of the color to draw onto the canvas
1692     * @param b blue component (0..255) of the color to draw onto the canvas
1693     */
1694    public void drawRGB(int r, int g, int b) {
1695        super.drawRGB(r, g, b);
1696    }
1697
1698    /**
1699     * Draw the specified round-rect using the specified paint. The roundrect will be filled or
1700     * framed based on the Style in the paint.
1701     *
1702     * @param rect The rectangular bounds of the roundRect to be drawn
1703     * @param rx The x-radius of the oval used to round the corners
1704     * @param ry The y-radius of the oval used to round the corners
1705     * @param paint The paint used to draw the roundRect
1706     */
1707    public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) {
1708        super.drawRoundRect(rect, rx, ry, paint);
1709    }
1710
1711    /**
1712     * Draw the specified round-rect using the specified paint. The roundrect will be filled or
1713     * framed based on the Style in the paint.
1714     *
1715     * @param rx The x-radius of the oval used to round the corners
1716     * @param ry The y-radius of the oval used to round the corners
1717     * @param paint The paint used to draw the roundRect
1718     */
1719    public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
1720            @NonNull Paint paint) {
1721        super.drawRoundRect(left, top, right, bottom, rx, ry, paint);
1722    }
1723
1724    /**
1725     * Draw the text, with origin at (x,y), using the specified paint. The origin is interpreted
1726     * based on the Align setting in the paint.
1727     *
1728     * @param text The text to be drawn
1729     * @param x The x-coordinate of the origin of the text being drawn
1730     * @param y The y-coordinate of the baseline of the text being drawn
1731     * @param paint The paint used for the text (e.g. color, size, style)
1732     */
1733    public void drawText(@NonNull char[] text, int index, int count, float x, float y,
1734            @NonNull Paint paint) {
1735        super.drawText(text, index, count, x, y, paint);
1736    }
1737
1738    /**
1739     * Draw the text, with origin at (x,y), using the specified paint. The origin is interpreted
1740     * based on the Align setting in the paint.
1741     *
1742     * @param text The text to be drawn
1743     * @param x The x-coordinate of the origin of the text being drawn
1744     * @param y The y-coordinate of the baseline of the text being drawn
1745     * @param paint The paint used for the text (e.g. color, size, style)
1746     */
1747    public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
1748        super.drawText(text, x, y, paint);
1749    }
1750
1751    /**
1752     * Draw the text, with origin at (x,y), using the specified paint. The origin is interpreted
1753     * based on the Align setting in the paint.
1754     *
1755     * @param text The text to be drawn
1756     * @param start The index of the first character in text to draw
1757     * @param end (end - 1) is the index of the last character in text to draw
1758     * @param x The x-coordinate of the origin of the text being drawn
1759     * @param y The y-coordinate of the baseline of the text being drawn
1760     * @param paint The paint used for the text (e.g. color, size, style)
1761     */
1762    public void drawText(@NonNull String text, int start, int end, float x, float y,
1763            @NonNull Paint paint) {
1764        super.drawText(text, start, end, x, y, paint);
1765    }
1766
1767    /**
1768     * Draw the specified range of text, specified by start/end, with its origin at (x,y), in the
1769     * specified Paint. The origin is interpreted based on the Align setting in the Paint.
1770     *
1771     * @param text The text to be drawn
1772     * @param start The index of the first character in text to draw
1773     * @param end (end - 1) is the index of the last character in text to draw
1774     * @param x The x-coordinate of origin for where to draw the text
1775     * @param y The y-coordinate of origin for where to draw the text
1776     * @param paint The paint used for the text (e.g. color, size, style)
1777     */
1778    public void drawText(@NonNull CharSequence text, int start, int end, float x, float y,
1779            @NonNull Paint paint) {
1780        super.drawText(text, start, end, x, y, paint);
1781    }
1782
1783    /**
1784     * Draw the text, with origin at (x,y), using the specified paint, along the specified path. The
1785     * paint's Align setting determins where along the path to start the text.
1786     *
1787     * @param text The text to be drawn
1788     * @param path The path the text should follow for its baseline
1789     * @param hOffset The distance along the path to add to the text's starting position
1790     * @param vOffset The distance above(-) or below(+) the path to position the text
1791     * @param paint The paint used for the text (e.g. color, size, style)
1792     */
1793    public void drawTextOnPath(@NonNull char[] text, int index, int count, @NonNull Path path,
1794            float hOffset, float vOffset, @NonNull Paint paint) {
1795        super.drawTextOnPath(text, index, count, path, hOffset, vOffset, paint);
1796    }
1797
1798    /**
1799     * Draw the text, with origin at (x,y), using the specified paint, along the specified path. The
1800     * paint's Align setting determins where along the path to start the text.
1801     *
1802     * @param text The text to be drawn
1803     * @param path The path the text should follow for its baseline
1804     * @param hOffset The distance along the path to add to the text's starting position
1805     * @param vOffset The distance above(-) or below(+) the path to position the text
1806     * @param paint The paint used for the text (e.g. color, size, style)
1807     */
1808    public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,
1809            float vOffset, @NonNull Paint paint) {
1810        super.drawTextOnPath(text, path, hOffset, vOffset, paint);
1811    }
1812
1813    /**
1814     * Draw a run of text, all in a single direction, with optional context for complex text
1815     * shaping.
1816     * <p>
1817     * See {@link #drawTextRun(CharSequence, int, int, int, int, float, float, boolean, Paint)} for
1818     * more details. This method uses a character array rather than CharSequence to represent the
1819     * string. Also, to be consistent with the pattern established in {@link #drawText}, in this
1820     * method {@code count} and {@code contextCount} are used rather than offsets of the end
1821     * position; {@code count = end - start, contextCount = contextEnd -
1822     * contextStart}.
1823     *
1824     * @param text the text to render
1825     * @param index the start of the text to render
1826     * @param count the count of chars to render
1827     * @param contextIndex the start of the context for shaping. Must be no greater than index.
1828     * @param contextCount the number of characters in the context for shaping. contexIndex +
1829     *            contextCount must be no less than index + count.
1830     * @param x the x position at which to draw the text
1831     * @param y the y position at which to draw the text
1832     * @param isRtl whether the run is in RTL direction
1833     * @param paint the paint
1834     */
1835    public void drawTextRun(@NonNull char[] text, int index, int count, int contextIndex,
1836            int contextCount, float x, float y, boolean isRtl, @NonNull Paint paint) {
1837        super.drawTextRun(text, index, count, contextIndex, contextCount, x, y, isRtl, paint);
1838    }
1839
1840    /**
1841     * Draw a run of text, all in a single direction, with optional context for complex text
1842     * shaping.
1843     * <p>
1844     * The run of text includes the characters from {@code start} to {@code end} in the text. In
1845     * addition, the range {@code contextStart} to {@code contextEnd} is used as context for the
1846     * purpose of complex text shaping, such as Arabic text potentially shaped differently based on
1847     * the text next to it.
1848     * <p>
1849     * All text outside the range {@code contextStart..contextEnd} is ignored. The text between
1850     * {@code start} and {@code end} will be laid out and drawn.
1851     * <p>
1852     * The direction of the run is explicitly specified by {@code isRtl}. Thus, this method is
1853     * suitable only for runs of a single direction. Alignment of the text is as determined by the
1854     * Paint's TextAlign value. Further, {@code 0 <= contextStart <= start <= end <= contextEnd
1855     * <= text.length} must hold on entry.
1856     * <p>
1857     * Also see {@link android.graphics.Paint#getRunAdvance} for a corresponding method to measure
1858     * the text; the advance width of the text drawn matches the value obtained from that method.
1859     *
1860     * @param text the text to render
1861     * @param start the start of the text to render. Data before this position can be used for
1862     *            shaping context.
1863     * @param end the end of the text to render. Data at or after this position can be used for
1864     *            shaping context.
1865     * @param contextStart the index of the start of the shaping context
1866     * @param contextEnd the index of the end of the shaping context
1867     * @param x the x position at which to draw the text
1868     * @param y the y position at which to draw the text
1869     * @param isRtl whether the run is in RTL direction
1870     * @param paint the paint
1871     * @see #drawTextRun(char[], int, int, int, int, float, float, boolean, Paint)
1872     */
1873    public void drawTextRun(@NonNull CharSequence text, int start, int end, int contextStart,
1874            int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) {
1875        super.drawTextRun(text, start, end, contextStart, contextEnd, x, y, isRtl, paint);
1876    }
1877
1878    /**
1879     * Draw the array of vertices, interpreted as triangles (based on mode). The verts array is
1880     * required, and specifies the x,y pairs for each vertex. If texs is non-null, then it is used
1881     * to specify the coordinate in shader coordinates to use at each vertex (the paint must have a
1882     * shader in this case). If there is no texs array, but there is a color array, then each color
1883     * is interpolated across its corresponding triangle in a gradient. If both texs and colors
1884     * arrays are present, then they behave as before, but the resulting color at each pixels is the
1885     * result of multiplying the colors from the shader and the color-gradient together. The indices
1886     * array is optional, but if it is present, then it is used to specify the index of each
1887     * triangle, rather than just walking through the arrays in order.
1888     *
1889     * @param mode How to interpret the array of vertices
1890     * @param vertexCount The number of values in the vertices array (and corresponding texs and
1891     *            colors arrays if non-null). Each logical vertex is two values (x, y), vertexCount
1892     *            must be a multiple of 2.
1893     * @param verts Array of vertices for the mesh
1894     * @param vertOffset Number of values in the verts to skip before drawing.
1895     * @param texs May be null. If not null, specifies the coordinates to sample into the current
1896     *            shader (e.g. bitmap tile or gradient)
1897     * @param texOffset Number of values in texs to skip before drawing.
1898     * @param colors May be null. If not null, specifies a color for each vertex, to be interpolated
1899     *            across the triangle.
1900     * @param colorOffset Number of values in colors to skip before drawing.
1901     * @param indices If not null, array of indices to reference into the vertex (texs, colors)
1902     *            array.
1903     * @param indexCount number of entries in the indices array (if not null).
1904     * @param paint Specifies the shader to use if the texs array is non-null.
1905     */
1906    public void drawVertices(@NonNull VertexMode mode, int vertexCount, @NonNull float[] verts,
1907            int vertOffset, @Nullable float[] texs, int texOffset, @Nullable int[] colors,
1908            int colorOffset, @Nullable short[] indices, int indexOffset, int indexCount,
1909            @NonNull Paint paint) {
1910        super.drawVertices(mode, vertexCount, verts, vertOffset, texs, texOffset,
1911                colors, colorOffset, indices, indexOffset, indexCount, paint);
1912    }
1913}
1914