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 17 package android.view; 18 19 import android.graphics.Bitmap; 20 import android.graphics.Canvas; 21 import android.graphics.ColorFilter; 22 import android.graphics.DrawFilter; 23 import android.graphics.Matrix; 24 import android.graphics.NinePatch; 25 import android.graphics.Paint; 26 import android.graphics.PaintFlagsDrawFilter; 27 import android.graphics.Path; 28 import android.graphics.Picture; 29 import android.graphics.PorterDuff; 30 import android.graphics.Rect; 31 import android.graphics.RectF; 32 import android.graphics.Region; 33 import android.graphics.Shader; 34 import android.graphics.SurfaceTexture; 35 import android.graphics.TemporaryBuffer; 36 import android.text.GraphicsOperations; 37 import android.text.SpannableString; 38 import android.text.SpannedString; 39 import android.text.TextUtils; 40 41 /** 42 * An implementation of Canvas on top of OpenGL ES 2.0. 43 */ 44 class GLES20Canvas extends HardwareCanvas { 45 // Must match modifiers used in the JNI layer 46 private static final int MODIFIER_NONE = 0; 47 private static final int MODIFIER_SHADOW = 1; 48 private static final int MODIFIER_SHADER = 2; 49 private static final int MODIFIER_COLOR_FILTER = 4; 50 51 private final boolean mOpaque; 52 private int mRenderer; 53 54 // The native renderer will be destroyed when this object dies. 55 // DO NOT overwrite this reference once it is set. 56 @SuppressWarnings({"unused", "FieldCanBeLocal"}) 57 private CanvasFinalizer mFinalizer; 58 59 private int mWidth; 60 private int mHeight; 61 62 private float[] mPoint; 63 private float[] mLine; 64 65 private Rect mClipBounds; 66 private RectF mPathBounds; 67 68 private DrawFilter mFilter; 69 70 /////////////////////////////////////////////////////////////////////////// 71 // JNI 72 /////////////////////////////////////////////////////////////////////////// 73 nIsAvailable()74 private static native boolean nIsAvailable(); 75 private static boolean sIsAvailable = nIsAvailable(); 76 isAvailable()77 static boolean isAvailable() { 78 return sIsAvailable; 79 } 80 81 /////////////////////////////////////////////////////////////////////////// 82 // Constructors 83 /////////////////////////////////////////////////////////////////////////// 84 85 /** 86 * Creates a canvas to render directly on screen. 87 */ GLES20Canvas(boolean translucent)88 GLES20Canvas(boolean translucent) { 89 this(false, translucent); 90 } 91 92 /** 93 * Creates a canvas to render into an FBO. 94 */ GLES20Canvas(int layer, boolean translucent)95 GLES20Canvas(int layer, boolean translucent) { 96 mOpaque = !translucent; 97 mRenderer = nCreateLayerRenderer(layer); 98 setupFinalizer(); 99 } 100 GLES20Canvas(boolean record, boolean translucent)101 protected GLES20Canvas(boolean record, boolean translucent) { 102 mOpaque = !translucent; 103 104 if (record) { 105 mRenderer = nCreateDisplayListRenderer(); 106 } else { 107 mRenderer = nCreateRenderer(); 108 } 109 110 setupFinalizer(); 111 } 112 setupFinalizer()113 private void setupFinalizer() { 114 if (mRenderer == 0) { 115 throw new IllegalStateException("Could not create GLES20Canvas renderer"); 116 } else { 117 mFinalizer = new CanvasFinalizer(mRenderer); 118 } 119 } 120 resetDisplayListRenderer()121 protected void resetDisplayListRenderer() { 122 nResetDisplayListRenderer(mRenderer); 123 } 124 nCreateRenderer()125 private static native int nCreateRenderer(); nCreateLayerRenderer(int layer)126 private static native int nCreateLayerRenderer(int layer); nCreateDisplayListRenderer()127 private static native int nCreateDisplayListRenderer(); nResetDisplayListRenderer(int renderer)128 private static native void nResetDisplayListRenderer(int renderer); nDestroyRenderer(int renderer)129 private static native void nDestroyRenderer(int renderer); 130 131 private static final class CanvasFinalizer { 132 private final int mRenderer; 133 CanvasFinalizer(int renderer)134 public CanvasFinalizer(int renderer) { 135 mRenderer = renderer; 136 } 137 138 @Override finalize()139 protected void finalize() throws Throwable { 140 try { 141 nDestroyRenderer(mRenderer); 142 } finally { 143 super.finalize(); 144 } 145 } 146 } 147 148 @Override setName(String name)149 public void setName(String name) { 150 super.setName(name); 151 nSetName(mRenderer, name); 152 } 153 nSetName(int renderer, String name)154 private static native void nSetName(int renderer, String name); 155 156 /////////////////////////////////////////////////////////////////////////// 157 // Hardware layers 158 /////////////////////////////////////////////////////////////////////////// 159 160 @Override pushLayerUpdate(HardwareLayer layer)161 void pushLayerUpdate(HardwareLayer layer) { 162 nPushLayerUpdate(mRenderer, ((GLES20RenderLayer) layer).mLayer); 163 } 164 165 @Override cancelLayerUpdate(HardwareLayer layer)166 void cancelLayerUpdate(HardwareLayer layer) { 167 nCancelLayerUpdate(mRenderer, ((GLES20RenderLayer) layer).mLayer); 168 } 169 170 @Override flushLayerUpdates()171 void flushLayerUpdates() { 172 nFlushLayerUpdates(mRenderer); 173 } 174 175 @Override clearLayerUpdates()176 void clearLayerUpdates() { 177 nClearLayerUpdates(mRenderer); 178 } 179 nCreateTextureLayer(boolean opaque, int[] layerInfo)180 static native int nCreateTextureLayer(boolean opaque, int[] layerInfo); nCreateLayer(int width, int height, boolean isOpaque, int[] layerInfo)181 static native int nCreateLayer(int width, int height, boolean isOpaque, int[] layerInfo); nResizeLayer(int layerId, int width, int height, int[] layerInfo)182 static native boolean nResizeLayer(int layerId, int width, int height, int[] layerInfo); nSetOpaqueLayer(int layerId, boolean isOpaque)183 static native void nSetOpaqueLayer(int layerId, boolean isOpaque); nSetLayerPaint(int layerId, int nativePaint)184 static native void nSetLayerPaint(int layerId, int nativePaint); nSetLayerColorFilter(int layerId, int nativeColorFilter)185 static native void nSetLayerColorFilter(int layerId, int nativeColorFilter); nUpdateTextureLayer(int layerId, int width, int height, boolean opaque, SurfaceTexture surface)186 static native void nUpdateTextureLayer(int layerId, int width, int height, boolean opaque, 187 SurfaceTexture surface); nClearLayerTexture(int layerId)188 static native void nClearLayerTexture(int layerId); nSetTextureLayerTransform(int layerId, int matrix)189 static native void nSetTextureLayerTransform(int layerId, int matrix); nDestroyLayer(int layerId)190 static native void nDestroyLayer(int layerId); nDestroyLayerDeferred(int layerId)191 static native void nDestroyLayerDeferred(int layerId); nUpdateRenderLayer(int layerId, int renderer, int displayList, int left, int top, int right, int bottom)192 static native void nUpdateRenderLayer(int layerId, int renderer, int displayList, 193 int left, int top, int right, int bottom); nCopyLayer(int layerId, int bitmap)194 static native boolean nCopyLayer(int layerId, int bitmap); 195 nClearLayerUpdates(int renderer)196 private static native void nClearLayerUpdates(int renderer); nFlushLayerUpdates(int renderer)197 private static native void nFlushLayerUpdates(int renderer); nPushLayerUpdate(int renderer, int layer)198 private static native void nPushLayerUpdate(int renderer, int layer); nCancelLayerUpdate(int renderer, int layer)199 private static native void nCancelLayerUpdate(int renderer, int layer); 200 201 /////////////////////////////////////////////////////////////////////////// 202 // Canvas management 203 /////////////////////////////////////////////////////////////////////////// 204 205 @Override isOpaque()206 public boolean isOpaque() { 207 return mOpaque; 208 } 209 210 @Override getWidth()211 public int getWidth() { 212 return mWidth; 213 } 214 215 @Override getHeight()216 public int getHeight() { 217 return mHeight; 218 } 219 220 @Override getMaximumBitmapWidth()221 public int getMaximumBitmapWidth() { 222 return nGetMaximumTextureWidth(); 223 } 224 225 @Override getMaximumBitmapHeight()226 public int getMaximumBitmapHeight() { 227 return nGetMaximumTextureHeight(); 228 } 229 nGetMaximumTextureWidth()230 private static native int nGetMaximumTextureWidth(); nGetMaximumTextureHeight()231 private static native int nGetMaximumTextureHeight(); 232 233 /** 234 * Returns the native OpenGLRenderer object. 235 */ getRenderer()236 int getRenderer() { 237 return mRenderer; 238 } 239 240 /////////////////////////////////////////////////////////////////////////// 241 // Setup 242 /////////////////////////////////////////////////////////////////////////// 243 244 @Override setViewport(int width, int height)245 public void setViewport(int width, int height) { 246 mWidth = width; 247 mHeight = height; 248 249 nSetViewport(mRenderer, width, height); 250 } 251 nSetViewport(int renderer, int width, int height)252 private static native void nSetViewport(int renderer, int width, int height); 253 254 @Override onPreDraw(Rect dirty)255 public int onPreDraw(Rect dirty) { 256 if (dirty != null) { 257 return nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom, 258 mOpaque); 259 } else { 260 return nPrepare(mRenderer, mOpaque); 261 } 262 } 263 nPrepare(int renderer, boolean opaque)264 private static native int nPrepare(int renderer, boolean opaque); nPrepareDirty(int renderer, int left, int top, int right, int bottom, boolean opaque)265 private static native int nPrepareDirty(int renderer, int left, int top, int right, int bottom, 266 boolean opaque); 267 268 @Override onPostDraw()269 public void onPostDraw() { 270 nFinish(mRenderer); 271 } 272 nFinish(int renderer)273 private static native void nFinish(int renderer); 274 275 /** 276 * Returns the size of the stencil buffer required by the underlying 277 * implementation. 278 * 279 * @return The minimum number of bits the stencil buffer must. Always >= 0. 280 * 281 * @hide 282 */ getStencilSize()283 public static int getStencilSize() { 284 return nGetStencilSize(); 285 } 286 nGetStencilSize()287 private static native int nGetStencilSize(); 288 setCountOverdrawEnabled(boolean enabled)289 void setCountOverdrawEnabled(boolean enabled) { 290 nSetCountOverdrawEnabled(mRenderer, enabled); 291 } 292 nSetCountOverdrawEnabled(int renderer, boolean enabled)293 static native void nSetCountOverdrawEnabled(int renderer, boolean enabled); 294 getOverdraw()295 float getOverdraw() { 296 return nGetOverdraw(mRenderer); 297 } 298 nGetOverdraw(int renderer)299 static native float nGetOverdraw(int renderer); 300 301 /////////////////////////////////////////////////////////////////////////// 302 // Functor 303 /////////////////////////////////////////////////////////////////////////// 304 305 @Override callDrawGLFunction(int drawGLFunction)306 public int callDrawGLFunction(int drawGLFunction) { 307 return nCallDrawGLFunction(mRenderer, drawGLFunction); 308 } 309 nCallDrawGLFunction(int renderer, int drawGLFunction)310 private static native int nCallDrawGLFunction(int renderer, int drawGLFunction); 311 312 @Override invokeFunctors(Rect dirty)313 public int invokeFunctors(Rect dirty) { 314 return nInvokeFunctors(mRenderer, dirty); 315 } 316 nInvokeFunctors(int renderer, Rect dirty)317 private static native int nInvokeFunctors(int renderer, Rect dirty); 318 319 @Override detachFunctor(int functor)320 public void detachFunctor(int functor) { 321 nDetachFunctor(mRenderer, functor); 322 } 323 nDetachFunctor(int renderer, int functor)324 private static native void nDetachFunctor(int renderer, int functor); 325 326 @Override attachFunctor(int functor)327 public void attachFunctor(int functor) { 328 nAttachFunctor(mRenderer, functor); 329 } 330 nAttachFunctor(int renderer, int functor)331 private static native void nAttachFunctor(int renderer, int functor); 332 333 /////////////////////////////////////////////////////////////////////////// 334 // Memory 335 /////////////////////////////////////////////////////////////////////////// 336 337 /** 338 * Must match Caches::FlushMode values 339 * 340 * @see #flushCaches(int) 341 */ 342 static final int FLUSH_CACHES_LAYERS = 0; 343 344 /** 345 * Must match Caches::FlushMode values 346 * 347 * @see #flushCaches(int) 348 */ 349 static final int FLUSH_CACHES_MODERATE = 1; 350 351 /** 352 * Must match Caches::FlushMode values 353 * 354 * @see #flushCaches(int) 355 */ 356 static final int FLUSH_CACHES_FULL = 2; 357 358 /** 359 * Flush caches to reclaim as much memory as possible. The amount of memory 360 * to reclaim is indicate by the level parameter. 361 * 362 * The level can be one of {@link #FLUSH_CACHES_MODERATE} or 363 * {@link #FLUSH_CACHES_FULL}. 364 * 365 * @param level Hint about the amount of memory to reclaim 366 */ flushCaches(int level)367 static void flushCaches(int level) { 368 nFlushCaches(level); 369 } 370 nFlushCaches(int level)371 private static native void nFlushCaches(int level); 372 373 /** 374 * Release all resources associated with the underlying caches. This should 375 * only be called after a full flushCaches(). 376 * 377 * @hide 378 */ terminateCaches()379 static void terminateCaches() { 380 nTerminateCaches(); 381 } 382 nTerminateCaches()383 private static native void nTerminateCaches(); 384 initCaches()385 static boolean initCaches() { 386 return nInitCaches(); 387 } 388 nInitCaches()389 private static native boolean nInitCaches(); 390 391 /////////////////////////////////////////////////////////////////////////// 392 // Atlas 393 /////////////////////////////////////////////////////////////////////////// 394 initAtlas(GraphicBuffer buffer, int[] map)395 static void initAtlas(GraphicBuffer buffer, int[] map) { 396 nInitAtlas(buffer, map, map.length); 397 } 398 nInitAtlas(GraphicBuffer buffer, int[] map, int count)399 private static native void nInitAtlas(GraphicBuffer buffer, int[] map, int count); 400 401 /////////////////////////////////////////////////////////////////////////// 402 // Display list 403 /////////////////////////////////////////////////////////////////////////// 404 getDisplayList(int displayList)405 int getDisplayList(int displayList) { 406 return nGetDisplayList(mRenderer, displayList); 407 } 408 nGetDisplayList(int renderer, int displayList)409 private static native int nGetDisplayList(int renderer, int displayList); 410 411 @Override outputDisplayList(DisplayList displayList)412 void outputDisplayList(DisplayList displayList) { 413 nOutputDisplayList(mRenderer, ((GLES20DisplayList) displayList).getNativeDisplayList()); 414 } 415 nOutputDisplayList(int renderer, int displayList)416 private static native void nOutputDisplayList(int renderer, int displayList); 417 418 @Override drawDisplayList(DisplayList displayList, Rect dirty, int flags)419 public int drawDisplayList(DisplayList displayList, Rect dirty, int flags) { 420 return nDrawDisplayList(mRenderer, ((GLES20DisplayList) displayList).getNativeDisplayList(), 421 dirty, flags); 422 } 423 nDrawDisplayList(int renderer, int displayList, Rect dirty, int flags)424 private static native int nDrawDisplayList(int renderer, int displayList, 425 Rect dirty, int flags); 426 427 /////////////////////////////////////////////////////////////////////////// 428 // Hardware layer 429 /////////////////////////////////////////////////////////////////////////// 430 drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint)431 void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) { 432 layer.setLayerPaint(paint); 433 434 final GLES20Layer glLayer = (GLES20Layer) layer; 435 nDrawLayer(mRenderer, glLayer.getLayer(), x, y); 436 } 437 nDrawLayer(int renderer, int layer, float x, float y)438 private static native void nDrawLayer(int renderer, int layer, float x, float y); 439 interrupt()440 void interrupt() { 441 nInterrupt(mRenderer); 442 } 443 resume()444 void resume() { 445 nResume(mRenderer); 446 } 447 nInterrupt(int renderer)448 private static native void nInterrupt(int renderer); nResume(int renderer)449 private static native void nResume(int renderer); 450 451 /////////////////////////////////////////////////////////////////////////// 452 // Support 453 /////////////////////////////////////////////////////////////////////////// 454 getInternalClipBounds()455 private Rect getInternalClipBounds() { 456 if (mClipBounds == null) mClipBounds = new Rect(); 457 return mClipBounds; 458 } 459 460 getPathBounds()461 private RectF getPathBounds() { 462 if (mPathBounds == null) mPathBounds = new RectF(); 463 return mPathBounds; 464 } 465 getPointStorage()466 private float[] getPointStorage() { 467 if (mPoint == null) mPoint = new float[2]; 468 return mPoint; 469 } 470 getLineStorage()471 private float[] getLineStorage() { 472 if (mLine == null) mLine = new float[4]; 473 return mLine; 474 } 475 476 /////////////////////////////////////////////////////////////////////////// 477 // Clipping 478 /////////////////////////////////////////////////////////////////////////// 479 480 @Override clipPath(Path path)481 public boolean clipPath(Path path) { 482 return nClipPath(mRenderer, path.mNativePath, Region.Op.INTERSECT.nativeInt); 483 } 484 485 @Override clipPath(Path path, Region.Op op)486 public boolean clipPath(Path path, Region.Op op) { 487 return nClipPath(mRenderer, path.mNativePath, op.nativeInt); 488 } 489 nClipPath(int renderer, int path, int op)490 private static native boolean nClipPath(int renderer, int path, int op); 491 492 @Override clipRect(float left, float top, float right, float bottom)493 public boolean clipRect(float left, float top, float right, float bottom) { 494 return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt); 495 } 496 nClipRect(int renderer, float left, float top, float right, float bottom, int op)497 private static native boolean nClipRect(int renderer, float left, float top, 498 float right, float bottom, int op); 499 500 @Override clipRect(float left, float top, float right, float bottom, Region.Op op)501 public boolean clipRect(float left, float top, float right, float bottom, Region.Op op) { 502 return nClipRect(mRenderer, left, top, right, bottom, op.nativeInt); 503 } 504 505 @Override clipRect(int left, int top, int right, int bottom)506 public boolean clipRect(int left, int top, int right, int bottom) { 507 return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt); 508 } 509 nClipRect(int renderer, int left, int top, int right, int bottom, int op)510 private static native boolean nClipRect(int renderer, int left, int top, 511 int right, int bottom, int op); 512 513 @Override clipRect(Rect rect)514 public boolean clipRect(Rect rect) { 515 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, 516 Region.Op.INTERSECT.nativeInt); 517 } 518 519 @Override clipRect(Rect rect, Region.Op op)520 public boolean clipRect(Rect rect, Region.Op op) { 521 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt); 522 } 523 524 @Override clipRect(RectF rect)525 public boolean clipRect(RectF rect) { 526 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, 527 Region.Op.INTERSECT.nativeInt); 528 } 529 530 @Override clipRect(RectF rect, Region.Op op)531 public boolean clipRect(RectF rect, Region.Op op) { 532 return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt); 533 } 534 535 @Override clipRegion(Region region)536 public boolean clipRegion(Region region) { 537 return nClipRegion(mRenderer, region.mNativeRegion, Region.Op.INTERSECT.nativeInt); 538 } 539 540 @Override clipRegion(Region region, Region.Op op)541 public boolean clipRegion(Region region, Region.Op op) { 542 return nClipRegion(mRenderer, region.mNativeRegion, op.nativeInt); 543 } 544 nClipRegion(int renderer, int region, int op)545 private static native boolean nClipRegion(int renderer, int region, int op); 546 547 @Override getClipBounds(Rect bounds)548 public boolean getClipBounds(Rect bounds) { 549 return nGetClipBounds(mRenderer, bounds); 550 } 551 nGetClipBounds(int renderer, Rect bounds)552 private static native boolean nGetClipBounds(int renderer, Rect bounds); 553 554 @Override quickReject(float left, float top, float right, float bottom, EdgeType type)555 public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) { 556 return nQuickReject(mRenderer, left, top, right, bottom); 557 } 558 nQuickReject(int renderer, float left, float top, float right, float bottom)559 private static native boolean nQuickReject(int renderer, float left, float top, 560 float right, float bottom); 561 562 @Override quickReject(Path path, EdgeType type)563 public boolean quickReject(Path path, EdgeType type) { 564 RectF pathBounds = getPathBounds(); 565 path.computeBounds(pathBounds, true); 566 return nQuickReject(mRenderer, pathBounds.left, pathBounds.top, 567 pathBounds.right, pathBounds.bottom); 568 } 569 570 @Override quickReject(RectF rect, EdgeType type)571 public boolean quickReject(RectF rect, EdgeType type) { 572 return nQuickReject(mRenderer, rect.left, rect.top, rect.right, rect.bottom); 573 } 574 575 /////////////////////////////////////////////////////////////////////////// 576 // Transformations 577 /////////////////////////////////////////////////////////////////////////// 578 579 @Override translate(float dx, float dy)580 public void translate(float dx, float dy) { 581 if (dx != 0.0f || dy != 0.0f) nTranslate(mRenderer, dx, dy); 582 } 583 nTranslate(int renderer, float dx, float dy)584 private static native void nTranslate(int renderer, float dx, float dy); 585 586 @Override skew(float sx, float sy)587 public void skew(float sx, float sy) { 588 nSkew(mRenderer, sx, sy); 589 } 590 nSkew(int renderer, float sx, float sy)591 private static native void nSkew(int renderer, float sx, float sy); 592 593 @Override rotate(float degrees)594 public void rotate(float degrees) { 595 nRotate(mRenderer, degrees); 596 } 597 nRotate(int renderer, float degrees)598 private static native void nRotate(int renderer, float degrees); 599 600 @Override scale(float sx, float sy)601 public void scale(float sx, float sy) { 602 nScale(mRenderer, sx, sy); 603 } 604 nScale(int renderer, float sx, float sy)605 private static native void nScale(int renderer, float sx, float sy); 606 607 @Override setMatrix(Matrix matrix)608 public void setMatrix(Matrix matrix) { 609 nSetMatrix(mRenderer, matrix == null ? 0 : matrix.native_instance); 610 } 611 nSetMatrix(int renderer, int matrix)612 private static native void nSetMatrix(int renderer, int matrix); 613 614 @SuppressWarnings("deprecation") 615 @Override getMatrix(Matrix matrix)616 public void getMatrix(Matrix matrix) { 617 nGetMatrix(mRenderer, matrix.native_instance); 618 } 619 nGetMatrix(int renderer, int matrix)620 private static native void nGetMatrix(int renderer, int matrix); 621 622 @Override concat(Matrix matrix)623 public void concat(Matrix matrix) { 624 if (matrix != null) nConcatMatrix(mRenderer, matrix.native_instance); 625 } 626 nConcatMatrix(int renderer, int matrix)627 private static native void nConcatMatrix(int renderer, int matrix); 628 629 /////////////////////////////////////////////////////////////////////////// 630 // State management 631 /////////////////////////////////////////////////////////////////////////// 632 633 @Override save()634 public int save() { 635 return nSave(mRenderer, Canvas.CLIP_SAVE_FLAG | Canvas.MATRIX_SAVE_FLAG); 636 } 637 638 @Override save(int saveFlags)639 public int save(int saveFlags) { 640 return nSave(mRenderer, saveFlags); 641 } 642 nSave(int renderer, int flags)643 private static native int nSave(int renderer, int flags); 644 645 @Override saveLayer(RectF bounds, Paint paint, int saveFlags)646 public int saveLayer(RectF bounds, Paint paint, int saveFlags) { 647 if (bounds != null) { 648 return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags); 649 } 650 651 int count; 652 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE; 653 try { 654 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 655 count = nSaveLayer(mRenderer, nativePaint, saveFlags); 656 } finally { 657 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier); 658 } 659 return count; 660 } 661 nSaveLayer(int renderer, int paint, int saveFlags)662 private static native int nSaveLayer(int renderer, int paint, int saveFlags); 663 664 @Override saveLayer(float left, float top, float right, float bottom, Paint paint, int saveFlags)665 public int saveLayer(float left, float top, float right, float bottom, Paint paint, 666 int saveFlags) { 667 if (left < right && top < bottom) { 668 int count; 669 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE; 670 try { 671 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 672 count = nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags); 673 } finally { 674 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier); 675 } 676 return count; 677 } 678 return save(saveFlags); 679 } 680 nSaveLayer(int renderer, float left, float top, float right, float bottom, int paint, int saveFlags)681 private static native int nSaveLayer(int renderer, float left, float top, 682 float right, float bottom, int paint, int saveFlags); 683 684 @Override saveLayerAlpha(RectF bounds, int alpha, int saveFlags)685 public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) { 686 if (bounds != null) { 687 return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom, 688 alpha, saveFlags); 689 } 690 return nSaveLayerAlpha(mRenderer, alpha, saveFlags); 691 } 692 nSaveLayerAlpha(int renderer, int alpha, int saveFlags)693 private static native int nSaveLayerAlpha(int renderer, int alpha, int saveFlags); 694 695 @Override saveLayerAlpha(float left, float top, float right, float bottom, int alpha, int saveFlags)696 public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha, 697 int saveFlags) { 698 if (left < right && top < bottom) { 699 return nSaveLayerAlpha(mRenderer, left, top, right, bottom, alpha, saveFlags); 700 } 701 return save(saveFlags); 702 } 703 nSaveLayerAlpha(int renderer, float left, float top, float right, float bottom, int alpha, int saveFlags)704 private static native int nSaveLayerAlpha(int renderer, float left, float top, float right, 705 float bottom, int alpha, int saveFlags); 706 707 @Override restore()708 public void restore() { 709 nRestore(mRenderer); 710 } 711 nRestore(int renderer)712 private static native void nRestore(int renderer); 713 714 @Override restoreToCount(int saveCount)715 public void restoreToCount(int saveCount) { 716 nRestoreToCount(mRenderer, saveCount); 717 } 718 nRestoreToCount(int renderer, int saveCount)719 private static native void nRestoreToCount(int renderer, int saveCount); 720 721 @Override getSaveCount()722 public int getSaveCount() { 723 return nGetSaveCount(mRenderer); 724 } 725 nGetSaveCount(int renderer)726 private static native int nGetSaveCount(int renderer); 727 728 /////////////////////////////////////////////////////////////////////////// 729 // Filtering 730 /////////////////////////////////////////////////////////////////////////// 731 732 @Override setDrawFilter(DrawFilter filter)733 public void setDrawFilter(DrawFilter filter) { 734 mFilter = filter; 735 if (filter == null) { 736 nResetPaintFilter(mRenderer); 737 } else if (filter instanceof PaintFlagsDrawFilter) { 738 PaintFlagsDrawFilter flagsFilter = (PaintFlagsDrawFilter) filter; 739 nSetupPaintFilter(mRenderer, flagsFilter.clearBits, flagsFilter.setBits); 740 } 741 } 742 nResetPaintFilter(int renderer)743 private static native void nResetPaintFilter(int renderer); nSetupPaintFilter(int renderer, int clearBits, int setBits)744 private static native void nSetupPaintFilter(int renderer, int clearBits, int setBits); 745 746 @Override getDrawFilter()747 public DrawFilter getDrawFilter() { 748 return mFilter; 749 } 750 751 /////////////////////////////////////////////////////////////////////////// 752 // Drawing 753 /////////////////////////////////////////////////////////////////////////// 754 755 @Override drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)756 public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, 757 Paint paint) { 758 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER); 759 try { 760 nDrawArc(mRenderer, oval.left, oval.top, oval.right, oval.bottom, 761 startAngle, sweepAngle, useCenter, paint.mNativePaint); 762 } finally { 763 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 764 } 765 } 766 nDrawArc(int renderer, float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, int paint)767 private static native void nDrawArc(int renderer, float left, float top, 768 float right, float bottom, float startAngle, float sweepAngle, 769 boolean useCenter, int paint); 770 771 @Override drawARGB(int a, int r, int g, int b)772 public void drawARGB(int a, int r, int g, int b) { 773 drawColor((a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF)); 774 } 775 776 @Override drawPatch(NinePatch patch, Rect dst, Paint paint)777 public void drawPatch(NinePatch patch, Rect dst, Paint paint) { 778 Bitmap bitmap = patch.getBitmap(); 779 throwIfCannotDraw(bitmap); 780 // Shaders are ignored when drawing patches 781 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE; 782 try { 783 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 784 nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk, 785 dst.left, dst.top, dst.right, dst.bottom, nativePaint); 786 } finally { 787 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier); 788 } 789 } 790 791 @Override drawPatch(NinePatch patch, RectF dst, Paint paint)792 public void drawPatch(NinePatch patch, RectF dst, Paint paint) { 793 Bitmap bitmap = patch.getBitmap(); 794 throwIfCannotDraw(bitmap); 795 // Shaders are ignored when drawing patches 796 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE; 797 try { 798 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 799 nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk, 800 dst.left, dst.top, dst.right, dst.bottom, nativePaint); 801 } finally { 802 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier); 803 } 804 } 805 nDrawPatch(int renderer, int bitmap, byte[] buffer, int chunk, float left, float top, float right, float bottom, int paint)806 private static native void nDrawPatch(int renderer, int bitmap, byte[] buffer, int chunk, 807 float left, float top, float right, float bottom, int paint); 808 809 @Override drawBitmap(Bitmap bitmap, float left, float top, Paint paint)810 public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) { 811 throwIfCannotDraw(bitmap); 812 // Shaders are ignored when drawing bitmaps 813 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; 814 try { 815 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 816 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, nativePaint); 817 } finally { 818 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 819 } 820 } 821 nDrawBitmap(int renderer, int bitmap, byte[] buffer, float left, float top, int paint)822 private static native void nDrawBitmap(int renderer, int bitmap, byte[] buffer, 823 float left, float top, int paint); 824 825 @Override drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)826 public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) { 827 throwIfCannotDraw(bitmap); 828 // Shaders are ignored when drawing bitmaps 829 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; 830 try { 831 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 832 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, 833 matrix.native_instance, nativePaint); 834 } finally { 835 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 836 } 837 } 838 nDrawBitmap(int renderer, int bitmap, byte[] buffer, int matrix, int paint)839 private static native void nDrawBitmap(int renderer, int bitmap, byte[] buffer, 840 int matrix, int paint); 841 842 @Override drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)843 public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) { 844 throwIfCannotDraw(bitmap); 845 // Shaders are ignored when drawing bitmaps 846 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; 847 try { 848 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 849 850 int left, top, right, bottom; 851 if (src == null) { 852 left = top = 0; 853 right = bitmap.getWidth(); 854 bottom = bitmap.getHeight(); 855 } else { 856 left = src.left; 857 right = src.right; 858 top = src.top; 859 bottom = src.bottom; 860 } 861 862 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom, 863 dst.left, dst.top, dst.right, dst.bottom, nativePaint); 864 } finally { 865 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 866 } 867 } 868 869 @Override drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint)870 public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) { 871 throwIfCannotDraw(bitmap); 872 // Shaders are ignored when drawing bitmaps 873 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; 874 try { 875 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 876 877 float left, top, right, bottom; 878 if (src == null) { 879 left = top = 0; 880 right = bitmap.getWidth(); 881 bottom = bitmap.getHeight(); 882 } else { 883 left = src.left; 884 right = src.right; 885 top = src.top; 886 bottom = src.bottom; 887 } 888 889 nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom, 890 dst.left, dst.top, dst.right, dst.bottom, nativePaint); 891 } finally { 892 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 893 } 894 } 895 nDrawBitmap(int renderer, int bitmap, byte[] buffer, float srcLeft, float srcTop, float srcRight, float srcBottom, float left, float top, float right, float bottom, int paint)896 private static native void nDrawBitmap(int renderer, int bitmap, byte[] buffer, 897 float srcLeft, float srcTop, float srcRight, float srcBottom, 898 float left, float top, float right, float bottom, int paint); 899 900 @Override drawBitmap(int[] colors, int offset, int stride, float x, float y, int width, int height, boolean hasAlpha, Paint paint)901 public void drawBitmap(int[] colors, int offset, int stride, float x, float y, 902 int width, int height, boolean hasAlpha, Paint paint) { 903 if (width < 0) { 904 throw new IllegalArgumentException("width must be >= 0"); 905 } 906 907 if (height < 0) { 908 throw new IllegalArgumentException("height must be >= 0"); 909 } 910 911 if (Math.abs(stride) < width) { 912 throw new IllegalArgumentException("abs(stride) must be >= width"); 913 } 914 915 int lastScanline = offset + (height - 1) * stride; 916 int length = colors.length; 917 918 if (offset < 0 || (offset + width > length) || lastScanline < 0 || 919 (lastScanline + width > length)) { 920 throw new ArrayIndexOutOfBoundsException(); 921 } 922 923 // Shaders are ignored when drawing bitmaps 924 int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE; 925 try { 926 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 927 nDrawBitmap(mRenderer, colors, offset, stride, x, y, 928 width, height, hasAlpha, nativePaint); 929 } finally { 930 if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier); 931 } 932 } 933 nDrawBitmap(int renderer, int[] colors, int offset, int stride, float x, float y, int width, int height, boolean hasAlpha, int nativePaint)934 private static native void nDrawBitmap(int renderer, int[] colors, int offset, int stride, 935 float x, float y, int width, int height, boolean hasAlpha, int nativePaint); 936 937 @Override drawBitmap(int[] colors, int offset, int stride, int x, int y, int width, int height, boolean hasAlpha, Paint paint)938 public void drawBitmap(int[] colors, int offset, int stride, int x, int y, 939 int width, int height, boolean hasAlpha, Paint paint) { 940 // Shaders are ignored when drawing bitmaps 941 drawBitmap(colors, offset, stride, (float) x, (float) y, width, height, hasAlpha, paint); 942 } 943 944 @Override drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset, Paint paint)945 public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts, 946 int vertOffset, int[] colors, int colorOffset, Paint paint) { 947 throwIfCannotDraw(bitmap); 948 if (meshWidth < 0 || meshHeight < 0 || vertOffset < 0 || colorOffset < 0) { 949 throw new ArrayIndexOutOfBoundsException(); 950 } 951 952 if (meshWidth == 0 || meshHeight == 0) { 953 return; 954 } 955 956 final int count = (meshWidth + 1) * (meshHeight + 1); 957 checkRange(verts.length, vertOffset, count * 2); 958 959 if (colors != null) { 960 checkRange(colors.length, colorOffset, count); 961 } 962 963 int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; 964 try { 965 final int nativePaint = paint == null ? 0 : paint.mNativePaint; 966 nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, meshWidth, meshHeight, 967 verts, vertOffset, colors, colorOffset, nativePaint); 968 } finally { 969 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 970 } 971 } 972 nDrawBitmapMesh(int renderer, int bitmap, byte[] buffer, int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset, int paint)973 private static native void nDrawBitmapMesh(int renderer, int bitmap, byte[] buffer, 974 int meshWidth, int meshHeight, float[] verts, int vertOffset, 975 int[] colors, int colorOffset, int paint); 976 977 @Override drawCircle(float cx, float cy, float radius, Paint paint)978 public void drawCircle(float cx, float cy, float radius, Paint paint) { 979 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER); 980 try { 981 nDrawCircle(mRenderer, cx, cy, radius, paint.mNativePaint); 982 } finally { 983 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 984 } 985 } 986 nDrawCircle(int renderer, float cx, float cy, float radius, int paint)987 private static native void nDrawCircle(int renderer, float cx, float cy, 988 float radius, int paint); 989 990 @Override drawColor(int color)991 public void drawColor(int color) { 992 drawColor(color, PorterDuff.Mode.SRC_OVER); 993 } 994 995 @Override drawColor(int color, PorterDuff.Mode mode)996 public void drawColor(int color, PorterDuff.Mode mode) { 997 nDrawColor(mRenderer, color, mode.nativeInt); 998 } 999 nDrawColor(int renderer, int color, int mode)1000 private static native void nDrawColor(int renderer, int color, int mode); 1001 1002 @Override drawLine(float startX, float startY, float stopX, float stopY, Paint paint)1003 public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) { 1004 float[] line = getLineStorage(); 1005 line[0] = startX; 1006 line[1] = startY; 1007 line[2] = stopX; 1008 line[3] = stopY; 1009 drawLines(line, 0, 4, paint); 1010 } 1011 1012 @Override drawLines(float[] pts, int offset, int count, Paint paint)1013 public void drawLines(float[] pts, int offset, int count, Paint paint) { 1014 if (count < 4) return; 1015 1016 if ((offset | count) < 0 || offset + count > pts.length) { 1017 throw new IllegalArgumentException("The lines array must contain 4 elements per line."); 1018 } 1019 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER); 1020 try { 1021 nDrawLines(mRenderer, pts, offset, count, paint.mNativePaint); 1022 } finally { 1023 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1024 } 1025 } 1026 nDrawLines(int renderer, float[] points, int offset, int count, int paint)1027 private static native void nDrawLines(int renderer, float[] points, 1028 int offset, int count, int paint); 1029 1030 @Override drawLines(float[] pts, Paint paint)1031 public void drawLines(float[] pts, Paint paint) { 1032 drawLines(pts, 0, pts.length, paint); 1033 } 1034 1035 @Override drawOval(RectF oval, Paint paint)1036 public void drawOval(RectF oval, Paint paint) { 1037 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER); 1038 try { 1039 nDrawOval(mRenderer, oval.left, oval.top, oval.right, oval.bottom, paint.mNativePaint); 1040 } finally { 1041 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1042 } 1043 } 1044 nDrawOval(int renderer, float left, float top, float right, float bottom, int paint)1045 private static native void nDrawOval(int renderer, float left, float top, 1046 float right, float bottom, int paint); 1047 1048 @Override drawPaint(Paint paint)1049 public void drawPaint(Paint paint) { 1050 final Rect r = getInternalClipBounds(); 1051 nGetClipBounds(mRenderer, r); 1052 drawRect(r.left, r.top, r.right, r.bottom, paint); 1053 } 1054 1055 @Override drawPath(Path path, Paint paint)1056 public void drawPath(Path path, Paint paint) { 1057 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER); 1058 try { 1059 if (path.isSimplePath) { 1060 if (path.rects != null) { 1061 nDrawRects(mRenderer, path.rects.mNativeRegion, paint.mNativePaint); 1062 } 1063 } else { 1064 nDrawPath(mRenderer, path.mNativePath, paint.mNativePaint); 1065 } 1066 } finally { 1067 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1068 } 1069 } 1070 nDrawPath(int renderer, int path, int paint)1071 private static native void nDrawPath(int renderer, int path, int paint); nDrawRects(int renderer, int region, int paint)1072 private static native void nDrawRects(int renderer, int region, int paint); 1073 drawRects(float[] rects, int count, Paint paint)1074 void drawRects(float[] rects, int count, Paint paint) { 1075 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER); 1076 try { 1077 nDrawRects(mRenderer, rects, count, paint.mNativePaint); 1078 } finally { 1079 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1080 } 1081 } 1082 nDrawRects(int renderer, float[] rects, int count, int paint)1083 private static native void nDrawRects(int renderer, float[] rects, int count, int paint); 1084 1085 @Override drawPicture(Picture picture)1086 public void drawPicture(Picture picture) { 1087 if (picture.createdFromStream) { 1088 return; 1089 } 1090 1091 picture.endRecording(); 1092 // TODO: Implement rendering 1093 } 1094 1095 @Override drawPicture(Picture picture, Rect dst)1096 public void drawPicture(Picture picture, Rect dst) { 1097 if (picture.createdFromStream) { 1098 return; 1099 } 1100 1101 save(); 1102 translate(dst.left, dst.top); 1103 if (picture.getWidth() > 0 && picture.getHeight() > 0) { 1104 scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight()); 1105 } 1106 drawPicture(picture); 1107 restore(); 1108 } 1109 1110 @Override drawPicture(Picture picture, RectF dst)1111 public void drawPicture(Picture picture, RectF dst) { 1112 if (picture.createdFromStream) { 1113 return; 1114 } 1115 1116 save(); 1117 translate(dst.left, dst.top); 1118 if (picture.getWidth() > 0 && picture.getHeight() > 0) { 1119 scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight()); 1120 } 1121 drawPicture(picture); 1122 restore(); 1123 } 1124 1125 @Override drawPoint(float x, float y, Paint paint)1126 public void drawPoint(float x, float y, Paint paint) { 1127 float[] point = getPointStorage(); 1128 point[0] = x; 1129 point[1] = y; 1130 drawPoints(point, 0, 2, paint); 1131 } 1132 1133 @Override drawPoints(float[] pts, Paint paint)1134 public void drawPoints(float[] pts, Paint paint) { 1135 drawPoints(pts, 0, pts.length, paint); 1136 } 1137 1138 @Override drawPoints(float[] pts, int offset, int count, Paint paint)1139 public void drawPoints(float[] pts, int offset, int count, Paint paint) { 1140 if (count < 2) return; 1141 1142 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER); 1143 try { 1144 nDrawPoints(mRenderer, pts, offset, count, paint.mNativePaint); 1145 } finally { 1146 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1147 } 1148 } 1149 nDrawPoints(int renderer, float[] points, int offset, int count, int paint)1150 private static native void nDrawPoints(int renderer, float[] points, 1151 int offset, int count, int paint); 1152 1153 @SuppressWarnings("deprecation") 1154 @Override drawPosText(char[] text, int index, int count, float[] pos, Paint paint)1155 public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) { 1156 if (index < 0 || index + count > text.length || count * 2 > pos.length) { 1157 throw new IndexOutOfBoundsException(); 1158 } 1159 1160 int modifiers = setupModifiers(paint); 1161 try { 1162 nDrawPosText(mRenderer, text, index, count, pos, paint.mNativePaint); 1163 } finally { 1164 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1165 } 1166 } 1167 nDrawPosText(int renderer, char[] text, int index, int count, float[] pos, int paint)1168 private static native void nDrawPosText(int renderer, char[] text, int index, int count, 1169 float[] pos, int paint); 1170 1171 @SuppressWarnings("deprecation") 1172 @Override drawPosText(String text, float[] pos, Paint paint)1173 public void drawPosText(String text, float[] pos, Paint paint) { 1174 if (text.length() * 2 > pos.length) { 1175 throw new ArrayIndexOutOfBoundsException(); 1176 } 1177 1178 int modifiers = setupModifiers(paint); 1179 try { 1180 nDrawPosText(mRenderer, text, 0, text.length(), pos, paint.mNativePaint); 1181 } finally { 1182 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1183 } 1184 } 1185 nDrawPosText(int renderer, String text, int start, int end, float[] pos, int paint)1186 private static native void nDrawPosText(int renderer, String text, int start, int end, 1187 float[] pos, int paint); 1188 1189 @Override drawRect(float left, float top, float right, float bottom, Paint paint)1190 public void drawRect(float left, float top, float right, float bottom, Paint paint) { 1191 if (left == right || top == bottom) return; 1192 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER); 1193 try { 1194 nDrawRect(mRenderer, left, top, right, bottom, paint.mNativePaint); 1195 } finally { 1196 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1197 } 1198 } 1199 nDrawRect(int renderer, float left, float top, float right, float bottom, int paint)1200 private static native void nDrawRect(int renderer, float left, float top, 1201 float right, float bottom, int paint); 1202 1203 @Override drawRect(Rect r, Paint paint)1204 public void drawRect(Rect r, Paint paint) { 1205 drawRect(r.left, r.top, r.right, r.bottom, paint); 1206 } 1207 1208 @Override drawRect(RectF r, Paint paint)1209 public void drawRect(RectF r, Paint paint) { 1210 drawRect(r.left, r.top, r.right, r.bottom, paint); 1211 } 1212 1213 @Override drawRGB(int r, int g, int b)1214 public void drawRGB(int r, int g, int b) { 1215 drawColor(0xFF000000 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF)); 1216 } 1217 1218 @Override drawRoundRect(RectF rect, float rx, float ry, Paint paint)1219 public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) { 1220 int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER); 1221 try { 1222 nDrawRoundRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, 1223 rx, ry, paint.mNativePaint); 1224 } finally { 1225 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1226 } 1227 } 1228 nDrawRoundRect(int renderer, float left, float top, float right, float bottom, float rx, float y, int paint)1229 private static native void nDrawRoundRect(int renderer, float left, float top, 1230 float right, float bottom, float rx, float y, int paint); 1231 1232 @Override drawText(char[] text, int index, int count, float x, float y, Paint paint)1233 public void drawText(char[] text, int index, int count, float x, float y, Paint paint) { 1234 if ((index | count | (index + count) | (text.length - index - count)) < 0) { 1235 throw new IndexOutOfBoundsException(); 1236 } 1237 1238 int modifiers = setupModifiers(paint); 1239 try { 1240 nDrawText(mRenderer, text, index, count, x, y, paint.mBidiFlags, paint.mNativePaint); 1241 } finally { 1242 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1243 } 1244 } 1245 nDrawText(int renderer, char[] text, int index, int count, float x, float y, int bidiFlags, int paint)1246 private static native void nDrawText(int renderer, char[] text, int index, int count, 1247 float x, float y, int bidiFlags, int paint); 1248 1249 @Override drawText(CharSequence text, int start, int end, float x, float y, Paint paint)1250 public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) { 1251 int modifiers = setupModifiers(paint); 1252 try { 1253 if (text instanceof String || text instanceof SpannedString || 1254 text instanceof SpannableString) { 1255 nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags, 1256 paint.mNativePaint); 1257 } else if (text instanceof GraphicsOperations) { 1258 ((GraphicsOperations) text).drawText(this, start, end, x, y, 1259 paint); 1260 } else { 1261 char[] buf = TemporaryBuffer.obtain(end - start); 1262 TextUtils.getChars(text, start, end, buf, 0); 1263 nDrawText(mRenderer, buf, 0, end - start, x, y, 1264 paint.mBidiFlags, paint.mNativePaint); 1265 TemporaryBuffer.recycle(buf); 1266 } 1267 } finally { 1268 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1269 } 1270 } 1271 1272 @Override drawText(String text, int start, int end, float x, float y, Paint paint)1273 public void drawText(String text, int start, int end, float x, float y, Paint paint) { 1274 if ((start | end | (end - start) | (text.length() - end)) < 0) { 1275 throw new IndexOutOfBoundsException(); 1276 } 1277 1278 int modifiers = setupModifiers(paint); 1279 try { 1280 nDrawText(mRenderer, text, start, end, x, y, paint.mBidiFlags, paint.mNativePaint); 1281 } finally { 1282 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1283 } 1284 } 1285 nDrawText(int renderer, String text, int start, int end, float x, float y, int bidiFlags, int paint)1286 private static native void nDrawText(int renderer, String text, int start, int end, 1287 float x, float y, int bidiFlags, int paint); 1288 1289 @Override drawText(String text, float x, float y, Paint paint)1290 public void drawText(String text, float x, float y, Paint paint) { 1291 int modifiers = setupModifiers(paint); 1292 try { 1293 nDrawText(mRenderer, text, 0, text.length(), x, y, paint.mBidiFlags, 1294 paint.mNativePaint); 1295 } finally { 1296 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1297 } 1298 } 1299 1300 @Override drawTextOnPath(char[] text, int index, int count, Path path, float hOffset, float vOffset, Paint paint)1301 public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset, 1302 float vOffset, Paint paint) { 1303 if (index < 0 || index + count > text.length) { 1304 throw new ArrayIndexOutOfBoundsException(); 1305 } 1306 1307 int modifiers = setupModifiers(paint); 1308 try { 1309 nDrawTextOnPath(mRenderer, text, index, count, path.mNativePath, hOffset, vOffset, 1310 paint.mBidiFlags, paint.mNativePaint); 1311 } finally { 1312 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1313 } 1314 } 1315 nDrawTextOnPath(int renderer, char[] text, int index, int count, int path, float hOffset, float vOffset, int bidiFlags, int nativePaint)1316 private static native void nDrawTextOnPath(int renderer, char[] text, int index, int count, 1317 int path, float hOffset, float vOffset, int bidiFlags, int nativePaint); 1318 1319 @Override drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint)1320 public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) { 1321 if (text.length() == 0) return; 1322 1323 int modifiers = setupModifiers(paint); 1324 try { 1325 nDrawTextOnPath(mRenderer, text, 0, text.length(), path.mNativePath, hOffset, vOffset, 1326 paint.mBidiFlags, paint.mNativePaint); 1327 } finally { 1328 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1329 } 1330 } 1331 nDrawTextOnPath(int renderer, String text, int start, int end, int path, float hOffset, float vOffset, int bidiFlags, int nativePaint)1332 private static native void nDrawTextOnPath(int renderer, String text, int start, int end, 1333 int path, float hOffset, float vOffset, int bidiFlags, int nativePaint); 1334 1335 @Override drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount, float x, float y, int dir, Paint paint)1336 public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount, 1337 float x, float y, int dir, Paint paint) { 1338 if ((index | count | text.length - index - count) < 0) { 1339 throw new IndexOutOfBoundsException(); 1340 } 1341 if (dir != DIRECTION_LTR && dir != DIRECTION_RTL) { 1342 throw new IllegalArgumentException("Unknown direction: " + dir); 1343 } 1344 1345 int modifiers = setupModifiers(paint); 1346 try { 1347 nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, dir, 1348 paint.mNativePaint); 1349 } finally { 1350 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1351 } 1352 } 1353 nDrawTextRun(int renderer, char[] text, int index, int count, int contextIndex, int contextCount, float x, float y, int dir, int nativePaint)1354 private static native void nDrawTextRun(int renderer, char[] text, int index, int count, 1355 int contextIndex, int contextCount, float x, float y, int dir, int nativePaint); 1356 1357 @Override drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd, float x, float y, int dir, Paint paint)1358 public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd, 1359 float x, float y, int dir, Paint paint) { 1360 if ((start | end | end - start | text.length() - end) < 0) { 1361 throw new IndexOutOfBoundsException(); 1362 } 1363 1364 int modifiers = setupModifiers(paint); 1365 try { 1366 int flags = dir == 0 ? 0 : 1; 1367 if (text instanceof String || text instanceof SpannedString || 1368 text instanceof SpannableString) { 1369 nDrawTextRun(mRenderer, text.toString(), start, end, contextStart, 1370 contextEnd, x, y, flags, paint.mNativePaint); 1371 } else if (text instanceof GraphicsOperations) { 1372 ((GraphicsOperations) text).drawTextRun(this, start, end, 1373 contextStart, contextEnd, x, y, flags, paint); 1374 } else { 1375 int contextLen = contextEnd - contextStart; 1376 int len = end - start; 1377 char[] buf = TemporaryBuffer.obtain(contextLen); 1378 TextUtils.getChars(text, contextStart, contextEnd, buf, 0); 1379 nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen, 1380 x, y, flags, paint.mNativePaint); 1381 TemporaryBuffer.recycle(buf); 1382 } 1383 } finally { 1384 if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); 1385 } 1386 } 1387 nDrawTextRun(int renderer, String text, int start, int end, int contextStart, int contextEnd, float x, float y, int flags, int nativePaint)1388 private static native void nDrawTextRun(int renderer, String text, int start, int end, 1389 int contextStart, int contextEnd, float x, float y, int flags, int nativePaint); 1390 1391 @Override drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset, float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices, int indexOffset, int indexCount, Paint paint)1392 public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset, 1393 float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices, 1394 int indexOffset, int indexCount, Paint paint) { 1395 // TODO: Implement 1396 } 1397 setupModifiers(Bitmap b, Paint paint)1398 private int setupModifiers(Bitmap b, Paint paint) { 1399 if (b.getConfig() != Bitmap.Config.ALPHA_8) { 1400 final ColorFilter filter = paint.getColorFilter(); 1401 if (filter != null) { 1402 nSetupColorFilter(mRenderer, filter.nativeColorFilter); 1403 return MODIFIER_COLOR_FILTER; 1404 } 1405 1406 return MODIFIER_NONE; 1407 } else { 1408 return setupModifiers(paint); 1409 } 1410 } 1411 setupModifiers(Paint paint)1412 private int setupModifiers(Paint paint) { 1413 int modifiers = MODIFIER_NONE; 1414 1415 if (paint.hasShadow) { 1416 nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy, 1417 paint.shadowColor); 1418 modifiers |= MODIFIER_SHADOW; 1419 } 1420 1421 final Shader shader = paint.getShader(); 1422 if (shader != null) { 1423 nSetupShader(mRenderer, shader.native_shader); 1424 modifiers |= MODIFIER_SHADER; 1425 } 1426 1427 final ColorFilter filter = paint.getColorFilter(); 1428 if (filter != null) { 1429 nSetupColorFilter(mRenderer, filter.nativeColorFilter); 1430 modifiers |= MODIFIER_COLOR_FILTER; 1431 } 1432 1433 return modifiers; 1434 } 1435 setupModifiers(Paint paint, int flags)1436 private int setupModifiers(Paint paint, int flags) { 1437 int modifiers = MODIFIER_NONE; 1438 1439 if (paint.hasShadow && (flags & MODIFIER_SHADOW) != 0) { 1440 nSetupShadow(mRenderer, paint.shadowRadius, paint.shadowDx, paint.shadowDy, 1441 paint.shadowColor); 1442 modifiers |= MODIFIER_SHADOW; 1443 } 1444 1445 final Shader shader = paint.getShader(); 1446 if (shader != null && (flags & MODIFIER_SHADER) != 0) { 1447 nSetupShader(mRenderer, shader.native_shader); 1448 modifiers |= MODIFIER_SHADER; 1449 } 1450 1451 final ColorFilter filter = paint.getColorFilter(); 1452 if (filter != null && (flags & MODIFIER_COLOR_FILTER) != 0) { 1453 nSetupColorFilter(mRenderer, filter.nativeColorFilter); 1454 modifiers |= MODIFIER_COLOR_FILTER; 1455 } 1456 1457 return modifiers; 1458 } 1459 setupColorFilter(Paint paint)1460 private int setupColorFilter(Paint paint) { 1461 final ColorFilter filter = paint.getColorFilter(); 1462 if (filter != null) { 1463 nSetupColorFilter(mRenderer, filter.nativeColorFilter); 1464 return MODIFIER_COLOR_FILTER; 1465 } 1466 return MODIFIER_NONE; 1467 } 1468 nSetupShader(int renderer, int shader)1469 private static native void nSetupShader(int renderer, int shader); nSetupColorFilter(int renderer, int colorFilter)1470 private static native void nSetupColorFilter(int renderer, int colorFilter); nSetupShadow(int renderer, float radius, float dx, float dy, int color)1471 private static native void nSetupShadow(int renderer, float radius, 1472 float dx, float dy, int color); 1473 nResetModifiers(int renderer, int modifiers)1474 private static native void nResetModifiers(int renderer, int modifiers); 1475 } 1476