Home | History | Annotate | Download | only in view
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.view;
     18 
     19 import android.annotation.ColorInt;
     20 import android.annotation.NonNull;
     21 import android.annotation.Nullable;
     22 import android.annotation.Size;
     23 import android.graphics.BaseCanvas;
     24 import android.graphics.Bitmap;
     25 import android.graphics.Canvas;
     26 import android.graphics.Color;
     27 import android.graphics.Matrix;
     28 import android.graphics.NinePatch;
     29 import android.graphics.Paint;
     30 import android.graphics.Path;
     31 import android.graphics.Picture;
     32 import android.graphics.PorterDuff;
     33 import android.graphics.Rect;
     34 import android.graphics.RectF;
     35 import android.graphics.TemporaryBuffer;
     36 import android.text.GraphicsOperations;
     37 import android.text.PrecomputedText;
     38 import android.text.SpannableString;
     39 import android.text.SpannedString;
     40 import android.text.TextUtils;
     41 
     42 import dalvik.annotation.optimization.FastNative;
     43 
     44 /**
     45  * This class is a base class for canvases that defer drawing operations, so all
     46  * the draw operations can be marked @FastNative. It contains a re-implementation of
     47  * all the methods in {@link BaseCanvas}.
     48  *
     49  * @hide
     50  */
     51 public class RecordingCanvas extends Canvas {
     52 
     53     public RecordingCanvas(long nativeCanvas) {
     54         super(nativeCanvas);
     55     }
     56 
     57     @Override
     58     public final void drawArc(float left, float top, float right, float bottom, float startAngle,
     59             float sweepAngle, boolean useCenter, @NonNull Paint paint) {
     60         nDrawArc(mNativeCanvasWrapper, left, top, right, bottom, startAngle, sweepAngle,
     61                 useCenter, paint.getNativeInstance());
     62     }
     63 
     64     @Override
     65     public final void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle,
     66             boolean useCenter, @NonNull Paint paint) {
     67         drawArc(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle, useCenter,
     68                 paint);
     69     }
     70 
     71     @Override
     72     public final void drawARGB(int a, int r, int g, int b) {
     73         drawColor(Color.argb(a, r, g, b));
     74     }
     75 
     76     @Override
     77     public final void drawBitmap(@NonNull Bitmap bitmap, float left, float top,
     78             @Nullable Paint paint) {
     79         throwIfCannotDraw(bitmap);
     80         nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top,
     81                 paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity,
     82                 bitmap.mDensity);
     83     }
     84 
     85     @Override
     86     public final void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix,
     87             @Nullable Paint paint) {
     88         nDrawBitmapMatrix(mNativeCanvasWrapper, bitmap, matrix.ni(),
     89                 paint != null ? paint.getNativeInstance() : 0);
     90     }
     91 
     92     @Override
     93     public final void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst,
     94             @Nullable Paint paint) {
     95         if (dst == null) {
     96             throw new NullPointerException();
     97         }
     98         throwIfCannotDraw(bitmap);
     99         final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
    100 
    101         int left, top, right, bottom;
    102         if (src == null) {
    103             left = top = 0;
    104             right = bitmap.getWidth();
    105             bottom = bitmap.getHeight();
    106         } else {
    107             left = src.left;
    108             right = src.right;
    109             top = src.top;
    110             bottom = src.bottom;
    111         }
    112 
    113         nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom,
    114                 dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
    115                 bitmap.mDensity);
    116     }
    117 
    118     @Override
    119     public final void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst,
    120             @Nullable Paint paint) {
    121         if (dst == null) {
    122             throw new NullPointerException();
    123         }
    124         throwIfCannotDraw(bitmap);
    125         final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
    126 
    127         float left, top, right, bottom;
    128         if (src == null) {
    129             left = top = 0;
    130             right = bitmap.getWidth();
    131             bottom = bitmap.getHeight();
    132         } else {
    133             left = src.left;
    134             right = src.right;
    135             top = src.top;
    136             bottom = src.bottom;
    137         }
    138 
    139         nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom,
    140                 dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
    141                 bitmap.mDensity);
    142     }
    143 
    144     /** @deprecated checkstyle */
    145     @Override
    146     @Deprecated
    147     public final void drawBitmap(@NonNull int[] colors, int offset, int stride, float x, float y,
    148             int width, int height, boolean hasAlpha, @Nullable Paint paint) {
    149         // check for valid input
    150         if (width < 0) {
    151             throw new IllegalArgumentException("width must be >= 0");
    152         }
    153         if (height < 0) {
    154             throw new IllegalArgumentException("height must be >= 0");
    155         }
    156         if (Math.abs(stride) < width) {
    157             throw new IllegalArgumentException("abs(stride) must be >= width");
    158         }
    159         int lastScanline = offset + (height - 1) * stride;
    160         int length = colors.length;
    161         if (offset < 0 || (offset + width > length) || lastScanline < 0
    162                 || (lastScanline + width > length)) {
    163             throw new ArrayIndexOutOfBoundsException();
    164         }
    165         // quick escape if there's nothing to draw
    166         if (width == 0 || height == 0) {
    167             return;
    168         }
    169         // punch down to native for the actual draw
    170         nDrawBitmap(mNativeCanvasWrapper, colors, offset, stride, x, y, width, height, hasAlpha,
    171                 paint != null ? paint.getNativeInstance() : 0);
    172     }
    173 
    174     /** @deprecated checkstyle */
    175     @Override
    176     @Deprecated
    177     public final void drawBitmap(@NonNull int[] colors, int offset, int stride, int x, int y,
    178             int width, int height, boolean hasAlpha, @Nullable Paint paint) {
    179         // call through to the common float version
    180         drawBitmap(colors, offset, stride, (float) x, (float) y, width, height,
    181                 hasAlpha, paint);
    182     }
    183 
    184     @Override
    185     public final void drawBitmapMesh(@NonNull Bitmap bitmap, int meshWidth, int meshHeight,
    186             @NonNull float[] verts, int vertOffset, @Nullable int[] colors, int colorOffset,
    187             @Nullable Paint paint) {
    188         if ((meshWidth | meshHeight | vertOffset | colorOffset) < 0) {
    189             throw new ArrayIndexOutOfBoundsException();
    190         }
    191         if (meshWidth == 0 || meshHeight == 0) {
    192             return;
    193         }
    194         int count = (meshWidth + 1) * (meshHeight + 1);
    195         // we mul by 2 since we need two floats per vertex
    196         checkRange(verts.length, vertOffset, count * 2);
    197         if (colors != null) {
    198             // no mul by 2, since we need only 1 color per vertex
    199             checkRange(colors.length, colorOffset, count);
    200         }
    201         nDrawBitmapMesh(mNativeCanvasWrapper, bitmap, meshWidth, meshHeight,
    202                 verts, vertOffset, colors, colorOffset,
    203                 paint != null ? paint.getNativeInstance() : 0);
    204     }
    205 
    206     @Override
    207     public final void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
    208         nDrawCircle(mNativeCanvasWrapper, cx, cy, radius, paint.getNativeInstance());
    209     }
    210 
    211     @Override
    212     public final void drawColor(@ColorInt int color) {
    213         nDrawColor(mNativeCanvasWrapper, color, PorterDuff.Mode.SRC_OVER.nativeInt);
    214     }
    215 
    216     @Override
    217     public final void drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
    218         nDrawColor(mNativeCanvasWrapper, color, mode.nativeInt);
    219     }
    220 
    221     @Override
    222     public final void drawLine(float startX, float startY, float stopX, float stopY,
    223             @NonNull Paint paint) {
    224         nDrawLine(mNativeCanvasWrapper, startX, startY, stopX, stopY, paint.getNativeInstance());
    225     }
    226 
    227     @Override
    228     public final void drawLines(@Size(multiple = 4) @NonNull float[] pts, int offset, int count,
    229             @NonNull Paint paint) {
    230         nDrawLines(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
    231     }
    232 
    233     @Override
    234     public final void drawLines(@Size(multiple = 4) @NonNull float[] pts, @NonNull Paint paint) {
    235         drawLines(pts, 0, pts.length, paint);
    236     }
    237 
    238     @Override
    239     public final void drawOval(float left, float top, float right, float bottom,
    240             @NonNull Paint paint) {
    241         nDrawOval(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
    242     }
    243 
    244     @Override
    245     public final void drawOval(@NonNull RectF oval, @NonNull Paint paint) {
    246         if (oval == null) {
    247             throw new NullPointerException();
    248         }
    249         drawOval(oval.left, oval.top, oval.right, oval.bottom, paint);
    250     }
    251 
    252     @Override
    253     public final void drawPaint(@NonNull Paint paint) {
    254         nDrawPaint(mNativeCanvasWrapper, paint.getNativeInstance());
    255     }
    256 
    257     @Override
    258     public final void drawPatch(@NonNull NinePatch patch, @NonNull Rect dst,
    259             @Nullable Paint paint) {
    260         Bitmap bitmap = patch.getBitmap();
    261         throwIfCannotDraw(bitmap);
    262         final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
    263         nDrawNinePatch(mNativeCanvasWrapper, bitmap.getNativeInstance(), patch.mNativeChunk,
    264                 dst.left, dst.top, dst.right, dst.bottom, nativePaint,
    265                 mDensity, patch.getDensity());
    266     }
    267 
    268     @Override
    269     public final void drawPatch(@NonNull NinePatch patch, @NonNull RectF dst,
    270             @Nullable Paint paint) {
    271         Bitmap bitmap = patch.getBitmap();
    272         throwIfCannotDraw(bitmap);
    273         final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
    274         nDrawNinePatch(mNativeCanvasWrapper, bitmap.getNativeInstance(), patch.mNativeChunk,
    275                 dst.left, dst.top, dst.right, dst.bottom, nativePaint,
    276                 mDensity, patch.getDensity());
    277     }
    278 
    279     @Override
    280     public final void drawPath(@NonNull Path path, @NonNull Paint paint) {
    281         if (path.isSimplePath && path.rects != null) {
    282             nDrawRegion(mNativeCanvasWrapper, path.rects.mNativeRegion, paint.getNativeInstance());
    283         } else {
    284             nDrawPath(mNativeCanvasWrapper, path.readOnlyNI(), paint.getNativeInstance());
    285         }
    286     }
    287 
    288     @Override
    289     public final void drawPicture(@NonNull Picture picture) {
    290         picture.endRecording();
    291         int restoreCount = save();
    292         picture.draw(this);
    293         restoreToCount(restoreCount);
    294     }
    295 
    296     @Override
    297     public final void drawPicture(@NonNull Picture picture, @NonNull Rect dst) {
    298         save();
    299         translate(dst.left, dst.top);
    300         if (picture.getWidth() > 0 && picture.getHeight() > 0) {
    301             scale((float) dst.width() / picture.getWidth(),
    302                     (float) dst.height() / picture.getHeight());
    303         }
    304         drawPicture(picture);
    305         restore();
    306     }
    307 
    308     @Override
    309     public final void drawPicture(@NonNull Picture picture, @NonNull RectF dst) {
    310         save();
    311         translate(dst.left, dst.top);
    312         if (picture.getWidth() > 0 && picture.getHeight() > 0) {
    313             scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
    314         }
    315         drawPicture(picture);
    316         restore();
    317     }
    318 
    319     @Override
    320     public final void drawPoint(float x, float y, @NonNull Paint paint) {
    321         nDrawPoint(mNativeCanvasWrapper, x, y, paint.getNativeInstance());
    322     }
    323 
    324     @Override
    325     public final void drawPoints(@Size(multiple = 2) float[] pts, int offset, int count,
    326             @NonNull Paint paint) {
    327         nDrawPoints(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
    328     }
    329 
    330     @Override
    331     public final void drawPoints(@Size(multiple = 2) @NonNull float[] pts, @NonNull Paint paint) {
    332         drawPoints(pts, 0, pts.length, paint);
    333     }
    334 
    335     /** @deprecated checkstyle */
    336     @Override
    337     @Deprecated
    338     public final void drawPosText(@NonNull char[] text, int index, int count,
    339             @NonNull @Size(multiple = 2) float[] pos,
    340             @NonNull Paint paint) {
    341         if (index < 0 || index + count > text.length || count * 2 > pos.length) {
    342             throw new IndexOutOfBoundsException();
    343         }
    344         for (int i = 0; i < count; i++) {
    345             drawText(text, index + i, 1, pos[i * 2], pos[i * 2 + 1], paint);
    346         }
    347     }
    348 
    349     /** @deprecated checkstyle */
    350     @Override
    351     @Deprecated
    352     public final void drawPosText(@NonNull String text, @NonNull @Size(multiple = 2) float[] pos,
    353             @NonNull Paint paint) {
    354         drawPosText(text.toCharArray(), 0, text.length(), pos, paint);
    355     }
    356 
    357     @Override
    358     public final void drawRect(float left, float top, float right, float bottom,
    359             @NonNull Paint paint) {
    360         nDrawRect(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
    361     }
    362 
    363     @Override
    364     public final void drawRect(@NonNull Rect r, @NonNull Paint paint) {
    365         drawRect(r.left, r.top, r.right, r.bottom, paint);
    366     }
    367 
    368     @Override
    369     public final void drawRect(@NonNull RectF rect, @NonNull Paint paint) {
    370         nDrawRect(mNativeCanvasWrapper,
    371                 rect.left, rect.top, rect.right, rect.bottom, paint.getNativeInstance());
    372     }
    373 
    374     @Override
    375     public final void drawRGB(int r, int g, int b) {
    376         drawColor(Color.rgb(r, g, b));
    377     }
    378 
    379     @Override
    380     public final void drawRoundRect(float left, float top, float right, float bottom,
    381             float rx, float ry, @NonNull Paint paint) {
    382         nDrawRoundRect(mNativeCanvasWrapper, left, top, right, bottom, rx, ry,
    383                 paint.getNativeInstance());
    384     }
    385 
    386     @Override
    387     public final void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) {
    388         drawRoundRect(rect.left, rect.top, rect.right, rect.bottom, rx, ry, paint);
    389     }
    390 
    391     @Override
    392     public final void drawText(@NonNull char[] text, int index, int count, float x, float y,
    393             @NonNull Paint paint) {
    394         if ((index | count | (index + count)
    395                 | (text.length - index - count)) < 0) {
    396             throw new IndexOutOfBoundsException();
    397         }
    398         nDrawText(mNativeCanvasWrapper, text, index, count, x, y, paint.mBidiFlags,
    399                 paint.getNativeInstance());
    400     }
    401 
    402     @Override
    403     public final void drawText(@NonNull CharSequence text, int start, int end, float x, float y,
    404             @NonNull Paint paint) {
    405         if ((start | end | (end - start) | (text.length() - end)) < 0) {
    406             throw new IndexOutOfBoundsException();
    407         }
    408         if (text instanceof String || text instanceof SpannedString
    409                 || text instanceof SpannableString) {
    410             nDrawText(mNativeCanvasWrapper, text.toString(), start, end, x, y,
    411                     paint.mBidiFlags, paint.getNativeInstance());
    412         } else if (text instanceof GraphicsOperations) {
    413             ((GraphicsOperations) text).drawText(this, start, end, x, y,
    414                     paint);
    415         } else {
    416             char[] buf = TemporaryBuffer.obtain(end - start);
    417             TextUtils.getChars(text, start, end, buf, 0);
    418             nDrawText(mNativeCanvasWrapper, buf, 0, end - start, x, y,
    419                     paint.mBidiFlags, paint.getNativeInstance());
    420             TemporaryBuffer.recycle(buf);
    421         }
    422     }
    423 
    424     @Override
    425     public final void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
    426         nDrawText(mNativeCanvasWrapper, text, 0, text.length(), x, y, paint.mBidiFlags,
    427                 paint.getNativeInstance());
    428     }
    429 
    430     @Override
    431     public final void drawText(@NonNull String text, int start, int end, float x, float y,
    432             @NonNull Paint paint) {
    433         if ((start | end | (end - start) | (text.length() - end)) < 0) {
    434             throw new IndexOutOfBoundsException();
    435         }
    436         nDrawText(mNativeCanvasWrapper, text, start, end, x, y, paint.mBidiFlags,
    437                 paint.getNativeInstance());
    438     }
    439 
    440     @Override
    441     public final void drawTextOnPath(@NonNull char[] text, int index, int count, @NonNull Path path,
    442             float hOffset, float vOffset, @NonNull Paint paint) {
    443         if (index < 0 || index + count > text.length) {
    444             throw new ArrayIndexOutOfBoundsException();
    445         }
    446         nDrawTextOnPath(mNativeCanvasWrapper, text, index, count,
    447                 path.readOnlyNI(), hOffset, vOffset,
    448                 paint.mBidiFlags, paint.getNativeInstance());
    449     }
    450 
    451     @Override
    452     public final void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,
    453             float vOffset, @NonNull Paint paint) {
    454         if (text.length() > 0) {
    455             nDrawTextOnPath(mNativeCanvasWrapper, text, path.readOnlyNI(), hOffset, vOffset,
    456                     paint.mBidiFlags, paint.getNativeInstance());
    457         }
    458     }
    459 
    460     @Override
    461     public final void drawTextRun(@NonNull char[] text, int index, int count, int contextIndex,
    462             int contextCount, float x, float y, boolean isRtl, @NonNull Paint paint) {
    463 
    464         if (text == null) {
    465             throw new NullPointerException("text is null");
    466         }
    467         if (paint == null) {
    468             throw new NullPointerException("paint is null");
    469         }
    470         if ((index | count | contextIndex | contextCount | index - contextIndex
    471                 | (contextIndex + contextCount) - (index + count)
    472                 | text.length - (contextIndex + contextCount)) < 0) {
    473             throw new IndexOutOfBoundsException();
    474         }
    475 
    476         nDrawTextRun(mNativeCanvasWrapper, text, index, count, contextIndex, contextCount,
    477                 x, y, isRtl, paint.getNativeInstance(), 0 /* measured text */);
    478     }
    479 
    480     @Override
    481     public final void drawTextRun(@NonNull CharSequence text, int start, int end, int contextStart,
    482             int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) {
    483 
    484         if (text == null) {
    485             throw new NullPointerException("text is null");
    486         }
    487         if (paint == null) {
    488             throw new NullPointerException("paint is null");
    489         }
    490         if ((start | end | contextStart | contextEnd | start - contextStart | end - start
    491                 | contextEnd - end | text.length() - contextEnd) < 0) {
    492             throw new IndexOutOfBoundsException();
    493         }
    494 
    495         if (text instanceof String || text instanceof SpannedString
    496                 || text instanceof SpannableString) {
    497             nDrawTextRun(mNativeCanvasWrapper, text.toString(), start, end, contextStart,
    498                     contextEnd, x, y, isRtl, paint.getNativeInstance());
    499         } else if (text instanceof GraphicsOperations) {
    500             ((GraphicsOperations) text).drawTextRun(this, start, end,
    501                     contextStart, contextEnd, x, y, isRtl, paint);
    502         } else {
    503             int contextLen = contextEnd - contextStart;
    504             int len = end - start;
    505             char[] buf = TemporaryBuffer.obtain(contextLen);
    506             TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
    507             long measuredTextPtr = 0;
    508             if (text instanceof PrecomputedText) {
    509                 PrecomputedText mt = (PrecomputedText) text;
    510                 int paraIndex = mt.findParaIndex(start);
    511                 if (end <= mt.getParagraphEnd(paraIndex)) {
    512                     // Only support if the target is in the same paragraph.
    513                     measuredTextPtr = mt.getMeasuredParagraph(paraIndex).getNativePtr();
    514                 }
    515             }
    516             nDrawTextRun(mNativeCanvasWrapper, buf, start - contextStart, len,
    517                     0, contextLen, x, y, isRtl, paint.getNativeInstance(), measuredTextPtr);
    518             TemporaryBuffer.recycle(buf);
    519         }
    520     }
    521 
    522     @Override
    523     public final void drawVertices(@NonNull VertexMode mode, int vertexCount,
    524             @NonNull float[] verts, int vertOffset, @Nullable float[] texs, int texOffset,
    525             @Nullable int[] colors, int colorOffset, @Nullable short[] indices, int indexOffset,
    526             int indexCount, @NonNull Paint paint) {
    527         checkRange(verts.length, vertOffset, vertexCount);
    528         if (isHardwareAccelerated()) {
    529             return;
    530         }
    531         if (texs != null) {
    532             checkRange(texs.length, texOffset, vertexCount);
    533         }
    534         if (colors != null) {
    535             checkRange(colors.length, colorOffset, vertexCount / 2);
    536         }
    537         if (indices != null) {
    538             checkRange(indices.length, indexOffset, indexCount);
    539         }
    540         nDrawVertices(mNativeCanvasWrapper, mode.nativeInt, vertexCount, verts,
    541                 vertOffset, texs, texOffset, colors, colorOffset,
    542                 indices, indexOffset, indexCount, paint.getNativeInstance());
    543     }
    544 
    545     @FastNative
    546     private static native void nDrawBitmap(long nativeCanvas, Bitmap bitmap, float left, float top,
    547             long nativePaintOrZero, int canvasDensity, int screenDensity, int bitmapDensity);
    548 
    549     @FastNative
    550     private static native void nDrawBitmap(long nativeCanvas, Bitmap bitmap,
    551             float srcLeft, float srcTop, float srcRight, float srcBottom,
    552             float dstLeft, float dstTop, float dstRight, float dstBottom,
    553             long nativePaintOrZero, int screenDensity, int bitmapDensity);
    554 
    555     @FastNative
    556     private static native void nDrawBitmap(long nativeCanvas, int[] colors, int offset, int stride,
    557             float x, float y, int width, int height, boolean hasAlpha, long nativePaintOrZero);
    558 
    559     @FastNative
    560     private static native void nDrawColor(long nativeCanvas, int color, int mode);
    561 
    562     @FastNative
    563     private static native void nDrawPaint(long nativeCanvas, long nativePaint);
    564 
    565     @FastNative
    566     private static native void nDrawPoint(long canvasHandle, float x, float y, long paintHandle);
    567 
    568     @FastNative
    569     private static native void nDrawPoints(long canvasHandle, float[] pts, int offset, int count,
    570             long paintHandle);
    571 
    572     @FastNative
    573     private static native void nDrawLine(long nativeCanvas, float startX, float startY, float stopX,
    574             float stopY, long nativePaint);
    575 
    576     @FastNative
    577     private static native void nDrawLines(long canvasHandle, float[] pts, int offset, int count,
    578             long paintHandle);
    579 
    580     @FastNative
    581     private static native void nDrawRect(long nativeCanvas, float left, float top, float right,
    582             float bottom, long nativePaint);
    583 
    584     @FastNative
    585     private static native void nDrawOval(long nativeCanvas, float left, float top, float right,
    586             float bottom, long nativePaint);
    587 
    588     @FastNative
    589     private static native void nDrawCircle(long nativeCanvas, float cx, float cy, float radius,
    590             long nativePaint);
    591 
    592     @FastNative
    593     private static native void nDrawArc(long nativeCanvas, float left, float top, float right,
    594             float bottom, float startAngle, float sweep, boolean useCenter, long nativePaint);
    595 
    596     @FastNative
    597     private static native void nDrawRoundRect(long nativeCanvas, float left, float top, float right,
    598             float bottom, float rx, float ry, long nativePaint);
    599 
    600     @FastNative
    601     private static native void nDrawPath(long nativeCanvas, long nativePath, long nativePaint);
    602 
    603     @FastNative
    604     private static native void nDrawRegion(long nativeCanvas, long nativeRegion, long nativePaint);
    605 
    606     @FastNative
    607     private static native void nDrawNinePatch(long nativeCanvas, long nativeBitmap, long ninePatch,
    608             float dstLeft, float dstTop, float dstRight, float dstBottom, long nativePaintOrZero,
    609             int screenDensity, int bitmapDensity);
    610 
    611     @FastNative
    612     private static native void nDrawBitmapMatrix(long nativeCanvas, Bitmap bitmap,
    613             long nativeMatrix, long nativePaint);
    614 
    615     @FastNative
    616     private static native void nDrawBitmapMesh(long nativeCanvas, Bitmap bitmap, int meshWidth,
    617             int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset,
    618             long nativePaint);
    619 
    620     @FastNative
    621     private static native void nDrawVertices(long nativeCanvas, int mode, int n, float[] verts,
    622             int vertOffset, float[] texs, int texOffset, int[] colors, int colorOffset,
    623             short[] indices, int indexOffset, int indexCount, long nativePaint);
    624 
    625     @FastNative
    626     private static native void nDrawText(long nativeCanvas, char[] text, int index, int count,
    627             float x, float y, int flags, long nativePaint);
    628 
    629     @FastNative
    630     private static native void nDrawText(long nativeCanvas, String text, int start, int end,
    631             float x, float y, int flags, long nativePaint);
    632 
    633     @FastNative
    634     private static native void nDrawTextRun(long nativeCanvas, String text, int start, int end,
    635             int contextStart, int contextEnd, float x, float y, boolean isRtl, long nativePaint);
    636 
    637     @FastNative
    638     private static native void nDrawTextRun(long nativeCanvas, char[] text, int start, int count,
    639             int contextStart, int contextCount, float x, float y, boolean isRtl, long nativePaint,
    640             long nativePrecomputedText);
    641 
    642     @FastNative
    643     private static native void nDrawTextOnPath(long nativeCanvas, char[] text, int index, int count,
    644             long nativePath, float hOffset, float vOffset, int bidiFlags, long nativePaint);
    645 
    646     @FastNative
    647     private static native void nDrawTextOnPath(long nativeCanvas, String text, long nativePath,
    648             float hOffset, float vOffset, int flags, long nativePaint);
    649 }
    650