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