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