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