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