• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package android.graphics;
18 
19 import android.annotation.ColorInt;
20 import android.annotation.IntDef;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.Size;
24 import android.os.Build;
25 
26 import dalvik.annotation.optimization.CriticalNative;
27 import dalvik.annotation.optimization.FastNative;
28 
29 import libcore.util.NativeAllocationRegistry;
30 
31 import java.lang.annotation.Retention;
32 import java.lang.annotation.RetentionPolicy;
33 
34 import 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  */
49 public class Canvas extends BaseCanvas {
50     /** @hide */
51     public static boolean sCompatibilityRestore = false;
52     /** @hide */
53     public static boolean sCompatibilitySetBitmap = false;
54 
55     /** @hide */
getNativeCanvasWrapper()56     public long getNativeCanvasWrapper() {
57         return mNativeCanvasWrapper;
58     }
59 
60     /** @hide */
isRecordingFor(Object o)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      */
Canvas()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      */
Canvas(@onNull Bitmap bitmap)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 */
Canvas(long nativeCanvas)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
getGL()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      */
isHardwareAccelerated()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      */
setBitmap(@ullable Bitmap bitmap)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 */
setHighContrastText(boolean highContrastText)203     public void setHighContrastText(boolean highContrastText) {
204         nSetHighContrastText(mNativeCanvasWrapper, highContrastText);
205     }
206 
207     /** @hide */
insertReorderBarrier()208     public void insertReorderBarrier() {}
209 
210     /** @hide */
insertInorderBarrier()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      */
isOpaque()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      */
getWidth()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      */
getHeight()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      */
getDensity()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      */
setDensity(int density)268     public void setDensity(int density) {
269         if (mBitmap != null) {
270             mBitmap.setDensity(density);
271         }
272         mDensity = density;
273     }
274 
275     /** @hide */
setScreenDensity(int density)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      */
getMaximumBitmapWidth()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      */
getMaximumBitmapHeight()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      */
save()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      */
save(@aveflags int saveFlags)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      */
saveLayer(@ullable RectF bounds, @Nullable Paint paint, @Saveflags int saveFlags)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      */
saveLayer(@ullable RectF bounds, @Nullable Paint paint)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      */
saveLayer(float left, float top, float right, float bottom, @Nullable Paint paint, @Saveflags int saveFlags)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      */
saveLayer(float left, float top, float right, float bottom, @Nullable Paint paint)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      */
saveLayerAlpha(@ullable RectF bounds, int alpha, @Saveflags int saveFlags)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      */
saveLayerAlpha(@ullable RectF bounds, int alpha)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      */
saveLayerAlpha(float left, float top, float right, float bottom, int alpha, @Saveflags int saveFlags)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      */
saveLayerAlpha(float left, float top, float right, float bottom, int alpha)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      */
restore()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      */
getSaveCount()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      */
restoreToCount(int saveCount)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     */
translate(float dx, float dy)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      */
scale(float sx, float sy)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      */
scale(float sx, float sy, float px, float py)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      */
rotate(float degrees)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      */
rotate(float degrees, float px, float py)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      */
skew(float sx, float sy)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      */
concat(@ullable Matrix matrix)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      */
setMatrix(@ullable Matrix matrix)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
getMatrix(@onNull Matrix ctm)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
getMatrix()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
clipRect(@onNull RectF rect, @NonNull Region.Op op)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
clipRect(@onNull Rect rect, @NonNull Region.Op op)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      */
clipRect(@onNull RectF rect)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      */
clipOutRect(@onNull RectF rect)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      */
clipRect(@onNull Rect rect)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      */
clipOutRect(@onNull Rect rect)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
clipRect(float left, float top, float right, float bottom, @NonNull Region.Op op)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      */
clipRect(float left, float top, float right, float bottom)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      */
clipOutRect(float left, float top, float right, float bottom)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      */
clipRect(int left, int top, int right, int bottom)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      */
clipOutRect(int left, int top, int right, int bottom)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
clipPath(@onNull Path path, @NonNull Region.Op op)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      */
clipPath(@onNull Path path)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      */
clipOutPath(@onNull Path path)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
clipRegion(@onNull Region region, @NonNull Region.Op op)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
clipRegion(@onNull Region region)1001     public boolean clipRegion(@NonNull Region region) {
1002         return false;
1003     }
1004 
getDrawFilter()1005     public @Nullable DrawFilter getDrawFilter() {
1006         return mDrawFilter;
1007     }
1008 
setDrawFilter(@ullable DrawFilter filter)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 
EdgeType(int nativeInt)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      */
quickReject(@onNull RectF rect, @NonNull EdgeType type)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      */
quickReject(@onNull Path path, @NonNull EdgeType type)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      */
quickReject(float left, float top, float right, float bottom, @NonNull EdgeType type)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      */
getClipBounds(@ullable Rect bounds)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      */
getClipBounds()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      */
drawPicture(@onNull Picture picture)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      */
drawPicture(@onNull Picture picture, @NonNull RectF dst)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      */
drawPicture(@onNull Picture picture, @NonNull Rect dst)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 
VertexMode(int nativeInt)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      */
release()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      */
freeCaches()1214     public static void freeCaches() {
1215         nFreeCaches();
1216     }
1217 
1218     /**
1219      * Free up text layout caches
1220      *
1221      * @hide
1222      */
freeTextLayoutCaches()1223     public static void freeTextLayoutCaches() {
1224         nFreeTextLayoutCaches();
1225     }
1226 
nFreeCaches()1227     private static native void nFreeCaches();
nFreeTextLayoutCaches()1228     private static native void nFreeTextLayoutCaches();
nInitRaster(Bitmap bitmap)1229     private static native long nInitRaster(Bitmap bitmap);
nGetNativeFinalizer()1230     private static native long nGetNativeFinalizer();
1231 
1232     // ---------------- @FastNative -------------------
1233 
1234     @FastNative
nSetBitmap(long canvasHandle, Bitmap bitmap)1235     private static native void nSetBitmap(long canvasHandle, Bitmap bitmap);
1236 
1237     @FastNative
nGetClipBounds(long nativeCanvas, Rect bounds)1238     private static native boolean nGetClipBounds(long nativeCanvas, Rect bounds);
1239 
1240     // ---------------- @CriticalNative -------------------
1241 
1242     @CriticalNative
nIsOpaque(long canvasHandle)1243     private static native boolean nIsOpaque(long canvasHandle);
1244     @CriticalNative
nSetHighContrastText(long renderer, boolean highContrastText)1245     private static native void nSetHighContrastText(long renderer, boolean highContrastText);
1246     @CriticalNative
nGetWidth(long canvasHandle)1247     private static native int nGetWidth(long canvasHandle);
1248     @CriticalNative
nGetHeight(long canvasHandle)1249     private static native int nGetHeight(long canvasHandle);
1250 
1251     @CriticalNative
nSave(long canvasHandle, int saveFlags)1252     private static native int nSave(long canvasHandle, int saveFlags);
1253     @CriticalNative
nSaveLayer(long nativeCanvas, float l, float t, float r, float b, long nativePaint, int layerFlags)1254     private static native int nSaveLayer(long nativeCanvas, float l, float t, float r, float b,
1255             long nativePaint, int layerFlags);
1256     @CriticalNative
nSaveLayerAlpha(long nativeCanvas, float l, float t, float r, float b, int alpha, int layerFlags)1257     private static native int nSaveLayerAlpha(long nativeCanvas, float l, float t, float r, float b,
1258             int alpha, int layerFlags);
1259     @CriticalNative
nRestore(long canvasHandle)1260     private static native boolean nRestore(long canvasHandle);
1261     @CriticalNative
nRestoreToCount(long canvasHandle, int saveCount)1262     private static native void nRestoreToCount(long canvasHandle, int saveCount);
1263     @CriticalNative
nGetSaveCount(long canvasHandle)1264     private static native int nGetSaveCount(long canvasHandle);
1265 
1266     @CriticalNative
nTranslate(long canvasHandle, float dx, float dy)1267     private static native void nTranslate(long canvasHandle, float dx, float dy);
1268     @CriticalNative
nScale(long canvasHandle, float sx, float sy)1269     private static native void nScale(long canvasHandle, float sx, float sy);
1270     @CriticalNative
nRotate(long canvasHandle, float degrees)1271     private static native void nRotate(long canvasHandle, float degrees);
1272     @CriticalNative
nSkew(long canvasHandle, float sx, float sy)1273     private static native void nSkew(long canvasHandle, float sx, float sy);
1274     @CriticalNative
nConcat(long nativeCanvas, long nativeMatrix)1275     private static native void nConcat(long nativeCanvas, long nativeMatrix);
1276     @CriticalNative
nSetMatrix(long nativeCanvas, long nativeMatrix)1277     private static native void nSetMatrix(long nativeCanvas, long nativeMatrix);
1278     @CriticalNative
nClipRect(long nativeCanvas, float left, float top, float right, float bottom, int regionOp)1279     private static native boolean nClipRect(long nativeCanvas,
1280             float left, float top, float right, float bottom, int regionOp);
1281     @CriticalNative
nClipPath(long nativeCanvas, long nativePath, int regionOp)1282     private static native boolean nClipPath(long nativeCanvas, long nativePath, int regionOp);
1283     @CriticalNative
nSetDrawFilter(long nativeCanvas, long nativeFilter)1284     private static native void nSetDrawFilter(long nativeCanvas, long nativeFilter);
1285     @CriticalNative
nGetMatrix(long nativeCanvas, long nativeMatrix)1286     private static native void nGetMatrix(long nativeCanvas, long nativeMatrix);
1287     @CriticalNative
nQuickReject(long nativeCanvas, long nativePath)1288     private static native boolean nQuickReject(long nativeCanvas, long nativePath);
1289     @CriticalNative
nQuickReject(long nativeCanvas, float left, float top, float right, float bottom)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      */
drawArc(@onNull RectF oval, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint)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      */
drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint)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      */
drawARGB(int a, int r, int g, int b)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      */
drawBitmap(@onNull Bitmap bitmap, float left, float top, @Nullable Paint paint)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      */
drawBitmap(@onNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst, @Nullable Paint paint)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      */
drawBitmap(@onNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst, @Nullable Paint paint)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
drawBitmap(@onNull int[] colors, int offset, int stride, float x, float y, int width, int height, boolean hasAlpha, @Nullable Paint paint)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
drawBitmap(@onNull int[] colors, int offset, int stride, int x, int y, int width, int height, boolean hasAlpha, @Nullable Paint paint)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      */
drawBitmap(@onNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint)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      */
drawBitmapMesh(@onNull Bitmap bitmap, int meshWidth, int meshHeight, @NonNull float[] verts, int vertOffset, @Nullable int[] colors, int colorOffset, @Nullable Paint paint)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      */
drawCircle(float cx, float cy, float radius, @NonNull Paint paint)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      */
drawColor(@olorInt int color)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      */
drawColor(@olorInt int color, @NonNull PorterDuff.Mode mode)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      */
drawLine(float startX, float startY, float stopX, float stopY, @NonNull Paint paint)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      */
drawLines(@izemultiple = 4) @onNull float[] pts, int offset, int count, @NonNull Paint paint)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 
drawLines(@izemultiple = 4) @onNull float[] pts, @NonNull Paint paint)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      */
drawOval(@onNull RectF oval, @NonNull Paint paint)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      */
drawOval(float left, float top, float right, float bottom, @NonNull Paint paint)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      */
drawPaint(@onNull Paint paint)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      */
drawPatch(@onNull NinePatch patch, @NonNull Rect dst, @Nullable Paint paint)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      */
drawPatch(@onNull NinePatch patch, @NonNull RectF dst, @Nullable Paint paint)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      */
drawPath(@onNull Path path, @NonNull Paint paint)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      */
drawPoint(float x, float y, @NonNull Paint paint)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      */
drawPoints(@izemultiple = 2) float[] pts, int offset, int count, @NonNull Paint paint)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      */
drawPoints(@izemultiple = 2) @onNull float[] pts, @NonNull Paint paint)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
drawPosText(@onNull char[] text, int index, int count, @NonNull @Size(multiple = 2) float[] pos, @NonNull Paint paint)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
drawPosText(@onNull String text, @NonNull @Size(multiple = 2) float[] pos, @NonNull Paint paint)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      */
drawRect(@onNull RectF rect, @NonNull Paint paint)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      */
drawRect(@onNull Rect r, @NonNull Paint paint)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      */
drawRect(float left, float top, float right, float bottom, @NonNull Paint paint)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      */
drawRGB(int r, int g, int b)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      */
drawRoundRect(@onNull RectF rect, float rx, float ry, @NonNull Paint paint)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      */
drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, @NonNull Paint paint)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      */
drawText(@onNull char[] text, int index, int count, float x, float y, @NonNull Paint paint)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      */
drawText(@onNull String text, float x, float y, @NonNull Paint paint)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      */
drawText(@onNull String text, int start, int end, float x, float y, @NonNull Paint paint)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      */
drawText(@onNull CharSequence text, int start, int end, float x, float y, @NonNull Paint paint)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      */
drawTextOnPath(@onNull char[] text, int index, int count, @NonNull Path path, float hOffset, float vOffset, @NonNull Paint paint)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      */
drawTextOnPath(@onNull String text, @NonNull Path path, float hOffset, float vOffset, @NonNull Paint paint)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      */
drawTextRun(@onNull char[] text, int index, int count, int contextIndex, int contextCount, float x, float y, boolean isRtl, @NonNull Paint paint)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      */
drawTextRun(@onNull CharSequence text, int start, int end, int contextStart, int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint)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      */
drawVertices(@onNull VertexMode mode, int vertexCount, @NonNull float[] verts, int vertOffset, @Nullable float[] texs, int texOffset, @Nullable int[] colors, int colorOffset, @Nullable short[] indices, int indexOffset, int indexCount, @NonNull Paint paint)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