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