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