GLES20Canvas.java revision cabfcc1364eb7e4de0b15b3574fba45027b45cfc
1/* 2 * Copyright (C) 2010 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 17package android.view; 18 19import android.graphics.Bitmap; 20import android.graphics.Canvas; 21import android.graphics.ColorFilter; 22import android.graphics.DrawFilter; 23import android.graphics.Matrix; 24import android.graphics.Paint; 25import android.graphics.Path; 26import android.graphics.Picture; 27import android.graphics.PorterDuff; 28import android.graphics.Rect; 29import android.graphics.RectF; 30import android.graphics.Region; 31import android.graphics.Shader; 32import android.graphics.TemporaryBuffer; 33import android.text.GraphicsOperations; 34import android.text.SpannableString; 35import android.text.SpannedString; 36import android.text.TextUtils; 37 38/** 39 * An implementation of Canvas on top of OpenGL ES 2.0. 40 */ 41class GLES20Canvas extends HardwareCanvas { 42 private final boolean mOpaque; 43 private int mRenderer; 44 45 // The native renderer will be destroyed when this object dies. 46 // DO NOT overwrite this reference once it is set. 47 private CanvasFinalizer mFinalizer; 48 49 private int mWidth; 50 private int mHeight; 51 52 private final float[] mPoint = new float[2]; 53 private final float[] mLine = new float[4]; 54 55 private final Rect mClipBounds = new Rect(); 56 57 private DrawFilter mFilter; 58 59 /////////////////////////////////////////////////////////////////////////// 60 // JNI 61 /////////////////////////////////////////////////////////////////////////// 62 63 private static native boolean nIsAvailable(); 64 private static boolean sIsAvailable = nIsAvailable(); 65 66 static boolean isAvailable() { 67 return sIsAvailable; 68 } 69 70 /////////////////////////////////////////////////////////////////////////// 71 // Constructors 72 /////////////////////////////////////////////////////////////////////////// 73 74 /** 75 * Creates a canvas to render directly on screen. 76 */ 77 GLES20Canvas(boolean translucent) { 78 this(false, translucent); 79 } 80 81 /** 82 * Creates a canvas to render into an FBO. 83 */ 84 GLES20Canvas(int layer, boolean translucent) { 85 mOpaque = !translucent; 86 mRenderer = nCreateLayerRenderer(layer); 87 setupFinalizer(); 88 } 89 90 protected GLES20Canvas(boolean record, boolean translucent) { 91 mOpaque = !translucent; 92 93 setupRenderer(record); 94 } 95 96 protected void setupRenderer(boolean record) { 97 if (record) { 98 mRenderer = nGetDisplayListRenderer(mRenderer); 99 } else { 100 mRenderer = nCreateRenderer(); 101 } 102 103 setupFinalizer(); 104 } 105 106 private void setupFinalizer() { 107 if (mRenderer == 0) { 108 throw new IllegalStateException("Could not create GLES20Canvas renderer"); 109 } else { 110 mFinalizer = CanvasFinalizer.getFinalizer(mFinalizer, mRenderer); 111 } 112 } 113 114 private static native int nCreateRenderer(); 115 private static native int nCreateLayerRenderer(int layer); 116 private static native int nGetDisplayListRenderer(int renderer); 117 private static native void nDestroyRenderer(int renderer); 118 119 private static class CanvasFinalizer { 120 int mRenderer; 121 122 // Factory method returns new instance if old one is null, or old instance 123 // otherwise, destroying native renderer along the way as necessary 124 static CanvasFinalizer getFinalizer(CanvasFinalizer oldFinalizer, int renderer) { 125 if (oldFinalizer == null) { 126 return new CanvasFinalizer(renderer); 127 } 128 oldFinalizer.replaceNativeObject(renderer); 129 return oldFinalizer; 130 } 131 132 private CanvasFinalizer(int renderer) { 133 mRenderer = renderer; 134 } 135 136 private void replaceNativeObject(int newRenderer) { 137 if (mRenderer != 0 && newRenderer != mRenderer) { 138 nDestroyRenderer(mRenderer); 139 } 140 mRenderer = newRenderer; 141 } 142 143 @Override 144 protected void finalize() throws Throwable { 145 try { 146 replaceNativeObject(0); 147 } finally { 148 super.finalize(); 149 } 150 } 151 } 152 153 /////////////////////////////////////////////////////////////////////////// 154 // Hardware layers 155 /////////////////////////////////////////////////////////////////////////// 156 157 static native int nCreateLayer(int width, int height, boolean isOpaque, int[] layerInfo); 158 static native void nResizeLayer(int layerId, int width, int height, int[] layerInfo); 159 static native void nDestroyLayer(int layerId); 160 static native void nDestroyLayerDeferred(int layerId); 161 162 /////////////////////////////////////////////////////////////////////////// 163 // Canvas management 164 /////////////////////////////////////////////////////////////////////////// 165 166 @Override 167 public boolean isOpaque() { 168 return mOpaque; 169 } 170 171 @Override 172 public int getWidth() { 173 return mWidth; 174 } 175 176 @Override 177 public int getHeight() { 178 return mHeight; 179 } 180 181 /////////////////////////////////////////////////////////////////////////// 182 // Setup 183 /////////////////////////////////////////////////////////////////////////// 184 185 @Override 186 public void setViewport(int width, int height) { 187 mWidth = width; 188 mHeight = height; 189 190 nSetViewport(mRenderer, width, height); 191 } 192 193 private static native void nSetViewport(int renderer, int width, int height); 194 195 /** 196 * @hide 197 */ 198 public static boolean preserveBackBuffer() { 199 return nPreserveBackBuffer(); 200 } 201 202 private static native boolean nPreserveBackBuffer(); 203 204 @Override 205 void onPreDraw(Rect dirty) { 206 if (dirty != null) { 207 nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom, mOpaque); 208 } else { 209 nPrepare(mRenderer, mOpaque); 210 } 211 } 212 213 private static native void nPrepare(int renderer, boolean opaque); 214 private static native void nPrepareDirty(int renderer, int left, int top, int right, int bottom, 215 boolean opaque); 216 217 @Override 218 void onPostDraw() { 219 nFinish(mRenderer); 220 } 221 222 private static native void nFinish(int renderer); 223 224 @Override 225 public boolean callDrawGLFunction(int drawGLFunction) { 226 return nCallDrawGLFunction(mRenderer, drawGLFunction); 227 } 228 229 private static native boolean nCallDrawGLFunction(int renderer, int drawGLFunction); 230 231 /////////////////////////////////////////////////////////////////////////// 232 // Display list 233 /////////////////////////////////////////////////////////////////////////// 234 235 int getDisplayList() { 236 return nGetDisplayList(mRenderer); 237 } 238 239 private static native int nGetDisplayList(int renderer); 240 241 static void destroyDisplayList(int displayList) { 242 nDestroyDisplayList(displayList); 243 } 244 245 private static native void nDestroyDisplayList(int displayList); 246 247 @Override 248 public boolean drawDisplayList(DisplayList displayList, Rect dirty) { 249 return nDrawDisplayList(mRenderer, 250 ((GLES20DisplayList) displayList).mNativeDisplayList, dirty); 251 } 252 253 private static native boolean nDrawDisplayList(int renderer, int displayList, Rect dirty); 254 255 /////////////////////////////////////////////////////////////////////////// 256 // Hardware layer 257 /////////////////////////////////////////////////////////////////////////// 258 259 void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) { 260 final GLES20Layer glLayer = (GLES20Layer) layer; 261 boolean hasColorFilter = paint != null && setupColorFilter(paint); 262 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 263 nDrawLayer(mRenderer, glLayer.getLayer(), x, y, nativePaint); 264 if (hasColorFilter) nResetModifiers(mRenderer); 265 } 266 267 private static native void nDrawLayer(int renderer, int layer, float x, float y, int paint); 268 269 void interrupt() { 270 nInterrupt(mRenderer); 271 } 272 273 void resume() { 274 nResume(mRenderer); 275 } 276 277 private static native void nInterrupt(int renderer); 278 private static native void nResume(int renderer); 279 280 /////////////////////////////////////////////////////////////////////////// 281 // Clipping 282 /////////////////////////////////////////////////////////////////////////// 283 284 @Override 285 public boolean clipPath(Path path) { 286 throw new UnsupportedOperationException(); 287 } 288 289 @Override 290 public boolean clipPath(Path path, Region.Op op) { 291 throw new UnsupportedOperationException(); 292 } 293 294 @Override 295 public boolean clipRect(float left, float top, float right, float bottom) { 296 return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt); 297 } 298 299 private static native boolean nClipRect(int renderer, float left, float top, 300 float right, float bottom, int op); 301 302 @Override 303 public boolean clipRect(float left, float top, float right, float bottom, Region.Op op) { 304 return nClipRect(mRenderer, left, top, right, bottom, op.nativeInt); 305 } 306 307 @Override 308 public boolean clipRect(int left, int top, int right, int bottom) { 309 return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt); 310 } 311 312 private static native boolean nClipRect(int renderer, int left, int top, int right, int bottom, 313 int op); 314 315 @Override 316 public boolean clipRect(Rect rect) { 317 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, 318 Region.Op.INTERSECT.nativeInt); 319 } 320 321 @Override 322 public boolean clipRect(Rect rect, Region.Op op) { 323 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt); 324 } 325 326 @Override 327 public boolean clipRect(RectF rect) { 328 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, 329 Region.Op.INTERSECT.nativeInt); 330 } 331 332 @Override 333 public boolean clipRect(RectF rect, Region.Op op) { 334 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt); 335 } 336 337 @Override 338 public boolean clipRegion(Region region) { 339 throw new UnsupportedOperationException(); 340 } 341 342 @Override 343 public boolean clipRegion(Region region, Region.Op op) { 344 throw new UnsupportedOperationException(); 345 } 346 347 @Override 348 public boolean getClipBounds(Rect bounds) { 349 return nGetClipBounds(mRenderer, bounds); 350 } 351 352 private static native boolean nGetClipBounds(int renderer, Rect bounds); 353 354 @Override 355 public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) { 356 return nQuickReject(mRenderer, left, top, right, bottom, type.nativeInt); 357 } 358 359 private static native boolean nQuickReject(int renderer, float left, float top, 360 float right, float bottom, int edge); 361 362 @Override 363 public boolean quickReject(Path path, EdgeType type) { 364 throw new UnsupportedOperationException(); 365 } 366 367 @Override 368 public boolean quickReject(RectF rect, EdgeType type) { 369 return quickReject(rect.left, rect.top, rect.right, rect.bottom, type); 370 } 371 372 /////////////////////////////////////////////////////////////////////////// 373 // Transformations 374 /////////////////////////////////////////////////////////////////////////// 375 376 @Override 377 public void translate(float dx, float dy) { 378 if (dx != 0.0f || dy != 0.0f) nTranslate(mRenderer, dx, dy); 379 } 380 381 private static native void nTranslate(int renderer, float dx, float dy); 382 383 @Override 384 public void skew(float sx, float sy) { 385 nSkew(mRenderer, sx, sy); 386 } 387 388 private static native void nSkew(int renderer, float sx, float sy); 389 390 @Override 391 public void rotate(float degrees) { 392 nRotate(mRenderer, degrees); 393 } 394 395 private static native void nRotate(int renderer, float degrees); 396 397 @Override 398 public void scale(float sx, float sy) { 399 nScale(mRenderer, sx, sy); 400 } 401 402 private static native void nScale(int renderer, float sx, float sy); 403 404 @Override 405 public void setMatrix(Matrix matrix) { 406 nSetMatrix(mRenderer, matrix.native_instance); 407 } 408 409 private static native void nSetMatrix(int renderer, int matrix); 410 411 @Override 412 public int getNativeMatrix() { 413 return nGetMatrix(mRenderer); 414 } 415 416 private static native int nGetMatrix(int renderer); 417 418 @Override 419 public void getMatrix(Matrix matrix) { 420 nGetMatrix(mRenderer, matrix.native_instance); 421 } 422 423 private static native void nGetMatrix(int renderer, int matrix); 424 425 @Override 426 public void concat(Matrix matrix) { 427 nConcatMatrix(mRenderer, matrix.native_instance); 428 } 429 430 private static native void nConcatMatrix(int renderer, int matrix); 431 432 /////////////////////////////////////////////////////////////////////////// 433 // State management 434 /////////////////////////////////////////////////////////////////////////// 435 436 @Override 437 public int save() { 438 return nSave(mRenderer, Canvas.CLIP_SAVE_FLAG | Canvas.MATRIX_SAVE_FLAG); 439 } 440 441 @Override 442 public int save(int saveFlags) { 443 return nSave(mRenderer, saveFlags); 444 } 445 446 private static native int nSave(int renderer, int flags); 447 448 @Override 449 public int saveLayer(RectF bounds, Paint paint, int saveFlags) { 450 return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags); 451 } 452 453 @Override 454 public int saveLayer(float left, float top, float right, float bottom, Paint paint, 455 int saveFlags) { 456 if (left < right && top < bottom) { 457 boolean hasColorFilter = paint != null && setupColorFilter(paint); 458 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 459 int count = nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags); 460 if (hasColorFilter) nResetModifiers(mRenderer); 461 return count; 462 } 463 return save(saveFlags); 464 } 465 466 private static native int nSaveLayer(int renderer, float left, float top, 467 float right, float bottom, int paint, int saveFlags); 468 469 @Override 470 public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) { 471 return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom, 472 alpha, saveFlags); 473 } 474 475 @Override 476 public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha, 477 int saveFlags) { 478 if (left < right && top < bottom) { 479 return nSaveLayerAlpha(mRenderer, left, top, right, bottom, alpha, saveFlags); 480 } 481 return save(saveFlags); 482 } 483 484 private static native int nSaveLayerAlpha(int renderer, float left, float top, float right, 485 float bottom, int alpha, int saveFlags); 486 487 @Override 488 public void restore() { 489 nRestore(mRenderer); 490 } 491 492 private static native void nRestore(int renderer); 493 494 @Override 495 public void restoreToCount(int saveCount) { 496 nRestoreToCount(mRenderer, saveCount); 497 } 498 499 private static native void nRestoreToCount(int renderer, int saveCount); 500 501 @Override 502 public int getSaveCount() { 503 return nGetSaveCount(mRenderer); 504 } 505 506 private static native int nGetSaveCount(int renderer); 507 508 /////////////////////////////////////////////////////////////////////////// 509 // Filtering 510 /////////////////////////////////////////////////////////////////////////// 511 512 @Override 513 public void setDrawFilter(DrawFilter filter) { 514 mFilter = filter; 515 } 516 517 @Override 518 public DrawFilter getDrawFilter() { 519 return mFilter; 520 } 521 522 /////////////////////////////////////////////////////////////////////////// 523 // Drawing 524 /////////////////////////////////////////////////////////////////////////// 525 526 @Override 527 public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, 528 Paint paint) { 529 boolean hasModifier = setupModifiers(paint); 530 nDrawArc(mRenderer, oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle, 531 useCenter, paint.mNativePaint); 532 if (hasModifier) nResetModifiers(mRenderer); 533 } 534 535 private static native void nDrawArc(int renderer, float left, float top, 536 float right, float bottom, float startAngle, float sweepAngle, 537 boolean useCenter, int paint); 538 539 @Override 540 public void drawARGB(int a, int r, int g, int b) { 541 drawColor((a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF)); 542 } 543 544 @Override 545 public void drawPatch(Bitmap bitmap, byte[] chunks, RectF dst, Paint paint) { 546 // Shaders are ignored when drawing patches 547 boolean hasColorFilter = paint != null && setupColorFilter(paint); 548 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 549 nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, chunks, 550 dst.left, dst.top, dst.right, dst.bottom, nativePaint); 551 if (hasColorFilter) nResetModifiers(mRenderer); 552 } 553 554 private static native void nDrawPatch(int renderer, int bitmap, byte[] buffer, byte[] chunks, 555 float left, float top, float right, float bottom, int paint); 556 557 @Override 558 public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) { 559 // Shaders are ignored when drawing bitmaps 560 boolean hasColorFilter = paint != null && setupColorFilter(paint); 561 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 562 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, nativePaint); 563 if (hasColorFilter) nResetModifiers(mRenderer); 564 } 565 566 private static native void nDrawBitmap( 567 int renderer, int bitmap, byte[] buffer, float left, float top, int paint); 568 569 @Override 570 public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) { 571 // Shaders are ignored when drawing bitmaps 572 boolean hasColorFilter = paint != null && setupColorFilter(paint); 573 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 574 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, 575 matrix.native_instance, nativePaint); 576 if (hasColorFilter) nResetModifiers(mRenderer); 577 } 578 579 private static native void nDrawBitmap(int renderer, int bitmap, byte[] buff, 580 int matrix, int paint); 581 582 @Override 583 public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) { 584 // Shaders are ignored when drawing bitmaps 585 boolean hasColorFilter = paint != null && setupColorFilter(paint); 586 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 587 588 int left, top, right, bottom; 589 if (src == null) { 590 left = top = 0; 591 right = bitmap.getWidth(); 592 bottom = bitmap.getHeight(); 593 } else { 594 left = src.left; 595 right = src.right; 596 top = src.top; 597 bottom = src.bottom; 598 } 599 600 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom, 601 dst.left, dst.top, dst.right, dst.bottom, nativePaint); 602 if (hasColorFilter) nResetModifiers(mRenderer); 603 } 604 605 @Override 606 public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) { 607 // Shaders are ignored when drawing bitmaps 608 boolean hasColorFilter = paint != null && setupColorFilter(paint); 609 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 610 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, src.left, src.top, src.right, 611 src.bottom, dst.left, dst.top, dst.right, dst.bottom, nativePaint); 612 if (hasColorFilter) nResetModifiers(mRenderer); 613 } 614 615 private static native void nDrawBitmap(int renderer, int bitmap, byte[] buffer, 616 float srcLeft, float srcTop, float srcRight, float srcBottom, 617 float left, float top, float right, float bottom, int paint); 618 619 @Override 620 public void drawBitmap(int[] colors, int offset, int stride, float x, float y, 621 int width, int height, boolean hasAlpha, Paint paint) { 622 // Shaders are ignored when drawing bitmaps 623 boolean hasColorFilter = paint != null && setupColorFilter(paint); 624 final Bitmap.Config config = hasAlpha ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; 625 final Bitmap b = Bitmap.createBitmap(colors, offset, stride, width, height, config); 626 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 627 nDrawBitmap(mRenderer, b.mNativeBitmap, b.mBuffer, x, y, nativePaint); 628 b.recycle(); 629 if (hasColorFilter) nResetModifiers(mRenderer); 630 } 631 632 @Override 633 public void drawBitmap(int[] colors, int offset, int stride, int x, int y, 634 int width, int height, boolean hasAlpha, Paint paint) { 635 // Shaders are ignored when drawing bitmaps 636 drawBitmap(colors, offset, stride, (float) x, (float) y, width, height, hasAlpha, paint); 637 } 638 639 @Override 640 public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts, 641 int vertOffset, int[] colors, int colorOffset, Paint paint) { 642 if (meshWidth < 0 || meshHeight < 0 || vertOffset < 0 || colorOffset < 0) { 643 throw new ArrayIndexOutOfBoundsException(); 644 } 645 646 if (meshWidth == 0 || meshHeight == 0) { 647 return; 648 } 649 650 final int count = (meshWidth + 1) * (meshHeight + 1); 651 checkRange(verts.length, vertOffset, count * 2); 652 653 // TODO: Colors are ignored for now 654 colors = null; 655 colorOffset = 0; 656 657 boolean hasColorFilter = paint != null && setupColorFilter(paint); 658 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 659 nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, meshWidth, meshHeight, 660 verts, vertOffset, colors, colorOffset, nativePaint); 661 if (hasColorFilter) nResetModifiers(mRenderer); 662 } 663 664 private static native void nDrawBitmapMesh(int renderer, int bitmap, byte[] buffer, 665 int meshWidth, int meshHeight, float[] verts, int vertOffset, 666 int[] colors, int colorOffset, int paint); 667 668 @Override 669 public void drawCircle(float cx, float cy, float radius, Paint paint) { 670 boolean hasModifier = setupModifiers(paint); 671 nDrawCircle(mRenderer, cx, cy, radius, paint.mNativePaint); 672 if (hasModifier) nResetModifiers(mRenderer); 673 } 674 675 private static native void nDrawCircle(int renderer, float cx, float cy, 676 float radius, int paint); 677 678 @Override 679 public void drawColor(int color) { 680 drawColor(color, PorterDuff.Mode.SRC_OVER); 681 } 682 683 @Override 684 public void drawColor(int color, PorterDuff.Mode mode) { 685 nDrawColor(mRenderer, color, mode.nativeInt); 686 } 687 688 private static native void nDrawColor(int renderer, int color, int mode); 689 690 @Override 691 public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) { 692 mLine[0] = startX; 693 mLine[1] = startY; 694 mLine[2] = stopX; 695 mLine[3] = stopY; 696 drawLines(mLine, 0, 4, paint); 697 } 698 699 @Override 700 public void drawLines(float[] pts, int offset, int count, Paint paint) { 701 if ((offset | count) < 0 || offset + count > pts.length) { 702 throw new IllegalArgumentException("The lines array must contain 4 elements per line."); 703 } 704 boolean hasModifier = setupModifiers(paint); 705 nDrawLines(mRenderer, pts, offset, count, paint.mNativePaint); 706 if (hasModifier) nResetModifiers(mRenderer); 707 } 708 709 private static native void nDrawLines(int renderer, float[] points, 710 int offset, int count, int paint); 711 712 @Override 713 public void drawLines(float[] pts, Paint paint) { 714 drawLines(pts, 0, pts.length, paint); 715 } 716 717 @Override 718 public void drawOval(RectF oval, Paint paint) { 719 boolean hasModifier = setupModifiers(paint); 720 nDrawOval(mRenderer, oval.left, oval.top, oval.right, oval.bottom, paint.mNativePaint); 721 if (hasModifier) nResetModifiers(mRenderer); 722 } 723 724 private static native void nDrawOval(int renderer, float left, float top, 725 float right, float bottom, int paint); 726 727 @Override 728 public void drawPaint(Paint paint) { 729 final Rect r = mClipBounds; 730 nGetClipBounds(mRenderer, r); 731 drawRect(r.left, r.top, r.right, r.bottom, paint); 732 } 733 734 @Override 735 public void drawPath(Path path, Paint paint) { 736 boolean hasModifier = setupModifiers(paint); 737 if (path.isSimplePath) { 738 if (path.rects != null) { 739 nDrawRects(mRenderer, path.rects.mNativeRegion, paint.mNativePaint); 740 } 741 } else { 742 nDrawPath(mRenderer, path.mNativePath, paint.mNativePaint); 743 } 744 if (hasModifier) nResetModifiers(mRenderer); 745 } 746 747 private static native void nDrawPath(int renderer, int path, int paint); 748 private static native void nDrawRects(int renderer, int region, int paint); 749 750 @Override 751 public void drawPicture(Picture picture) { 752 throw new UnsupportedOperationException(); 753 } 754 755 @Override 756 public void drawPicture(Picture picture, Rect dst) { 757 throw new UnsupportedOperationException(); 758 } 759 760 @Override 761 public void drawPicture(Picture picture, RectF dst) { 762 throw new UnsupportedOperationException(); 763 } 764 765 @Override 766 public void drawPoint(float x, float y, Paint paint) { 767 mPoint[0] = x; 768 mPoint[1] = y; 769 drawPoints(mPoint, 0, 1, paint); 770 } 771 772 @Override 773 public void drawPoints(float[] pts, int offset, int count, Paint paint) { 774 // TODO: Implement 775 } 776 777 @Override 778 public void drawPoints(float[] pts, Paint paint) { 779 drawPoints(pts, 0, pts.length / 2, paint); 780 } 781 782 @Override 783 public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) { 784 // TODO: Implement 785 } 786 787 @Override 788 public void drawPosText(String text, float[] pos, Paint paint) { 789 // TODO: Implement 790 } 791 792 @Override 793 public void drawRect(float left, float top, float right, float bottom, Paint paint) { 794 boolean hasModifier = setupModifiers(paint); 795 nDrawRect(mRenderer, left, top, right, bottom, paint.mNativePaint); 796 if (hasModifier) nResetModifiers(mRenderer); 797 } 798 799 private static native void nDrawRect(int renderer, float left, float top, 800 float right, float bottom, int paint); 801 802 @Override 803 public void drawRect(Rect r, Paint paint) { 804 drawRect(r.left, r.top, r.right, r.bottom, paint); 805 } 806 807 @Override 808 public void drawRect(RectF r, Paint paint) { 809 drawRect(r.left, r.top, r.right, r.bottom, paint); 810 } 811 812 @Override 813 public void drawRGB(int r, int g, int b) { 814 drawColor(0xFF000000 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF)); 815 } 816 817 @Override 818 public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) { 819 boolean hasModifier = setupModifiers(paint); 820 nDrawRoundRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, 821 rx, ry, paint.mNativePaint); 822 if (hasModifier) nResetModifiers(mRenderer); 823 } 824 825 private static native void nDrawRoundRect(int renderer, float left, float top, 826 float right, float bottom, float rx, float y, int paint); 827 828 @Override 829 public void drawText(char[] text, int index, int count, float x, float y, Paint paint) { 830 if ((index | count | (index + count) | (text.length - index - count)) < 0) { 831 throw new IndexOutOfBoundsException(); 832 } 833 834 boolean hasModifier = setupModifiers(paint); 835 try { 836 nDrawText(mRenderer, text, index, count, x, y, paint.mBidiFlags, paint.mNativePaint); 837 } finally { 838 if (hasModifier) nResetModifiers(mRenderer); 839 } 840 } 841 842 private static native void nDrawText(int renderer, char[] text, int index, int count, 843 float x, float y, int bidiFlags, int paint); 844 845 @Override 846 public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) { 847 boolean hasModifier = setupModifiers(paint); 848 try { 849 if (text instanceof String || text instanceof SpannedString || 850 text instanceof SpannableString) { 851 nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags, 852 paint.mNativePaint); 853 } else if (text instanceof GraphicsOperations) { 854 ((GraphicsOperations) text).drawText(this, start, end, x, y, 855 paint); 856 } else { 857 char[] buf = TemporaryBuffer.obtain(end - start); 858 TextUtils.getChars(text, start, end, buf, 0); 859 nDrawText(mRenderer, buf, 0, end - start, x, y, 860 paint.mBidiFlags, paint.mNativePaint); 861 TemporaryBuffer.recycle(buf); 862 } 863 } finally { 864 if (hasModifier) nResetModifiers(mRenderer); 865 } 866 } 867 868 @Override 869 public void drawText(String text, int start, int end, float x, float y, Paint paint) { 870 if ((start | end | (end - start) | (text.length() - end)) < 0) { 871 throw new IndexOutOfBoundsException(); 872 } 873 874 boolean hasModifier = setupModifiers(paint); 875 try { 876 nDrawText(mRenderer, text, start, end, x, y, paint.mBidiFlags, paint.mNativePaint); 877 } finally { 878 if (hasModifier) nResetModifiers(mRenderer); 879 } 880 } 881 882 private static native void nDrawText(int renderer, String text, int start, int end, 883 float x, float y, int bidiFlags, int paint); 884 885 @Override 886 public void drawText(String text, float x, float y, Paint paint) { 887 boolean hasModifier = setupModifiers(paint); 888 try { 889 nDrawText(mRenderer, text, 0, text.length(), x, y, paint.mBidiFlags, 890 paint.mNativePaint); 891 } finally { 892 if (hasModifier) nResetModifiers(mRenderer); 893 } 894 } 895 896 @Override 897 public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset, 898 float vOffset, Paint paint) { 899 // TODO: Implement 900 } 901 902 @Override 903 public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) { 904 // TODO: Implement 905 } 906 907 @Override 908 public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount, 909 float x, float y, int dir, Paint paint) { 910 if ((index | count | text.length - index - count) < 0) { 911 throw new IndexOutOfBoundsException(); 912 } 913 if (dir != DIRECTION_LTR && dir != DIRECTION_RTL) { 914 throw new IllegalArgumentException("Unknown direction: " + dir); 915 } 916 917 boolean hasModifier = setupModifiers(paint); 918 try { 919 nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, dir, 920 paint.mNativePaint); 921 } finally { 922 if (hasModifier) nResetModifiers(mRenderer); 923 } 924 } 925 926 private static native void nDrawTextRun(int renderer, char[] text, int index, int count, 927 int contextIndex, int contextCount, float x, float y, int dir, int nativePaint); 928 929 @Override 930 public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd, 931 float x, float y, int dir, Paint paint) { 932 if ((start | end | end - start | text.length() - end) < 0) { 933 throw new IndexOutOfBoundsException(); 934 } 935 936 boolean hasModifier = setupModifiers(paint); 937 try { 938 int flags = dir == 0 ? 0 : 1; 939 if (text instanceof String || text instanceof SpannedString || 940 text instanceof SpannableString) { 941 nDrawTextRun(mRenderer, text.toString(), start, end, contextStart, 942 contextEnd, x, y, flags, paint.mNativePaint); 943 } else if (text instanceof GraphicsOperations) { 944 ((GraphicsOperations) text).drawTextRun(this, start, end, 945 contextStart, contextEnd, x, y, flags, paint); 946 } else { 947 int contextLen = contextEnd - contextStart; 948 int len = end - start; 949 char[] buf = TemporaryBuffer.obtain(contextLen); 950 TextUtils.getChars(text, contextStart, contextEnd, buf, 0); 951 nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen, 952 x, y, flags, paint.mNativePaint); 953 TemporaryBuffer.recycle(buf); 954 } 955 } finally { 956 if (hasModifier) nResetModifiers(mRenderer); 957 } 958 } 959 960 private static native void nDrawTextRun(int renderer, String text, int start, int end, 961 int contextStart, int contextEnd, float x, float y, int flags, int nativePaint); 962 963 @Override 964 public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset, 965 float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices, 966 int indexOffset, int indexCount, Paint paint) { 967 // TODO: Implement 968 } 969 970 private boolean setupModifiers(Paint paint) { 971 boolean hasModifier = false; 972 973 if (paint.hasShadow) { 974 nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy, 975 paint.shadowColor); 976 hasModifier = true; 977 } 978 979 final Shader shader = paint.getShader(); 980 if (shader != null) { 981 nSetupShader(mRenderer, shader.native_shader); 982 hasModifier = true; 983 } 984 985 final ColorFilter filter = paint.getColorFilter(); 986 if (filter != null) { 987 nSetupColorFilter(mRenderer, filter.nativeColorFilter); 988 hasModifier = true; 989 } 990 991 return hasModifier; 992 } 993 994 private boolean setupColorFilter(Paint paint) { 995 final ColorFilter filter = paint.getColorFilter(); 996 if (filter != null) { 997 nSetupColorFilter(mRenderer, filter.nativeColorFilter); 998 return true; 999 } 1000 return false; 1001 } 1002 1003 private static native void nSetupShader(int renderer, int shader); 1004 private static native void nSetupColorFilter(int renderer, int colorFilter); 1005 private static native void nSetupShadow(int renderer, float radius, 1006 float dx, float dy, int color); 1007 1008 private static native void nResetModifiers(int renderer); 1009} 1010