• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.graphics;
18 
19 import android.annotation.ColorInt;
20 import android.annotation.ColorLong;
21 import android.annotation.IntRange;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.annotation.Size;
25 import android.graphics.fonts.Font;
26 import android.graphics.text.MeasuredText;
27 import android.text.GraphicsOperations;
28 import android.text.MeasuredParagraph;
29 import android.text.PrecomputedText;
30 import android.text.SpannableString;
31 import android.text.SpannedString;
32 import android.text.TextUtils;
33 
34 import com.android.internal.util.Preconditions;
35 
36 import dalvik.annotation.optimization.FastNative;
37 
38 import java.util.Objects;
39 
40 /**
41  * This class is a base class for canvases that defer drawing operations, so all
42  * the draw operations can be marked @FastNative. It contains a re-implementation of
43  * all the methods in {@link BaseCanvas}.
44  *
45  * @hide
46  */
47 @android.ravenwood.annotation.RavenwoodKeepWholeClass
48 public class BaseRecordingCanvas extends Canvas {
49 
BaseRecordingCanvas(long nativeCanvas)50     public BaseRecordingCanvas(long nativeCanvas) {
51         super(nativeCanvas);
52     }
53 
54     @Override
drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint)55     public final void drawArc(float left, float top, float right, float bottom, float startAngle,
56             float sweepAngle, boolean useCenter, @NonNull Paint paint) {
57         nDrawArc(mNativeCanvasWrapper, left, top, right, bottom, startAngle, sweepAngle,
58                 useCenter, paint.getNativeInstance());
59     }
60 
61     @Override
drawArc(@onNull RectF oval, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint)62     public final void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle,
63             boolean useCenter, @NonNull Paint paint) {
64         drawArc(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle, useCenter,
65                 paint);
66     }
67 
68     @Override
drawARGB(int a, int r, int g, int b)69     public final void drawARGB(int a, int r, int g, int b) {
70         drawColor(Color.argb(a, r, g, b));
71     }
72 
73     @Override
drawBitmap(@onNull Bitmap bitmap, float left, float top, @Nullable Paint paint)74     public final void drawBitmap(@NonNull Bitmap bitmap, float left, float top,
75             @Nullable Paint paint) {
76         throwIfCannotDraw(bitmap);
77         nDrawBitmap(mNativeCanvasWrapper, bitmap.getNativeInstance(), left, top,
78                 paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity,
79                 bitmap.mDensity);
80     }
81 
82     @Override
drawBitmap(@onNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint)83     public final void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix,
84             @Nullable Paint paint) {
85         nDrawBitmapMatrix(mNativeCanvasWrapper, bitmap.getNativeInstance(), matrix.ni(),
86                 paint != null ? paint.getNativeInstance() : 0);
87     }
88 
89     @Override
drawBitmap(@onNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst, @Nullable Paint paint)90     public final void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst,
91             @Nullable Paint paint) {
92         if (dst == null) {
93             throw new NullPointerException();
94         }
95         throwIfCannotDraw(bitmap);
96         final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
97 
98         int left, top, right, bottom;
99         if (src == null) {
100             left = top = 0;
101             right = bitmap.getWidth();
102             bottom = bitmap.getHeight();
103         } else {
104             left = src.left;
105             right = src.right;
106             top = src.top;
107             bottom = src.bottom;
108         }
109 
110         nDrawBitmap(mNativeCanvasWrapper, bitmap.getNativeInstance(), left, top, right, bottom,
111                 dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
112                 bitmap.mDensity);
113     }
114 
115     @Override
drawBitmap(@onNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst, @Nullable Paint paint)116     public final void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst,
117             @Nullable Paint paint) {
118         if (dst == null) {
119             throw new NullPointerException();
120         }
121         throwIfCannotDraw(bitmap);
122         final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
123 
124         float left, top, right, bottom;
125         if (src == null) {
126             left = top = 0;
127             right = bitmap.getWidth();
128             bottom = bitmap.getHeight();
129         } else {
130             left = src.left;
131             right = src.right;
132             top = src.top;
133             bottom = src.bottom;
134         }
135 
136         nDrawBitmap(mNativeCanvasWrapper, bitmap.getNativeInstance(), left, top, right, bottom,
137                 dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
138                 bitmap.mDensity);
139     }
140 
141     /** @deprecated checkstyle */
142     @Override
143     @Deprecated
drawBitmap(@onNull int[] colors, int offset, int stride, float x, float y, int width, int height, boolean hasAlpha, @Nullable Paint paint)144     public final void drawBitmap(@NonNull int[] colors, int offset, int stride, float x, float y,
145             int width, int height, boolean hasAlpha, @Nullable Paint paint) {
146         // check for valid input
147         if (width < 0) {
148             throw new IllegalArgumentException("width must be >= 0");
149         }
150         if (height < 0) {
151             throw new IllegalArgumentException("height must be >= 0");
152         }
153         if (Math.abs(stride) < width) {
154             throw new IllegalArgumentException("abs(stride) must be >= width");
155         }
156         int lastScanline = offset + (height - 1) * stride;
157         int length = colors.length;
158         if (offset < 0 || (offset + width > length) || lastScanline < 0
159                 || (lastScanline + width > length)) {
160             throw new ArrayIndexOutOfBoundsException();
161         }
162         // quick escape if there's nothing to draw
163         if (width == 0 || height == 0) {
164             return;
165         }
166         // punch down to native for the actual draw
167         nDrawBitmap(mNativeCanvasWrapper, colors, offset, stride, x, y, width, height, hasAlpha,
168                 paint != null ? paint.getNativeInstance() : 0);
169     }
170 
171     /** @deprecated checkstyle */
172     @Override
173     @Deprecated
drawBitmap(@onNull int[] colors, int offset, int stride, int x, int y, int width, int height, boolean hasAlpha, @Nullable Paint paint)174     public final void drawBitmap(@NonNull int[] colors, int offset, int stride, int x, int y,
175             int width, int height, boolean hasAlpha, @Nullable Paint paint) {
176         // call through to the common float version
177         drawBitmap(colors, offset, stride, (float) x, (float) y, width, height,
178                 hasAlpha, paint);
179     }
180 
181     @Override
drawBitmapMesh(@onNull Bitmap bitmap, int meshWidth, int meshHeight, @NonNull float[] verts, int vertOffset, @Nullable int[] colors, int colorOffset, @Nullable Paint paint)182     public final void drawBitmapMesh(@NonNull Bitmap bitmap, int meshWidth, int meshHeight,
183             @NonNull float[] verts, int vertOffset, @Nullable int[] colors, int colorOffset,
184             @Nullable Paint paint) {
185         if ((meshWidth | meshHeight | vertOffset | colorOffset) < 0) {
186             throw new ArrayIndexOutOfBoundsException();
187         }
188         if (meshWidth == 0 || meshHeight == 0) {
189             return;
190         }
191         int count = (meshWidth + 1) * (meshHeight + 1);
192         // we mul by 2 since we need two floats per vertex
193         checkRange(verts.length, vertOffset, count * 2);
194         if (colors != null) {
195             // no mul by 2, since we need only 1 color per vertex
196             checkRange(colors.length, colorOffset, count);
197         }
198         nDrawBitmapMesh(mNativeCanvasWrapper, bitmap.getNativeInstance(), meshWidth, meshHeight,
199                 verts, vertOffset, colors, colorOffset,
200                 paint != null ? paint.getNativeInstance() : 0);
201     }
202 
203     @Override
drawCircle(float cx, float cy, float radius, @NonNull Paint paint)204     public final void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
205         nDrawCircle(mNativeCanvasWrapper, cx, cy, radius, paint.getNativeInstance());
206     }
207 
208     @Override
drawColor(@olorInt int color)209     public final void drawColor(@ColorInt int color) {
210         nDrawColor(mNativeCanvasWrapper, color, BlendMode.SRC_OVER.getXfermode().porterDuffMode);
211     }
212 
213     @Override
drawColor(@olorInt int color, @NonNull PorterDuff.Mode mode)214     public final void drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
215         nDrawColor(mNativeCanvasWrapper, color, mode.nativeInt);
216     }
217 
218     @Override
drawColor(@olorInt int color, @NonNull BlendMode mode)219     public final void drawColor(@ColorInt int color, @NonNull BlendMode mode) {
220         nDrawColor(mNativeCanvasWrapper, color, mode.getXfermode().porterDuffMode);
221     }
222 
223     @Override
drawColor(@olorLong long color, @NonNull BlendMode mode)224     public final void drawColor(@ColorLong long color, @NonNull BlendMode mode) {
225         ColorSpace cs = Color.colorSpace(color);
226         nDrawColor(mNativeCanvasWrapper, cs.getNativeInstance(), color,
227                 mode.getXfermode().porterDuffMode);
228     }
229 
230     @Override
drawLine(float startX, float startY, float stopX, float stopY, @NonNull Paint paint)231     public final void drawLine(float startX, float startY, float stopX, float stopY,
232             @NonNull Paint paint) {
233         nDrawLine(mNativeCanvasWrapper, startX, startY, stopX, stopY, paint.getNativeInstance());
234     }
235 
236     @Override
drawLines(@izemultiple = 4) @onNull float[] pts, int offset, int count, @NonNull Paint paint)237     public final void drawLines(@Size(multiple = 4) @NonNull float[] pts, int offset, int count,
238             @NonNull Paint paint) {
239         nDrawLines(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
240     }
241 
242     @Override
drawLines(@izemultiple = 4) @onNull float[] pts, @NonNull Paint paint)243     public final void drawLines(@Size(multiple = 4) @NonNull float[] pts, @NonNull Paint paint) {
244         drawLines(pts, 0, pts.length, paint);
245     }
246 
247     @Override
drawOval(float left, float top, float right, float bottom, @NonNull Paint paint)248     public final void drawOval(float left, float top, float right, float bottom,
249             @NonNull Paint paint) {
250         nDrawOval(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
251     }
252 
253     @Override
drawOval(@onNull RectF oval, @NonNull Paint paint)254     public final void drawOval(@NonNull RectF oval, @NonNull Paint paint) {
255         if (oval == null) {
256             throw new NullPointerException();
257         }
258         drawOval(oval.left, oval.top, oval.right, oval.bottom, paint);
259     }
260 
261     @Override
drawPaint(@onNull Paint paint)262     public final void drawPaint(@NonNull Paint paint) {
263         nDrawPaint(mNativeCanvasWrapper, paint.getNativeInstance());
264     }
265 
266     @Override
drawPatch(@onNull NinePatch patch, @NonNull Rect dst, @Nullable Paint paint)267     public final void drawPatch(@NonNull NinePatch patch, @NonNull Rect dst,
268             @Nullable Paint paint) {
269         Bitmap bitmap = patch.getBitmap();
270         throwIfCannotDraw(bitmap);
271         final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
272         nDrawNinePatch(mNativeCanvasWrapper, bitmap.getNativeInstance(), patch.mNativeChunk,
273                 dst.left, dst.top, dst.right, dst.bottom, nativePaint,
274                 mDensity, patch.getDensity());
275     }
276 
277     @Override
drawPatch(@onNull NinePatch patch, @NonNull RectF dst, @Nullable Paint paint)278     public final void drawPatch(@NonNull NinePatch patch, @NonNull RectF dst,
279             @Nullable Paint paint) {
280         Bitmap bitmap = patch.getBitmap();
281         throwIfCannotDraw(bitmap);
282         final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
283         nDrawNinePatch(mNativeCanvasWrapper, bitmap.getNativeInstance(), patch.mNativeChunk,
284                 dst.left, dst.top, dst.right, dst.bottom, nativePaint,
285                 mDensity, patch.getDensity());
286     }
287 
288     @Override
drawPath(@onNull Path path, @NonNull Paint paint)289     public final void drawPath(@NonNull Path path, @NonNull Paint paint) {
290         nDrawPath(mNativeCanvasWrapper, path.readOnlyNI(), paint.getNativeInstance());
291     }
292 
293     @Override
drawRegion(@onNull Region region, @NonNull Paint paint)294     public void drawRegion(@NonNull Region region, @NonNull Paint paint) {
295         nDrawRegion(mNativeCanvasWrapper, region.mNativeRegion, paint.getNativeInstance());
296     }
297 
298     @Override
drawPicture(@onNull Picture picture)299     public final void drawPicture(@NonNull Picture picture) {
300         picture.endRecording();
301         int restoreCount = save();
302         picture.draw(this);
303         restoreToCount(restoreCount);
304     }
305 
306     @Override
drawPicture(@onNull Picture picture, @NonNull Rect dst)307     public final void drawPicture(@NonNull Picture picture, @NonNull Rect dst) {
308         save();
309         translate(dst.left, dst.top);
310         if (picture.getWidth() > 0 && picture.getHeight() > 0) {
311             scale((float) dst.width() / picture.getWidth(),
312                     (float) dst.height() / picture.getHeight());
313         }
314         drawPicture(picture);
315         restore();
316     }
317 
318     @Override
drawPicture(@onNull Picture picture, @NonNull RectF dst)319     public final void drawPicture(@NonNull Picture picture, @NonNull RectF dst) {
320         save();
321         translate(dst.left, dst.top);
322         if (picture.getWidth() > 0 && picture.getHeight() > 0) {
323             scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
324         }
325         drawPicture(picture);
326         restore();
327     }
328 
329     @Override
drawPoint(float x, float y, @NonNull Paint paint)330     public final void drawPoint(float x, float y, @NonNull Paint paint) {
331         nDrawPoint(mNativeCanvasWrapper, x, y, paint.getNativeInstance());
332     }
333 
334     @Override
drawPoints(@izemultiple = 2) float[] pts, int offset, int count, @NonNull Paint paint)335     public final void drawPoints(@Size(multiple = 2) float[] pts, int offset, int count,
336             @NonNull Paint paint) {
337         nDrawPoints(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
338     }
339 
340     @Override
drawPoints(@izemultiple = 2) @onNull float[] pts, @NonNull Paint paint)341     public final void drawPoints(@Size(multiple = 2) @NonNull float[] pts, @NonNull Paint paint) {
342         drawPoints(pts, 0, pts.length, paint);
343     }
344 
345     /** @deprecated checkstyle */
346     @Override
347     @Deprecated
drawPosText(@onNull char[] text, int index, int count, @NonNull @Size(multiple = 2) float[] pos, @NonNull Paint paint)348     public final void drawPosText(@NonNull char[] text, int index, int count,
349             @NonNull @Size(multiple = 2) float[] pos,
350             @NonNull Paint paint) {
351         if (index < 0 || index + count > text.length || count * 2 > pos.length) {
352             throw new IndexOutOfBoundsException();
353         }
354         for (int i = 0; i < count; i++) {
355             drawText(text, index + i, 1, pos[i * 2], pos[i * 2 + 1], paint);
356         }
357     }
358 
359     /** @deprecated checkstyle */
360     @Override
361     @Deprecated
drawPosText(@onNull String text, @NonNull @Size(multiple = 2) float[] pos, @NonNull Paint paint)362     public final void drawPosText(@NonNull String text, @NonNull @Size(multiple = 2) float[] pos,
363             @NonNull Paint paint) {
364         drawPosText(text.toCharArray(), 0, text.length(), pos, paint);
365     }
366 
367     @Override
drawRect(float left, float top, float right, float bottom, @NonNull Paint paint)368     public final void drawRect(float left, float top, float right, float bottom,
369             @NonNull Paint paint) {
370         nDrawRect(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
371     }
372 
373     @Override
drawRect(@onNull Rect r, @NonNull Paint paint)374     public final void drawRect(@NonNull Rect r, @NonNull Paint paint) {
375         drawRect(r.left, r.top, r.right, r.bottom, paint);
376     }
377 
378     @Override
drawRect(@onNull RectF rect, @NonNull Paint paint)379     public final void drawRect(@NonNull RectF rect, @NonNull Paint paint) {
380         nDrawRect(mNativeCanvasWrapper,
381                 rect.left, rect.top, rect.right, rect.bottom, paint.getNativeInstance());
382     }
383 
384     @Override
drawRGB(int r, int g, int b)385     public final void drawRGB(int r, int g, int b) {
386         drawColor(Color.rgb(r, g, b));
387     }
388 
389     @Override
drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, @NonNull Paint paint)390     public final void drawRoundRect(float left, float top, float right, float bottom,
391             float rx, float ry, @NonNull Paint paint) {
392         nDrawRoundRect(mNativeCanvasWrapper, left, top, right, bottom, rx, ry,
393                 paint.getNativeInstance());
394     }
395 
396     @Override
drawRoundRect(@onNull RectF rect, float rx, float ry, @NonNull Paint paint)397     public final void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) {
398         drawRoundRect(rect.left, rect.top, rect.right, rect.bottom, rx, ry, paint);
399     }
400 
401     @Override
drawDoubleRoundRect(@onNull RectF outer, float outerRx, float outerRy, @NonNull RectF inner, float innerRx, float innerRy, @NonNull Paint paint)402     public final void drawDoubleRoundRect(@NonNull RectF outer, float outerRx, float outerRy,
403             @NonNull RectF inner, float innerRx, float innerRy, @NonNull Paint paint) {
404         nDrawDoubleRoundRect(mNativeCanvasWrapper,
405                 outer.left, outer.top, outer.right, outer.bottom, outerRx, outerRy,
406                 inner.left, inner.top, inner.right, inner.bottom, innerRx, innerRy,
407                 paint.getNativeInstance());
408     }
409 
410     @Override
drawDoubleRoundRect(@onNull RectF outer, @NonNull float[] outerRadii, @NonNull RectF inner, @NonNull float[] innerRadii, @NonNull Paint paint)411     public final void drawDoubleRoundRect(@NonNull RectF outer, @NonNull float[] outerRadii,
412             @NonNull RectF inner, @NonNull float[] innerRadii, @NonNull Paint paint) {
413         nDrawDoubleRoundRect(mNativeCanvasWrapper,
414                 outer.left, outer.top, outer.right, outer.bottom, outerRadii,
415                 inner.left, inner.top, inner.right, inner.bottom, innerRadii,
416                 paint.getNativeInstance());
417     }
418 
419     @Override
drawGlyphs( @onNull int[] glyphIds, @IntRange(from = 0) int glyphIdOffset, @NonNull float[] positions, @IntRange(from = 0) int positionOffset, @IntRange(from = 0) int glyphCount, @NonNull Font font, @NonNull Paint paint)420     public void drawGlyphs(
421             @NonNull int[] glyphIds,
422             @IntRange(from = 0) int glyphIdOffset,
423             @NonNull float[] positions,
424             @IntRange(from = 0) int positionOffset,
425             @IntRange(from = 0) int glyphCount,
426             @NonNull Font font,
427             @NonNull Paint paint) {
428         Objects.requireNonNull(glyphIds, "glyphIds must not be null.");
429         Objects.requireNonNull(positions, "positions must not be null.");
430         Objects.requireNonNull(font, "font must not be null.");
431         Objects.requireNonNull(paint, "paint must not be null.");
432         Preconditions.checkArgumentNonnegative(glyphCount);
433 
434         if (glyphIdOffset < 0 || glyphIdOffset + glyphCount > glyphIds.length) {
435             throw new IndexOutOfBoundsException(
436                     "glyphIds must have at least " + (glyphIdOffset + glyphCount) + " of elements");
437         }
438         if (positionOffset < 0 || positionOffset + glyphCount * 2 > positions.length) {
439             throw new IndexOutOfBoundsException(
440                     "positions must have at least " + (positionOffset + glyphCount * 2)
441                             + " of elements");
442         }
443         nDrawGlyphs(mNativeCanvasWrapper, glyphIds, positions, glyphIdOffset, positionOffset,
444                 glyphCount, font.getNativePtr(), paint.getNativeInstance());
445     }
446 
447     @Override
drawText(@onNull char[] text, int index, int count, float x, float y, @NonNull Paint paint)448     public final void drawText(@NonNull char[] text, int index, int count, float x, float y,
449             @NonNull Paint paint) {
450         if ((index | count | (index + count)
451                 | (text.length - index - count)) < 0) {
452             throw new IndexOutOfBoundsException();
453         }
454         nDrawText(mNativeCanvasWrapper, text, index, count, x, y, paint.mBidiFlags,
455                 paint.getNativeInstance());
456     }
457 
458     @Override
drawText(@onNull CharSequence text, int start, int end, float x, float y, @NonNull Paint paint)459     public final void drawText(@NonNull CharSequence text, int start, int end, float x, float y,
460             @NonNull Paint paint) {
461         if ((start | end | (end - start) | (text.length() - end)) < 0) {
462             throw new IndexOutOfBoundsException();
463         }
464         if (text instanceof String || text instanceof SpannedString
465                 || text instanceof SpannableString) {
466             nDrawText(mNativeCanvasWrapper, text.toString(), start, end, x, y,
467                     paint.mBidiFlags, paint.getNativeInstance());
468         } else if (text instanceof GraphicsOperations) {
469             ((GraphicsOperations) text).drawText(this, start, end, x, y,
470                     paint);
471         } else {
472             char[] buf = TemporaryBuffer.obtain(end - start);
473             TextUtils.getChars(text, start, end, buf, 0);
474             nDrawText(mNativeCanvasWrapper, buf, 0, end - start, x, y,
475                     paint.mBidiFlags, paint.getNativeInstance());
476             TemporaryBuffer.recycle(buf);
477         }
478     }
479 
480     @Override
drawText(@onNull String text, float x, float y, @NonNull Paint paint)481     public final void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
482         nDrawText(mNativeCanvasWrapper, text, 0, text.length(), x, y, paint.mBidiFlags,
483                 paint.getNativeInstance());
484     }
485 
486     @Override
drawText(@onNull String text, int start, int end, float x, float y, @NonNull Paint paint)487     public final void drawText(@NonNull String text, int start, int end, float x, float y,
488             @NonNull Paint paint) {
489         if ((start | end | (end - start) | (text.length() - end)) < 0) {
490             throw new IndexOutOfBoundsException();
491         }
492         nDrawText(mNativeCanvasWrapper, text, start, end, x, y, paint.mBidiFlags,
493                 paint.getNativeInstance());
494     }
495 
496     @Override
drawTextOnPath(@onNull char[] text, int index, int count, @NonNull Path path, float hOffset, float vOffset, @NonNull Paint paint)497     public final void drawTextOnPath(@NonNull char[] text, int index, int count, @NonNull Path path,
498             float hOffset, float vOffset, @NonNull Paint paint) {
499         if (index < 0 || index + count > text.length) {
500             throw new ArrayIndexOutOfBoundsException();
501         }
502         nDrawTextOnPath(mNativeCanvasWrapper, text, index, count,
503                 path.readOnlyNI(), hOffset, vOffset,
504                 paint.mBidiFlags, paint.getNativeInstance());
505     }
506 
507     @Override
drawTextOnPath(@onNull String text, @NonNull Path path, float hOffset, float vOffset, @NonNull Paint paint)508     public final void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,
509             float vOffset, @NonNull Paint paint) {
510         if (text.length() > 0) {
511             nDrawTextOnPath(mNativeCanvasWrapper, text, path.readOnlyNI(), hOffset, vOffset,
512                     paint.mBidiFlags, paint.getNativeInstance());
513         }
514     }
515 
516     @Override
drawTextRun(@onNull char[] text, int index, int count, int contextIndex, int contextCount, float x, float y, boolean isRtl, @NonNull Paint paint)517     public final void drawTextRun(@NonNull char[] text, int index, int count, int contextIndex,
518             int contextCount, float x, float y, boolean isRtl, @NonNull Paint paint) {
519 
520         if (text == null) {
521             throw new NullPointerException("text is null");
522         }
523         if (paint == null) {
524             throw new NullPointerException("paint is null");
525         }
526         if ((index | count | contextIndex | contextCount | index - contextIndex
527                 | (contextIndex + contextCount) - (index + count)
528                 | text.length - (contextIndex + contextCount)) < 0) {
529             throw new IndexOutOfBoundsException();
530         }
531 
532         nDrawTextRun(mNativeCanvasWrapper, text, index, count, contextIndex, contextCount,
533                 x, y, isRtl, paint.getNativeInstance(), 0 /* measured text */);
534     }
535 
536     @Override
drawTextRun(@onNull CharSequence text, int start, int end, int contextStart, int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint)537     public final void drawTextRun(@NonNull CharSequence text, int start, int end, int contextStart,
538             int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) {
539 
540         if (text == null) {
541             throw new NullPointerException("text is null");
542         }
543         if (paint == null) {
544             throw new NullPointerException("paint is null");
545         }
546         if ((start | end | contextStart | contextEnd | start - contextStart | end - start
547                 | contextEnd - end | text.length() - contextEnd) < 0) {
548             throw new IndexOutOfBoundsException();
549         }
550 
551         if (text instanceof String || text instanceof SpannedString
552                 || text instanceof SpannableString) {
553             nDrawTextRun(mNativeCanvasWrapper, text.toString(), start, end, contextStart,
554                     contextEnd, x, y, isRtl, paint.getNativeInstance());
555         } else if (text instanceof GraphicsOperations) {
556             ((GraphicsOperations) text).drawTextRun(this, start, end,
557                     contextStart, contextEnd, x, y, isRtl, paint);
558         } else {
559             if (text instanceof PrecomputedText) {
560                 final PrecomputedText pt = (PrecomputedText) text;
561                 final int paraIndex = pt.findParaIndex(start);
562                 if (end <= pt.getParagraphEnd(paraIndex)) {
563                     final int paraStart = pt.getParagraphStart(paraIndex);
564                     final MeasuredParagraph mp = pt.getMeasuredParagraph(paraIndex);
565                     // Only support if the target is in the same paragraph.
566                     drawTextRun(mp.getMeasuredText(),
567                             start - paraStart,
568                             end - paraStart,
569                             contextStart - paraStart,
570                             contextEnd - paraStart,
571                             x, y, isRtl, paint);
572                     return;
573                 }
574             }
575             int contextLen = contextEnd - contextStart;
576             int len = end - start;
577             char[] buf = TemporaryBuffer.obtain(contextLen);
578             TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
579             nDrawTextRun(mNativeCanvasWrapper, buf, start - contextStart, len,
580                     0, contextLen, x, y, isRtl, paint.getNativeInstance(),
581                     0 /* measured paragraph pointer */);
582             TemporaryBuffer.recycle(buf);
583         }
584     }
585 
586     @Override
drawTextRun(@onNull MeasuredText measuredText, int start, int end, int contextStart, int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint)587     public void drawTextRun(@NonNull MeasuredText measuredText, int start, int end,
588             int contextStart, int contextEnd, float x, float y, boolean isRtl,
589             @NonNull Paint paint) {
590         nDrawTextRun(mNativeCanvasWrapper, measuredText.getChars(), start, end - start,
591                 contextStart, contextEnd - contextStart, x, y, isRtl, paint.getNativeInstance(),
592                 measuredText.getNativePtr());
593     }
594 
595     @Override
drawVertices(@onNull VertexMode mode, int vertexCount, @NonNull float[] verts, int vertOffset, @Nullable float[] texs, int texOffset, @Nullable int[] colors, int colorOffset, @Nullable short[] indices, int indexOffset, int indexCount, @NonNull Paint paint)596     public final void drawVertices(@NonNull VertexMode mode, int vertexCount,
597             @NonNull float[] verts, int vertOffset, @Nullable float[] texs, int texOffset,
598             @Nullable int[] colors, int colorOffset, @Nullable short[] indices, int indexOffset,
599             int indexCount, @NonNull Paint paint) {
600         checkRange(verts.length, vertOffset, vertexCount);
601         if (texs != null) {
602             checkRange(texs.length, texOffset, vertexCount);
603         }
604         if (colors != null) {
605             checkRange(colors.length, colorOffset, vertexCount / 2);
606         }
607         if (indices != null) {
608             checkRange(indices.length, indexOffset, indexCount);
609         }
610         nDrawVertices(mNativeCanvasWrapper, mode.nativeInt, vertexCount, verts,
611                 vertOffset, texs, texOffset, colors, colorOffset,
612                 indices, indexOffset, indexCount, paint.getNativeInstance());
613     }
614 
615     @Override
drawMesh(@onNull Mesh mesh, @Nullable BlendMode blendMode, @NonNull Paint paint)616     public final void drawMesh(@NonNull Mesh mesh, @Nullable BlendMode blendMode,
617             @NonNull Paint paint) {
618         if (blendMode == null) {
619             blendMode = BlendMode.MODULATE;
620         }
621         nDrawMesh(mNativeCanvasWrapper, mesh.getNativeWrapperInstance(),
622                 blendMode.getXfermode().porterDuffMode, paint.getNativeInstance());
623     }
624 
625     /**
626      * @hide
627      */
628     @Override
punchHole(float left, float top, float right, float bottom, float rx, float ry, float alpha)629     public void punchHole(float left, float top, float right, float bottom, float rx, float ry,
630             float alpha) {
631         nPunchHole(mNativeCanvasWrapper, left, top, right, bottom, rx, ry, alpha);
632     }
633 
634     @FastNative
nDrawBitmap(long nativeCanvas, long bitmapHandle, float left, float top, long nativePaintOrZero, int canvasDensity, int screenDensity, int bitmapDensity)635     private static native void nDrawBitmap(long nativeCanvas, long bitmapHandle, float left,
636             float top, long nativePaintOrZero, int canvasDensity, int screenDensity,
637             int bitmapDensity);
638 
639     @FastNative
nDrawBitmap(long nativeCanvas, long bitmapHandle, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, long nativePaintOrZero, int screenDensity, int bitmapDensity)640     private static native void nDrawBitmap(long nativeCanvas, long bitmapHandle,
641             float srcLeft, float srcTop, float srcRight, float srcBottom,
642             float dstLeft, float dstTop, float dstRight, float dstBottom,
643             long nativePaintOrZero, int screenDensity, int bitmapDensity);
644 
645     @FastNative
nDrawBitmap(long nativeCanvas, int[] colors, int offset, int stride, float x, float y, int width, int height, boolean hasAlpha, long nativePaintOrZero)646     private static native void nDrawBitmap(long nativeCanvas, int[] colors, int offset, int stride,
647             float x, float y, int width, int height, boolean hasAlpha, long nativePaintOrZero);
648 
649     @FastNative
nDrawColor(long nativeCanvas, int color, int mode)650     private static native void nDrawColor(long nativeCanvas, int color, int mode);
651 
652     @FastNative
nDrawColor(long nativeCanvas, long nativeColorSpace, @ColorLong long color, int mode)653     private static native void nDrawColor(long nativeCanvas, long nativeColorSpace,
654             @ColorLong long color, int mode);
655 
656     @FastNative
nDrawPaint(long nativeCanvas, long nativePaint)657     private static native void nDrawPaint(long nativeCanvas, long nativePaint);
658 
659     @FastNative
nDrawPoint(long canvasHandle, float x, float y, long paintHandle)660     private static native void nDrawPoint(long canvasHandle, float x, float y, long paintHandle);
661 
662     @FastNative
nDrawPoints(long canvasHandle, float[] pts, int offset, int count, long paintHandle)663     private static native void nDrawPoints(long canvasHandle, float[] pts, int offset, int count,
664             long paintHandle);
665 
666     @FastNative
nDrawLine(long nativeCanvas, float startX, float startY, float stopX, float stopY, long nativePaint)667     private static native void nDrawLine(long nativeCanvas, float startX, float startY, float stopX,
668             float stopY, long nativePaint);
669 
670     @FastNative
nDrawLines(long canvasHandle, float[] pts, int offset, int count, long paintHandle)671     private static native void nDrawLines(long canvasHandle, float[] pts, int offset, int count,
672             long paintHandle);
673 
674     @FastNative
nDrawRect(long nativeCanvas, float left, float top, float right, float bottom, long nativePaint)675     private static native void nDrawRect(long nativeCanvas, float left, float top, float right,
676             float bottom, long nativePaint);
677 
678     @FastNative
nDrawOval(long nativeCanvas, float left, float top, float right, float bottom, long nativePaint)679     private static native void nDrawOval(long nativeCanvas, float left, float top, float right,
680             float bottom, long nativePaint);
681 
682     @FastNative
nDrawCircle(long nativeCanvas, float cx, float cy, float radius, long nativePaint)683     private static native void nDrawCircle(long nativeCanvas, float cx, float cy, float radius,
684             long nativePaint);
685 
686     @FastNative
nDrawArc(long nativeCanvas, float left, float top, float right, float bottom, float startAngle, float sweep, boolean useCenter, long nativePaint)687     private static native void nDrawArc(long nativeCanvas, float left, float top, float right,
688             float bottom, float startAngle, float sweep, boolean useCenter, long nativePaint);
689 
690     @FastNative
nDrawRoundRect(long nativeCanvas, float left, float top, float right, float bottom, float rx, float ry, long nativePaint)691     private static native void nDrawRoundRect(long nativeCanvas, float left, float top, float right,
692             float bottom, float rx, float ry, long nativePaint);
693 
694     @FastNative
nDrawDoubleRoundRect(long nativeCanvas, float outerLeft, float outerTop, float outerRight, float outerBottom, float outerRx, float outerRy, float innerLeft, float innerTop, float innerRight, float innerBottom, float innerRx, float innerRy, long nativePaint)695     private static native void nDrawDoubleRoundRect(long nativeCanvas,
696             float outerLeft, float outerTop, float outerRight, float outerBottom,
697             float outerRx, float outerRy, float innerLeft, float innerTop, float innerRight,
698             float innerBottom, float innerRx, float innerRy, long nativePaint);
699 
700     @FastNative
nDrawDoubleRoundRect(long nativeCanvas, float outerLeft, float outerTop, float outerRight, float outerBottom, float[] outerRadii, float innerLeft, float innerTop, float innerRight, float innerBottom, float[] innerRadii, long nativePaint)701     private static native void nDrawDoubleRoundRect(long nativeCanvas, float outerLeft,
702             float outerTop, float outerRight, float outerBottom, float[] outerRadii,
703             float innerLeft, float innerTop, float innerRight, float innerBottom,
704             float[] innerRadii, long nativePaint);
705 
706     @FastNative
nDrawPath(long nativeCanvas, long nativePath, long nativePaint)707     private static native void nDrawPath(long nativeCanvas, long nativePath, long nativePaint);
708 
709     @FastNative
nDrawRegion(long nativeCanvas, long nativeRegion, long nativePaint)710     private static native void nDrawRegion(long nativeCanvas, long nativeRegion, long nativePaint);
711 
712     @FastNative
nDrawNinePatch(long nativeCanvas, long nativeBitmap, long ninePatch, float dstLeft, float dstTop, float dstRight, float dstBottom, long nativePaintOrZero, int screenDensity, int bitmapDensity)713     private static native void nDrawNinePatch(long nativeCanvas, long nativeBitmap, long ninePatch,
714             float dstLeft, float dstTop, float dstRight, float dstBottom, long nativePaintOrZero,
715             int screenDensity, int bitmapDensity);
716 
717     @FastNative
nDrawBitmapMatrix(long nativeCanvas, long bitmapHandle, long nativeMatrix, long nativePaint)718     private static native void nDrawBitmapMatrix(long nativeCanvas, long bitmapHandle,
719             long nativeMatrix, long nativePaint);
720 
721     @FastNative
nDrawBitmapMesh(long nativeCanvas, long bitmapHandle, int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset, long nativePaint)722     private static native void nDrawBitmapMesh(long nativeCanvas, long bitmapHandle, int meshWidth,
723             int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset,
724             long nativePaint);
725 
726     @FastNative
nDrawMesh( long canvasHandle, long nativeMesh, int mode, long nativePaint)727     private static native void nDrawMesh(
728             long canvasHandle, long nativeMesh, int mode, long nativePaint);
729 
730     @FastNative
nDrawVertices(long nativeCanvas, int mode, int n, float[] verts, int vertOffset, float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices, int indexOffset, int indexCount, long nativePaint)731     private static native void nDrawVertices(long nativeCanvas, int mode, int n, float[] verts,
732             int vertOffset, float[] texs, int texOffset, int[] colors, int colorOffset,
733             short[] indices, int indexOffset, int indexCount, long nativePaint);
734 
735     @FastNative
nDrawGlyphs(long nativeCanvas, int[] glyphIds, float[] positions, int glyphIdStart, int positionStart, int glyphCount, long nativeFont, long nativePaint)736     private static native void nDrawGlyphs(long nativeCanvas, int[] glyphIds, float[] positions,
737             int glyphIdStart, int positionStart, int glyphCount, long nativeFont, long nativePaint);
738 
739     @FastNative
nDrawText(long nativeCanvas, char[] text, int index, int count, float x, float y, int flags, long nativePaint)740     private static native void nDrawText(long nativeCanvas, char[] text, int index, int count,
741             float x, float y, int flags, long nativePaint);
742 
743     @FastNative
nDrawText(long nativeCanvas, String text, int start, int end, float x, float y, int flags, long nativePaint)744     private static native void nDrawText(long nativeCanvas, String text, int start, int end,
745             float x, float y, int flags, long nativePaint);
746 
747     @FastNative
nDrawTextRun(long nativeCanvas, String text, int start, int end, int contextStart, int contextEnd, float x, float y, boolean isRtl, long nativePaint)748     private static native void nDrawTextRun(long nativeCanvas, String text, int start, int end,
749             int contextStart, int contextEnd, float x, float y, boolean isRtl, long nativePaint);
750 
751     @FastNative
nDrawTextRun(long nativeCanvas, char[] text, int start, int count, int contextStart, int contextCount, float x, float y, boolean isRtl, long nativePaint, long nativePrecomputedText)752     private static native void nDrawTextRun(long nativeCanvas, char[] text, int start, int count,
753             int contextStart, int contextCount, float x, float y, boolean isRtl, long nativePaint,
754             long nativePrecomputedText);
755 
756     @FastNative
nDrawTextOnPath(long nativeCanvas, char[] text, int index, int count, long nativePath, float hOffset, float vOffset, int bidiFlags, long nativePaint)757     private static native void nDrawTextOnPath(long nativeCanvas, char[] text, int index, int count,
758             long nativePath, float hOffset, float vOffset, int bidiFlags, long nativePaint);
759 
760     @FastNative
nDrawTextOnPath(long nativeCanvas, String text, long nativePath, float hOffset, float vOffset, int flags, long nativePaint)761     private static native void nDrawTextOnPath(long nativeCanvas, String text, long nativePath,
762             float hOffset, float vOffset, int flags, long nativePaint);
763 
764     @FastNative
nPunchHole(long renderer, float left, float top, float right, float bottom, float rx, float ry, float alpha)765     private static native void nPunchHole(long renderer, float left, float top, float right,
766             float bottom, float rx, float ry, float alpha);
767 }
768