Canvas_Delegate.java revision b6d0da46a4c0d7a62dbdd68729614748bd36ce38
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.graphics; 18 19import com.android.ide.common.rendering.api.LayoutLog; 20import com.android.layoutlib.bridge.Bridge; 21import com.android.layoutlib.bridge.impl.DelegateManager; 22import com.android.layoutlib.bridge.impl.GcSnapshot; 23import com.android.tools.layoutlib.annotations.LayoutlibDelegate; 24 25import android.graphics.Bitmap.Config; 26import android.text.TextUtils; 27 28import java.awt.Color; 29import java.awt.Composite; 30import java.awt.Graphics2D; 31import java.awt.Rectangle; 32import java.awt.RenderingHints; 33import java.awt.Shape; 34import java.awt.geom.AffineTransform; 35import java.awt.geom.Arc2D; 36import java.awt.image.BufferedImage; 37 38 39/** 40 * Delegate implementing the native methods of android.graphics.Canvas 41 * 42 * Through the layoutlib_create tool, the original native methods of Canvas have been replaced 43 * by calls to methods of the same name in this delegate class. 44 * 45 * This class behaves like the original native implementation, but in Java, keeping previously 46 * native data into its own objects and mapping them to int that are sent back and forth between 47 * it and the original Canvas class. 48 * 49 * @see DelegateManager 50 * 51 */ 52public final class Canvas_Delegate { 53 54 // ---- delegate manager ---- 55 private static final DelegateManager<Canvas_Delegate> sManager = 56 new DelegateManager<Canvas_Delegate>(Canvas_Delegate.class); 57 58 // ---- delegate helper data ---- 59 60 private final static boolean[] sBoolOut = new boolean[1]; 61 62 // ---- delegate data ---- 63 private Bitmap_Delegate mBitmap; 64 private GcSnapshot mSnapshot; 65 66 private DrawFilter_Delegate mDrawFilter = null; 67 68 // ---- Public Helper methods ---- 69 70 /** 71 * Returns the native delegate associated to a given {@link Canvas} object. 72 */ 73 public static Canvas_Delegate getDelegate(Canvas canvas) { 74 return sManager.getDelegate(canvas.getNativeCanvas()); 75 } 76 77 /** 78 * Returns the native delegate associated to a given an int referencing a {@link Canvas} object. 79 */ 80 public static Canvas_Delegate getDelegate(long native_canvas) { 81 return sManager.getDelegate(native_canvas); 82 } 83 84 /** 85 * Returns the current {@link Graphics2D} used to draw. 86 */ 87 public GcSnapshot getSnapshot() { 88 return mSnapshot; 89 } 90 91 /** 92 * Returns the {@link DrawFilter} delegate or null if none have been set. 93 * 94 * @return the delegate or null. 95 */ 96 public DrawFilter_Delegate getDrawFilter() { 97 return mDrawFilter; 98 } 99 100 // ---- native methods ---- 101 102 @LayoutlibDelegate 103 /*package*/ static boolean isOpaque(Canvas thisCanvas) { 104 // get the delegate from the native int. 105 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); 106 if (canvasDelegate == null) { 107 return false; 108 } 109 110 return canvasDelegate.mBitmap.getConfig() == Config.RGB_565; 111 } 112 113 @LayoutlibDelegate 114 /*package*/ static int getWidth(Canvas thisCanvas) { 115 // get the delegate from the native int. 116 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); 117 if (canvasDelegate == null) { 118 return 0; 119 } 120 121 return canvasDelegate.mBitmap.getImage().getWidth(); 122 } 123 124 @LayoutlibDelegate 125 /*package*/ static int getHeight(Canvas thisCanvas) { 126 // get the delegate from the native int. 127 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); 128 if (canvasDelegate == null) { 129 return 0; 130 } 131 132 return canvasDelegate.mBitmap.getImage().getHeight(); 133 } 134 135 @LayoutlibDelegate 136 /*package*/ static void translate(Canvas thisCanvas, float dx, float dy) { 137 // get the delegate from the native int. 138 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); 139 if (canvasDelegate == null) { 140 return; 141 } 142 143 canvasDelegate.getSnapshot().translate(dx, dy); 144 } 145 146 @LayoutlibDelegate 147 /*package*/ static void rotate(Canvas thisCanvas, float degrees) { 148 // get the delegate from the native int. 149 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); 150 if (canvasDelegate == null) { 151 return; 152 } 153 154 canvasDelegate.getSnapshot().rotate(Math.toRadians(degrees)); 155 } 156 157 @LayoutlibDelegate 158 /*package*/ static void scale(Canvas thisCanvas, float sx, float sy) { 159 // get the delegate from the native int. 160 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); 161 if (canvasDelegate == null) { 162 return; 163 } 164 165 canvasDelegate.getSnapshot().scale(sx, sy); 166 } 167 168 @LayoutlibDelegate 169 /*package*/ static void skew(Canvas thisCanvas, float kx, float ky) { 170 // get the delegate from the native int. 171 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); 172 if (canvasDelegate == null) { 173 return; 174 } 175 176 // get the current top graphics2D object. 177 GcSnapshot g = canvasDelegate.getSnapshot(); 178 179 // get its current matrix 180 AffineTransform currentTx = g.getTransform(); 181 // get the AffineTransform for the given skew. 182 float[] mtx = Matrix_Delegate.getSkew(kx, ky); 183 AffineTransform matrixTx = Matrix_Delegate.getAffineTransform(mtx); 184 185 // combine them so that the given matrix is applied after. 186 currentTx.preConcatenate(matrixTx); 187 188 // give it to the graphics2D as a new matrix replacing all previous transform 189 g.setTransform(currentTx); 190 } 191 192 @LayoutlibDelegate 193 /*package*/ static boolean clipRect(Canvas thisCanvas, RectF rect) { 194 return clipRect(thisCanvas, rect.left, rect.top, rect.right, rect.bottom); 195 } 196 197 @LayoutlibDelegate 198 /*package*/ static boolean clipRect(Canvas thisCanvas, Rect rect) { 199 return clipRect(thisCanvas, (float) rect.left, (float) rect.top, 200 (float) rect.right, (float) rect.bottom); 201 } 202 203 @LayoutlibDelegate 204 /*package*/ static boolean clipRect(Canvas thisCanvas, float left, float top, float right, 205 float bottom) { 206 // get the delegate from the native int. 207 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); 208 if (canvasDelegate == null) { 209 return false; 210 } 211 212 return canvasDelegate.clipRect(left, top, right, bottom, Region.Op.INTERSECT.nativeInt); 213 } 214 215 @LayoutlibDelegate 216 /*package*/ static boolean clipRect(Canvas thisCanvas, int left, int top, int right, 217 int bottom) { 218 219 return clipRect(thisCanvas, (float) left, (float) top, (float) right, (float) bottom); 220 } 221 222 @LayoutlibDelegate 223 /*package*/ static int save(Canvas thisCanvas) { 224 return save(thisCanvas, Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG); 225 } 226 227 @LayoutlibDelegate 228 /*package*/ static int save(Canvas thisCanvas, int saveFlags) { 229 // get the delegate from the native int. 230 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); 231 if (canvasDelegate == null) { 232 return 0; 233 } 234 235 return canvasDelegate.save(saveFlags); 236 } 237 238 @LayoutlibDelegate 239 /*package*/ static void restore(Canvas thisCanvas) { 240 // get the delegate from the native int. 241 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); 242 if (canvasDelegate == null) { 243 return; 244 } 245 246 canvasDelegate.restore(); 247 } 248 249 @LayoutlibDelegate 250 /*package*/ static int getSaveCount(Canvas thisCanvas) { 251 // get the delegate from the native int. 252 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); 253 if (canvasDelegate == null) { 254 return 0; 255 } 256 257 return canvasDelegate.getSnapshot().size(); 258 } 259 260 @LayoutlibDelegate 261 /*package*/ static void restoreToCount(Canvas thisCanvas, int saveCount) { 262 // get the delegate from the native int. 263 Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); 264 if (canvasDelegate == null) { 265 return; 266 } 267 268 canvasDelegate.restoreTo(saveCount); 269 } 270 271 @LayoutlibDelegate 272 /*package*/ static void drawPoints(Canvas thisCanvas, float[] pts, int offset, int count, 273 Paint paint) { 274 // FIXME 275 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, 276 "Canvas.drawPoint is not supported.", null, null /*data*/); 277 } 278 279 @LayoutlibDelegate 280 /*package*/ static void drawPoint(Canvas thisCanvas, float x, float y, Paint paint) { 281 // FIXME 282 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, 283 "Canvas.drawPoint is not supported.", null, null /*data*/); 284 } 285 286 @LayoutlibDelegate 287 /*package*/ static void drawLines(Canvas thisCanvas, 288 final float[] pts, final int offset, final int count, 289 Paint paint) { 290 draw(thisCanvas.getNativeCanvas(), paint.mNativePaint, false /*compositeOnly*/, 291 false /*forceSrcMode*/, new GcSnapshot.Drawable() { 292 @Override 293 public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) { 294 for (int i = 0 ; i < count ; i += 4) { 295 graphics.drawLine((int)pts[i + offset], (int)pts[i + offset + 1], 296 (int)pts[i + offset + 2], (int)pts[i + offset + 3]); 297 } 298 } 299 }); 300 } 301 302 @LayoutlibDelegate 303 /*package*/ static void freeCaches() { 304 // nothing to be done here. 305 } 306 307 @LayoutlibDelegate 308 /*package*/ static void freeTextLayoutCaches() { 309 // nothing to be done here yet. 310 } 311 312 @LayoutlibDelegate 313 /*package*/ static long initRaster(long nativeBitmapOrZero) { 314 if (nativeBitmapOrZero > 0) { 315 // get the Bitmap from the int 316 Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nativeBitmapOrZero); 317 318 // create a new Canvas_Delegate with the given bitmap and return its new native int. 319 Canvas_Delegate newDelegate = new Canvas_Delegate(bitmapDelegate); 320 321 return sManager.addNewDelegate(newDelegate); 322 } 323 324 // create a new Canvas_Delegate and return its new native int. 325 Canvas_Delegate newDelegate = new Canvas_Delegate(); 326 327 return sManager.addNewDelegate(newDelegate); 328 } 329 330 @LayoutlibDelegate 331 /*package*/ static void copyNativeCanvasState(long srcCanvas, long dstCanvas) { 332 // get the delegate from the native int. 333 Canvas_Delegate srcCanvasDelegate = sManager.getDelegate(srcCanvas); 334 if (srcCanvasDelegate == null) { 335 return; 336 } 337 338 // get the delegate from the native int. 339 Canvas_Delegate dstCanvasDelegate = sManager.getDelegate(dstCanvas); 340 if (dstCanvasDelegate == null) { 341 return; 342 } 343 // TODO: actually copy the canvas state. 344 } 345 346 @LayoutlibDelegate 347 /*package*/ static int native_saveLayer(long nativeCanvas, RectF bounds, 348 long paint, int layerFlags) { 349 // get the delegate from the native int. 350 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); 351 if (canvasDelegate == null) { 352 return 0; 353 } 354 355 Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(paint); 356 if (paintDelegate == null) { 357 return 0; 358 } 359 360 return canvasDelegate.saveLayer(bounds, paintDelegate, layerFlags); 361 } 362 363 @LayoutlibDelegate 364 /*package*/ static int native_saveLayer(long nativeCanvas, float l, 365 float t, float r, float b, 366 long paint, int layerFlags) { 367 // get the delegate from the native int. 368 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); 369 if (canvasDelegate == null) { 370 return 0; 371 } 372 373 Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(paint); 374 if (paintDelegate == null) { 375 return 0; 376 } 377 378 return canvasDelegate.saveLayer(new RectF(l, t, r, b), 379 paintDelegate, layerFlags); 380 } 381 382 @LayoutlibDelegate 383 /*package*/ static int native_saveLayerAlpha(long nativeCanvas, 384 RectF bounds, int alpha, 385 int layerFlags) { 386 // get the delegate from the native int. 387 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); 388 if (canvasDelegate == null) { 389 return 0; 390 } 391 392 return canvasDelegate.saveLayerAlpha(bounds, alpha, layerFlags); 393 } 394 395 @LayoutlibDelegate 396 /*package*/ static int native_saveLayerAlpha(long nativeCanvas, float l, 397 float t, float r, float b, 398 int alpha, int layerFlags) { 399 // get the delegate from the native int. 400 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); 401 if (canvasDelegate == null) { 402 return 0; 403 } 404 405 return canvasDelegate.saveLayerAlpha(new RectF(l, t, r, b), alpha, layerFlags); 406 } 407 408 409 @LayoutlibDelegate 410 /*package*/ static void native_concat(long nCanvas, long nMatrix) { 411 // get the delegate from the native int. 412 Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas); 413 if (canvasDelegate == null) { 414 return; 415 } 416 417 Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix); 418 if (matrixDelegate == null) { 419 return; 420 } 421 422 // get the current top graphics2D object. 423 GcSnapshot snapshot = canvasDelegate.getSnapshot(); 424 425 // get its current matrix 426 AffineTransform currentTx = snapshot.getTransform(); 427 // get the AffineTransform of the given matrix 428 AffineTransform matrixTx = matrixDelegate.getAffineTransform(); 429 430 // combine them so that the given matrix is applied after. 431 currentTx.concatenate(matrixTx); 432 433 // give it to the graphics2D as a new matrix replacing all previous transform 434 snapshot.setTransform(currentTx); 435 } 436 437 @LayoutlibDelegate 438 /*package*/ static void native_setMatrix(long nCanvas, long nMatrix) { 439 // get the delegate from the native int. 440 Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas); 441 if (canvasDelegate == null) { 442 return; 443 } 444 445 Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix); 446 if (matrixDelegate == null) { 447 return; 448 } 449 450 // get the current top graphics2D object. 451 GcSnapshot snapshot = canvasDelegate.getSnapshot(); 452 453 // get the AffineTransform of the given matrix 454 AffineTransform matrixTx = matrixDelegate.getAffineTransform(); 455 456 // give it to the graphics2D as a new matrix replacing all previous transform 457 snapshot.setTransform(matrixTx); 458 459 if (matrixDelegate.hasPerspective()) { 460 assert false; 461 Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_AFFINE, 462 "android.graphics.Canvas#setMatrix(android.graphics.Matrix) only " + 463 "supports affine transformations.", null, null /*data*/); 464 } 465 } 466 467 @LayoutlibDelegate 468 /*package*/ static boolean native_clipRect(long nCanvas, 469 float left, float top, 470 float right, float bottom, 471 int regionOp) { 472 473 // get the delegate from the native int. 474 Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas); 475 if (canvasDelegate == null) { 476 return false; 477 } 478 479 return canvasDelegate.clipRect(left, top, right, bottom, regionOp); 480 } 481 482 @LayoutlibDelegate 483 /*package*/ static boolean native_clipPath(long nativeCanvas, 484 long nativePath, 485 int regionOp) { 486 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); 487 if (canvasDelegate == null) { 488 return true; 489 } 490 491 Path_Delegate pathDelegate = Path_Delegate.getDelegate(nativePath); 492 if (pathDelegate == null) { 493 return true; 494 } 495 496 return canvasDelegate.mSnapshot.clip(pathDelegate.getJavaShape(), regionOp); 497 } 498 499 @LayoutlibDelegate 500 /*package*/ static boolean native_clipRegion(long nativeCanvas, 501 long nativeRegion, 502 int regionOp) { 503 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); 504 if (canvasDelegate == null) { 505 return true; 506 } 507 508 Region_Delegate region = Region_Delegate.getDelegate(nativeRegion); 509 if (region == null) { 510 return true; 511 } 512 513 return canvasDelegate.mSnapshot.clip(region.getJavaArea(), regionOp); 514 } 515 516 @LayoutlibDelegate 517 /*package*/ static void nativeSetDrawFilter(long nativeCanvas, long nativeFilter) { 518 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); 519 if (canvasDelegate == null) { 520 return; 521 } 522 523 canvasDelegate.mDrawFilter = DrawFilter_Delegate.getDelegate(nativeFilter); 524 525 if (canvasDelegate.mDrawFilter != null && 526 canvasDelegate.mDrawFilter.isSupported() == false) { 527 Bridge.getLog().fidelityWarning(LayoutLog.TAG_DRAWFILTER, 528 canvasDelegate.mDrawFilter.getSupportMessage(), null, null /*data*/); 529 } 530 } 531 532 @LayoutlibDelegate 533 /*package*/ static boolean native_getClipBounds(long nativeCanvas, 534 Rect bounds) { 535 // get the delegate from the native int. 536 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); 537 if (canvasDelegate == null) { 538 return false; 539 } 540 541 Rectangle rect = canvasDelegate.getSnapshot().getClip().getBounds(); 542 if (rect != null && rect.isEmpty() == false) { 543 bounds.left = rect.x; 544 bounds.top = rect.y; 545 bounds.right = rect.x + rect.width; 546 bounds.bottom = rect.y + rect.height; 547 return true; 548 } 549 550 return false; 551 } 552 553 @LayoutlibDelegate 554 /*package*/ static void native_getCTM(long canvas, long matrix) { 555 // get the delegate from the native int. 556 Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas); 557 if (canvasDelegate == null) { 558 return; 559 } 560 561 Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix); 562 if (matrixDelegate == null) { 563 return; 564 } 565 566 AffineTransform transform = canvasDelegate.getSnapshot().getTransform(); 567 matrixDelegate.set(Matrix_Delegate.makeValues(transform)); 568 } 569 570 @LayoutlibDelegate 571 /*package*/ static boolean native_quickReject(long nativeCanvas, 572 RectF rect) { 573 // FIXME properly implement quickReject 574 return false; 575 } 576 577 @LayoutlibDelegate 578 /*package*/ static boolean native_quickReject(long nativeCanvas, 579 long path) { 580 // FIXME properly implement quickReject 581 return false; 582 } 583 584 @LayoutlibDelegate 585 /*package*/ static boolean native_quickReject(long nativeCanvas, 586 float left, float top, 587 float right, float bottom) { 588 // FIXME properly implement quickReject 589 return false; 590 } 591 592 @LayoutlibDelegate 593 /*package*/ static void native_drawRGB(long nativeCanvas, int r, int g, int b) { 594 native_drawColor(nativeCanvas, 0xFF000000 | r << 16 | (g&0xFF) << 8 | (b&0xFF), 595 PorterDuff.Mode.SRC_OVER.nativeInt); 596 597 } 598 599 @LayoutlibDelegate 600 /*package*/ static void native_drawARGB(long nativeCanvas, int a, int r, int g, int b) { 601 native_drawColor(nativeCanvas, a << 24 | (r&0xFF) << 16 | (g&0xFF) << 8 | (b&0xFF), 602 PorterDuff.Mode.SRC_OVER.nativeInt); 603 } 604 605 @LayoutlibDelegate 606 /*package*/ static void native_drawColor(long nativeCanvas, int color) { 607 native_drawColor(nativeCanvas, color, PorterDuff.Mode.SRC_OVER.nativeInt); 608 } 609 610 @LayoutlibDelegate 611 /*package*/ static void native_drawColor(long nativeCanvas, final int color, final int mode) { 612 // get the delegate from the native int. 613 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); 614 if (canvasDelegate == null) { 615 return; 616 } 617 618 final int w = canvasDelegate.mBitmap.getImage().getWidth(); 619 final int h = canvasDelegate.mBitmap.getImage().getHeight(); 620 draw(nativeCanvas, new GcSnapshot.Drawable() { 621 622 @Override 623 public void draw(Graphics2D graphics, Paint_Delegate paint) { 624 // reset its transform just in case 625 graphics.setTransform(new AffineTransform()); 626 627 // set the color 628 graphics.setColor(new Color(color, true /*alpha*/)); 629 630 Composite composite = PorterDuffXfermode_Delegate.getComposite( 631 PorterDuffXfermode_Delegate.getPorterDuffMode(mode), 0xFF); 632 if (composite != null) { 633 graphics.setComposite(composite); 634 } 635 636 graphics.fillRect(0, 0, w, h); 637 } 638 }); 639 } 640 641 @LayoutlibDelegate 642 /*package*/ static void native_drawPaint(long nativeCanvas, long paint) { 643 // FIXME 644 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, 645 "Canvas.drawPaint is not supported.", null, null /*data*/); 646 } 647 648 @LayoutlibDelegate 649 /*package*/ static void native_drawLine(long nativeCanvas, 650 final float startX, final float startY, final float stopX, final float stopY, 651 long paint) { 652 653 draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, 654 new GcSnapshot.Drawable() { 655 @Override 656 public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) { 657 graphics.drawLine((int)startX, (int)startY, (int)stopX, (int)stopY); 658 } 659 }); 660 } 661 662 @LayoutlibDelegate 663 /*package*/ static void native_drawRect(long nativeCanvas, RectF rect, long paint) { 664 native_drawRect(nativeCanvas, rect.left, rect.top, rect.right, rect.bottom, paint); 665 } 666 667 @LayoutlibDelegate 668 /*package*/ static void native_drawRect(long nativeCanvas, 669 final float left, final float top, final float right, final float bottom, long paint) { 670 671 draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, 672 new GcSnapshot.Drawable() { 673 @Override 674 public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) { 675 int style = paintDelegate.getStyle(); 676 677 // draw 678 if (style == Paint.Style.FILL.nativeInt || 679 style == Paint.Style.FILL_AND_STROKE.nativeInt) { 680 graphics.fillRect((int)left, (int)top, 681 (int)(right-left), (int)(bottom-top)); 682 } 683 684 if (style == Paint.Style.STROKE.nativeInt || 685 style == Paint.Style.FILL_AND_STROKE.nativeInt) { 686 graphics.drawRect((int)left, (int)top, 687 (int)(right-left), (int)(bottom-top)); 688 } 689 } 690 }); 691 } 692 693 @LayoutlibDelegate 694 /*package*/ static void native_drawOval(long nativeCanvas, final RectF oval, long paint) { 695 if (oval.right > oval.left && oval.bottom > oval.top) { 696 draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, 697 new GcSnapshot.Drawable() { 698 @Override 699 public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) { 700 int style = paintDelegate.getStyle(); 701 702 // draw 703 if (style == Paint.Style.FILL.nativeInt || 704 style == Paint.Style.FILL_AND_STROKE.nativeInt) { 705 graphics.fillOval((int)oval.left, (int)oval.top, 706 (int)oval.width(), (int)oval.height()); 707 } 708 709 if (style == Paint.Style.STROKE.nativeInt || 710 style == Paint.Style.FILL_AND_STROKE.nativeInt) { 711 graphics.drawOval((int)oval.left, (int)oval.top, 712 (int)oval.width(), (int)oval.height()); 713 } 714 } 715 }); 716 } 717 } 718 719 @LayoutlibDelegate 720 /*package*/ static void native_drawCircle(long nativeCanvas, 721 float cx, float cy, float radius, long paint) { 722 native_drawOval(nativeCanvas, 723 new RectF(cx - radius, cy - radius, cx + radius, cy + radius), 724 paint); 725 } 726 727 @LayoutlibDelegate 728 /*package*/ static void native_drawArc(long nativeCanvas, 729 final RectF oval, final float startAngle, final float sweep, 730 final boolean useCenter, long paint) { 731 if (oval.right > oval.left && oval.bottom > oval.top) { 732 draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, 733 new GcSnapshot.Drawable() { 734 @Override 735 public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) { 736 int style = paintDelegate.getStyle(); 737 738 Arc2D.Float arc = new Arc2D.Float( 739 oval.left, oval.top, oval.width(), oval.height(), 740 -startAngle, -sweep, 741 useCenter ? Arc2D.PIE : Arc2D.OPEN); 742 743 // draw 744 if (style == Paint.Style.FILL.nativeInt || 745 style == Paint.Style.FILL_AND_STROKE.nativeInt) { 746 graphics.fill(arc); 747 } 748 749 if (style == Paint.Style.STROKE.nativeInt || 750 style == Paint.Style.FILL_AND_STROKE.nativeInt) { 751 graphics.draw(arc); 752 } 753 } 754 }); 755 } 756 } 757 758 @LayoutlibDelegate 759 /*package*/ static void native_drawRoundRect(long nativeCanvas, 760 final RectF rect, final float rx, final float ry, long paint) { 761 762 draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, 763 new GcSnapshot.Drawable() { 764 @Override 765 public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) { 766 int style = paintDelegate.getStyle(); 767 768 // draw 769 if (style == Paint.Style.FILL.nativeInt || 770 style == Paint.Style.FILL_AND_STROKE.nativeInt) { 771 graphics.fillRoundRect( 772 (int)rect.left, (int)rect.top, 773 (int)rect.width(), (int)rect.height(), 774 (int)rx, (int)ry); 775 } 776 777 if (style == Paint.Style.STROKE.nativeInt || 778 style == Paint.Style.FILL_AND_STROKE.nativeInt) { 779 graphics.drawRoundRect( 780 (int)rect.left, (int)rect.top, 781 (int)rect.width(), (int)rect.height(), 782 (int)rx, (int)ry); 783 } 784 } 785 }); 786 } 787 788 @LayoutlibDelegate 789 /*package*/ static void native_drawPath(long nativeCanvas, long path, long paint) { 790 final Path_Delegate pathDelegate = Path_Delegate.getDelegate(path); 791 if (pathDelegate == null) { 792 return; 793 } 794 795 draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, 796 new GcSnapshot.Drawable() { 797 @Override 798 public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) { 799 Shape shape = pathDelegate.getJavaShape(); 800 int style = paintDelegate.getStyle(); 801 802 if (style == Paint.Style.FILL.nativeInt || 803 style == Paint.Style.FILL_AND_STROKE.nativeInt) { 804 graphics.fill(shape); 805 } 806 807 if (style == Paint.Style.STROKE.nativeInt || 808 style == Paint.Style.FILL_AND_STROKE.nativeInt) { 809 graphics.draw(shape); 810 } 811 } 812 }); 813 } 814 815 @LayoutlibDelegate 816 /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, long bitmap, 817 float left, float top, 818 long nativePaintOrZero, 819 int canvasDensity, 820 int screenDensity, 821 int bitmapDensity) { 822 // get the delegate from the native int. 823 Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap); 824 if (bitmapDelegate == null) { 825 return; 826 } 827 828 BufferedImage image = bitmapDelegate.getImage(); 829 float right = left + image.getWidth(); 830 float bottom = top + image.getHeight(); 831 832 drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, 833 0, 0, image.getWidth(), image.getHeight(), 834 (int)left, (int)top, (int)right, (int)bottom); 835 } 836 837 @LayoutlibDelegate 838 /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, long bitmap, 839 Rect src, RectF dst, 840 long nativePaintOrZero, 841 int screenDensity, 842 int bitmapDensity) { 843 // get the delegate from the native int. 844 Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap); 845 if (bitmapDelegate == null) { 846 return; 847 } 848 849 BufferedImage image = bitmapDelegate.getImage(); 850 851 if (src == null) { 852 drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, 853 0, 0, image.getWidth(), image.getHeight(), 854 (int)dst.left, (int)dst.top, (int)dst.right, (int)dst.bottom); 855 } else { 856 drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, 857 src.left, src.top, src.width(), src.height(), 858 (int)dst.left, (int)dst.top, (int)dst.right, (int)dst.bottom); 859 } 860 } 861 862 @LayoutlibDelegate 863 /*package*/ static void native_drawBitmap(long nativeCanvas, long bitmap, 864 Rect src, Rect dst, 865 long nativePaintOrZero, 866 int screenDensity, 867 int bitmapDensity) { 868 // get the delegate from the native int. 869 Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap); 870 if (bitmapDelegate == null) { 871 return; 872 } 873 874 BufferedImage image = bitmapDelegate.getImage(); 875 876 if (src == null) { 877 drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, 878 0, 0, image.getWidth(), image.getHeight(), 879 dst.left, dst.top, dst.right, dst.bottom); 880 } else { 881 drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, 882 src.left, src.top, src.width(), src.height(), 883 dst.left, dst.top, dst.right, dst.bottom); 884 } 885 } 886 887 @LayoutlibDelegate 888 /*package*/ static void native_drawBitmap(long nativeCanvas, int[] colors, 889 int offset, int stride, final float x, 890 final float y, int width, int height, 891 boolean hasAlpha, 892 long nativePaintOrZero) { 893 894 // create a temp BufferedImage containing the content. 895 final BufferedImage image = new BufferedImage(width, height, 896 hasAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB); 897 image.setRGB(0, 0, width, height, colors, offset, stride); 898 899 draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, false /*forceSrcMode*/, 900 new GcSnapshot.Drawable() { 901 @Override 902 public void draw(Graphics2D graphics, Paint_Delegate paint) { 903 if (paint != null && paint.isFilterBitmap()) { 904 graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 905 RenderingHints.VALUE_INTERPOLATION_BILINEAR); 906 } 907 908 graphics.drawImage(image, (int) x, (int) y, null); 909 } 910 }); 911 } 912 913 @LayoutlibDelegate 914 /*package*/ static void nativeDrawBitmapMatrix(long nCanvas, long nBitmap, 915 long nMatrix, long nPaint) { 916 // get the delegate from the native int. 917 Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas); 918 if (canvasDelegate == null) { 919 return; 920 } 921 922 // get the delegate from the native int, which can be null 923 Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint); 924 925 // get the delegate from the native int. 926 Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nBitmap); 927 if (bitmapDelegate == null) { 928 return; 929 } 930 931 final BufferedImage image = getImageToDraw(bitmapDelegate, paintDelegate, sBoolOut); 932 933 Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix); 934 if (matrixDelegate == null) { 935 return; 936 } 937 938 final AffineTransform mtx = matrixDelegate.getAffineTransform(); 939 940 canvasDelegate.getSnapshot().draw(new GcSnapshot.Drawable() { 941 @Override 942 public void draw(Graphics2D graphics, Paint_Delegate paint) { 943 if (paint != null && paint.isFilterBitmap()) { 944 graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 945 RenderingHints.VALUE_INTERPOLATION_BILINEAR); 946 } 947 948 //FIXME add support for canvas, screen and bitmap densities. 949 graphics.drawImage(image, mtx, null); 950 } 951 }, paintDelegate, true /*compositeOnly*/, false /*forceSrcMode*/); 952 } 953 954 @LayoutlibDelegate 955 /*package*/ static void nativeDrawBitmapMesh(long nCanvas, long nBitmap, 956 int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors, 957 int colorOffset, long nPaint) { 958 // FIXME 959 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, 960 "Canvas.drawBitmapMesh is not supported.", null, null /*data*/); 961 } 962 963 @LayoutlibDelegate 964 /*package*/ static void nativeDrawVertices(long nCanvas, int mode, int n, 965 float[] verts, int vertOffset, 966 float[] texs, int texOffset, 967 int[] colors, int colorOffset, 968 short[] indices, int indexOffset, 969 int indexCount, long nPaint) { 970 // FIXME 971 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, 972 "Canvas.drawVertices is not supported.", null, null /*data*/); 973 } 974 975 @LayoutlibDelegate 976 /*package*/ static void native_drawText(long nativeCanvas, 977 final char[] text, final int index, final int count, 978 final float startX, final float startY, final int flags, long paint, 979 long typeface) { 980 981 // TODO: use typeface. 982 draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, 983 new GcSnapshot.Drawable() { 984 @Override 985 public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) { 986 // WARNING: the logic in this method is similar to Paint_Delegate.measureText. 987 // Any change to this method should be reflected in Paint.measureText 988 // Paint.TextAlign indicates how the text is positioned relative to X. 989 // LEFT is the default and there's nothing to do. 990 float x = startX; 991 int limit = index + count; 992 boolean isRtl = flags == Canvas.DIRECTION_RTL; 993 if (paintDelegate.getTextAlign() != Paint.Align.LEFT.nativeInt) { 994 RectF bounds = paintDelegate.measureText(text, index, count, isRtl); 995 float m = bounds.right - bounds.left; 996 if (paintDelegate.getTextAlign() == Paint.Align.CENTER.nativeInt) { 997 x -= m / 2; 998 } else if (paintDelegate.getTextAlign() == Paint.Align.RIGHT.nativeInt) { 999 x -= m; 1000 } 1001 } 1002 1003 new BidiRenderer(graphics, paintDelegate, text).renderText( 1004 index, limit, isRtl, null, 0, true, x, startY); 1005 } 1006 }); 1007 } 1008 1009 @LayoutlibDelegate 1010 /*package*/ static void native_drawText(long nativeCanvas, String text, 1011 int start, int end, float x, float y, final int flags, long paint, 1012 long typeface) { 1013 int count = end - start; 1014 char[] buffer = TemporaryBuffer.obtain(count); 1015 TextUtils.getChars(text, start, end, buffer, 0); 1016 1017 native_drawText(nativeCanvas, buffer, 0, count, x, y, flags, paint, typeface); 1018 } 1019 1020 @LayoutlibDelegate 1021 /*package*/ static void native_drawTextRun(long nativeCanvas, String text, 1022 int start, int end, int contextStart, int contextEnd, 1023 float x, float y, int flags, long paint, long typeface) { 1024 int count = end - start; 1025 char[] buffer = TemporaryBuffer.obtain(count); 1026 TextUtils.getChars(text, start, end, buffer, 0); 1027 1028 native_drawText(nativeCanvas, buffer, 0, count, x, y, flags, paint, typeface); 1029 } 1030 1031 @LayoutlibDelegate 1032 /*package*/ static void native_drawTextRun(long nativeCanvas, char[] text, 1033 int start, int count, int contextStart, int contextCount, 1034 float x, float y, int flags, long paint, long typeface) { 1035 native_drawText(nativeCanvas, text, start, count, x, y, flags, paint, typeface); 1036 } 1037 1038 @LayoutlibDelegate 1039 /*package*/ static void native_drawPosText(long nativeCanvas, 1040 char[] text, int index, 1041 int count, float[] pos, 1042 long paint) { 1043 // FIXME 1044 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, 1045 "Canvas.drawPosText is not supported.", null, null /*data*/); 1046 } 1047 1048 @LayoutlibDelegate 1049 /*package*/ static void native_drawPosText(long nativeCanvas, 1050 String text, float[] pos, 1051 long paint) { 1052 // FIXME 1053 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, 1054 "Canvas.drawPosText is not supported.", null, null /*data*/); 1055 } 1056 1057 @LayoutlibDelegate 1058 /*package*/ static void native_drawTextOnPath(long nativeCanvas, 1059 char[] text, int index, 1060 int count, long path, 1061 float hOffset, 1062 float vOffset, int bidiFlags, 1063 long paint) { 1064 // FIXME 1065 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, 1066 "Canvas.drawTextOnPath is not supported.", null, null /*data*/); 1067 } 1068 1069 @LayoutlibDelegate 1070 /*package*/ static void native_drawTextOnPath(long nativeCanvas, 1071 String text, long path, 1072 float hOffset, 1073 float vOffset, 1074 int flags, long paint) { 1075 // FIXME 1076 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, 1077 "Canvas.drawTextOnPath is not supported.", null, null /*data*/); 1078 } 1079 1080 @LayoutlibDelegate 1081 /*package*/ static void finalizer(long nativeCanvas) { 1082 // get the delegate from the native int so that it can be disposed. 1083 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); 1084 if (canvasDelegate == null) { 1085 return; 1086 } 1087 1088 canvasDelegate.dispose(); 1089 1090 // remove it from the manager. 1091 sManager.removeJavaReferenceFor(nativeCanvas); 1092 } 1093 1094 // ---- Private delegate/helper methods ---- 1095 1096 /** 1097 * Executes a {@link GcSnapshot.Drawable} with a given canvas and paint. 1098 * <p>Note that the drawable may actually be executed several times if there are 1099 * layers involved (see {@link #saveLayer(RectF, int, int)}. 1100 */ 1101 private static void draw(long nCanvas, long nPaint, boolean compositeOnly, boolean forceSrcMode, 1102 GcSnapshot.Drawable drawable) { 1103 // get the delegate from the native int. 1104 Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas); 1105 if (canvasDelegate == null) { 1106 return; 1107 } 1108 1109 // get the paint which can be null if nPaint is 0; 1110 Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint); 1111 1112 canvasDelegate.getSnapshot().draw(drawable, paintDelegate, compositeOnly, forceSrcMode); 1113 } 1114 1115 /** 1116 * Executes a {@link GcSnapshot.Drawable} with a given canvas. No paint object will be provided 1117 * to {@link GcSnapshot.Drawable#draw(Graphics2D, Paint_Delegate)}. 1118 * <p>Note that the drawable may actually be executed several times if there are 1119 * layers involved (see {@link #saveLayer(RectF, int, int)}. 1120 */ 1121 private static void draw(long nCanvas, GcSnapshot.Drawable drawable) { 1122 // get the delegate from the native int. 1123 Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas); 1124 if (canvasDelegate == null) { 1125 return; 1126 } 1127 1128 canvasDelegate.mSnapshot.draw(drawable); 1129 } 1130 1131 private Canvas_Delegate(Bitmap_Delegate bitmap) { 1132 mSnapshot = GcSnapshot.createDefaultSnapshot(mBitmap = bitmap); 1133 } 1134 1135 private Canvas_Delegate() { 1136 mSnapshot = GcSnapshot.createDefaultSnapshot(null /*image*/); 1137 } 1138 1139 /** 1140 * Disposes of the {@link Graphics2D} stack. 1141 */ 1142 private void dispose() { 1143 mSnapshot.dispose(); 1144 } 1145 1146 private int save(int saveFlags) { 1147 // get the current save count 1148 int count = mSnapshot.size(); 1149 1150 mSnapshot = mSnapshot.save(saveFlags); 1151 1152 // return the old save count 1153 return count; 1154 } 1155 1156 private int saveLayerAlpha(RectF rect, int alpha, int saveFlags) { 1157 Paint_Delegate paint = new Paint_Delegate(); 1158 paint.setAlpha(alpha); 1159 return saveLayer(rect, paint, saveFlags); 1160 } 1161 1162 private int saveLayer(RectF rect, Paint_Delegate paint, int saveFlags) { 1163 // get the current save count 1164 int count = mSnapshot.size(); 1165 1166 mSnapshot = mSnapshot.saveLayer(rect, paint, saveFlags); 1167 1168 // return the old save count 1169 return count; 1170 } 1171 1172 /** 1173 * Restores the {@link GcSnapshot} to <var>saveCount</var> 1174 * @param saveCount the saveCount 1175 */ 1176 private void restoreTo(int saveCount) { 1177 mSnapshot = mSnapshot.restoreTo(saveCount); 1178 } 1179 1180 /** 1181 * Restores the {@link GcSnapshot} to <var>saveCount</var> 1182 * @param saveCount the saveCount 1183 */ 1184 private void restore() { 1185 mSnapshot = mSnapshot.restore(); 1186 } 1187 1188 private boolean clipRect(float left, float top, float right, float bottom, int regionOp) { 1189 return mSnapshot.clipRect(left, top, right, bottom, regionOp); 1190 } 1191 1192 private void setBitmap(Bitmap_Delegate bitmap) { 1193 mBitmap = bitmap; 1194 assert mSnapshot.size() == 1; 1195 mSnapshot.setBitmap(mBitmap); 1196 } 1197 1198 private static void drawBitmap( 1199 long nativeCanvas, 1200 Bitmap_Delegate bitmap, 1201 long nativePaintOrZero, 1202 final int sleft, final int stop, final int sright, final int sbottom, 1203 final int dleft, final int dtop, final int dright, final int dbottom) { 1204 // get the delegate from the native int. 1205 Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); 1206 if (canvasDelegate == null) { 1207 return; 1208 } 1209 1210 // get the paint, which could be null if the int is 0 1211 Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nativePaintOrZero); 1212 1213 final BufferedImage image = getImageToDraw(bitmap, paintDelegate, sBoolOut); 1214 1215 draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, sBoolOut[0], 1216 new GcSnapshot.Drawable() { 1217 @Override 1218 public void draw(Graphics2D graphics, Paint_Delegate paint) { 1219 if (paint != null && paint.isFilterBitmap()) { 1220 graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 1221 RenderingHints.VALUE_INTERPOLATION_BILINEAR); 1222 } 1223 1224 //FIXME add support for canvas, screen and bitmap densities. 1225 graphics.drawImage(image, dleft, dtop, dright, dbottom, 1226 sleft, stop, sright, sbottom, null); 1227 } 1228 }); 1229 } 1230 1231 1232 /** 1233 * Returns a BufferedImage ready for drawing, based on the bitmap and paint delegate. 1234 * The image returns, through a 1-size boolean array, whether the drawing code should 1235 * use a SRC composite no matter what the paint says. 1236 * 1237 * @param bitmap the bitmap 1238 * @param paint the paint that will be used to draw 1239 * @param forceSrcMode whether the composite will have to be SRC 1240 * @return the image to draw 1241 */ 1242 private static BufferedImage getImageToDraw(Bitmap_Delegate bitmap, Paint_Delegate paint, 1243 boolean[] forceSrcMode) { 1244 BufferedImage image = bitmap.getImage(); 1245 forceSrcMode[0] = false; 1246 1247 // if the bitmap config is alpha_8, then we erase all color value from it 1248 // before drawing it. 1249 if (bitmap.getConfig() == Bitmap.Config.ALPHA_8) { 1250 fixAlpha8Bitmap(image); 1251 } else if (bitmap.hasAlpha() == false) { 1252 // hasAlpha is merely a rendering hint. There can in fact be alpha values 1253 // in the bitmap but it should be ignored at drawing time. 1254 // There is two ways to do this: 1255 // - override the composite to be SRC. This can only be used if the composite 1256 // was going to be SRC or SRC_OVER in the first place 1257 // - Create a different bitmap to draw in which all the alpha channel values is set 1258 // to 0xFF. 1259 if (paint != null) { 1260 Xfermode_Delegate xfermodeDelegate = paint.getXfermode(); 1261 if (xfermodeDelegate instanceof PorterDuffXfermode_Delegate) { 1262 PorterDuff.Mode mode = 1263 ((PorterDuffXfermode_Delegate)xfermodeDelegate).getMode(); 1264 1265 forceSrcMode[0] = mode == PorterDuff.Mode.SRC_OVER || 1266 mode == PorterDuff.Mode.SRC; 1267 } 1268 } 1269 1270 // if we can't force SRC mode, then create a temp bitmap of TYPE_RGB 1271 if (forceSrcMode[0] == false) { 1272 image = Bitmap_Delegate.createCopy(image, BufferedImage.TYPE_INT_RGB, 0xFF); 1273 } 1274 } 1275 1276 return image; 1277 } 1278 1279 private static void fixAlpha8Bitmap(final BufferedImage image) { 1280 int w = image.getWidth(); 1281 int h = image.getHeight(); 1282 int[] argb = new int[w * h]; 1283 image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth()); 1284 1285 final int length = argb.length; 1286 for (int i = 0 ; i < length; i++) { 1287 argb[i] &= 0xFF000000; 1288 } 1289 image.setRGB(0, 0, w, h, argb, 0, w); 1290 } 1291} 1292 1293