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