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