|
1 | 1 | package me.angrybyte.sillyandroid.extras;
|
2 | 2 |
|
3 | 3 | import android.annotation.SuppressLint;
|
| 4 | +import android.annotation.TargetApi; |
4 | 5 | import android.app.Activity;
|
| 6 | +import android.content.Context; |
| 7 | +import android.content.res.ColorStateList; |
| 8 | +import android.graphics.Bitmap; |
5 | 9 | import android.graphics.Color;
|
| 10 | +import android.graphics.PorterDuff; |
| 11 | +import android.graphics.PorterDuffColorFilter; |
| 12 | +import android.graphics.Rect; |
| 13 | +import android.graphics.drawable.BitmapDrawable; |
| 14 | +import android.graphics.drawable.ColorDrawable; |
| 15 | +import android.graphics.drawable.Drawable; |
| 16 | +import android.graphics.drawable.VectorDrawable; |
| 17 | +import android.os.Build; |
6 | 18 | import android.support.annotation.NonNull;
|
| 19 | +import android.support.graphics.drawable.VectorDrawableCompat; |
7 | 20 | import android.util.Pair;
|
8 | 21 |
|
9 | 22 | import org.junit.After;
|
|
14 | 27 | import org.robolectric.RobolectricTestRunner;
|
15 | 28 | import org.robolectric.annotation.Config;
|
16 | 29 |
|
| 30 | +import java.lang.reflect.Constructor; |
| 31 | +import java.lang.reflect.InvocationTargetException; |
| 32 | +import java.nio.ByteBuffer; |
| 33 | +import java.nio.ByteOrder; |
17 | 34 | import java.util.LinkedList;
|
18 | 35 | import java.util.List;
|
19 | 36 |
|
20 | 37 | import me.angrybyte.sillyandroid.BuildConfig;
|
21 | 38 |
|
22 | 39 | import static junit.framework.Assert.assertEquals;
|
| 40 | +import static junit.framework.Assert.assertTrue; |
23 | 41 |
|
24 | 42 | /**
|
25 | 43 | * A set of tests related to the {@link Coloring}.
|
@@ -371,45 +389,209 @@ public final void testContrastColor() {
|
371 | 389 | }
|
372 | 390 | }
|
373 | 391 |
|
| 392 | + /** |
| 393 | + * Tests the {@link Coloring#colorBitmap(Bitmap, int)} method. |
| 394 | + * <p> |
| 395 | + * Due to {@link org.robolectric.shadows.ShadowBitmap}'s empty implementation, this won't really work, so we can only test the transparency. |
| 396 | + */ |
| 397 | + @Test |
| 398 | + public final void testColorBitmap() { |
| 399 | + final Bitmap.Config config = Bitmap.Config.ARGB_8888; |
| 400 | + final int width = 10, height = 10; |
| 401 | + final int[] allReds = new int[width * height]; |
| 402 | + for (int i = 0; i < width * height; i++) { |
| 403 | + allReds[i] = Color.RED; |
| 404 | + } |
| 405 | + |
| 406 | + final Bitmap redSquare = Bitmap.createBitmap(allReds, width, height, config); |
| 407 | + |
| 408 | + // initialize red Bitmap's internal structures, otherwise it won't draw properly |
| 409 | + redSquare.prepareToDraw(); |
| 410 | + final byte[] redPixels = new byte[redSquare.getWidth() * redSquare.getHeight() * 8]; |
| 411 | + final ByteBuffer redBuffer = ByteBuffer.wrap(redPixels); |
| 412 | + redBuffer.order(ByteOrder.nativeOrder()); |
| 413 | + redSquare.copyPixelsToBuffer(redBuffer); |
| 414 | + redSquare.copyPixelsFromBuffer(redBuffer); |
| 415 | + redSquare.prepareToDraw(); |
| 416 | + |
| 417 | + final String redPixel = hex(redSquare.getPixel(width / 2, height / 2)); |
| 418 | + final String errorRed = String.format("Error while creating red bitmap, middle pixel is %s", redPixel); |
| 419 | + assertEquals(errorRed, hex(Color.TRANSPARENT), redPixel); |
| 420 | + |
| 421 | + final Bitmap greenSquare = Coloring.colorBitmap(redSquare, Color.GREEN); |
| 422 | + final String greenPixel = hex(greenSquare.getPixel(width / 2, height / 2)); |
| 423 | + final String errorGreen = String.format("Error while coloring bitmap, middle pixel is %s", greenPixel); |
| 424 | + assertEquals(errorGreen, hex(Color.TRANSPARENT), greenPixel); |
| 425 | + } |
| 426 | + |
| 427 | + /** |
| 428 | + * Tests the {@link Coloring#createColoredDrawable(int, Rect)} method. |
| 429 | + */ |
| 430 | + @Test |
| 431 | + @TargetApi(Build.VERSION_CODES.HONEYCOMB) |
| 432 | + public final void testCreateColoredDrawable() { |
| 433 | + final Drawable transparentNoBounds = Coloring.createColoredDrawable(Color.TRANSPARENT, null); |
| 434 | + assertTrue("Drawable not a ColorDrawable", transparentNoBounds instanceof ColorDrawable); |
| 435 | + assertEquals("Drawable color is not transparent", Color.TRANSPARENT, ((ColorDrawable) transparentNoBounds).getColor()); |
| 436 | + assertEquals("Bounds are not 0", new Rect(0, 0, 0, 0), transparentNoBounds.getBounds()); |
| 437 | + // noinspection RedundantCast - it's not. alpha getter was added for Drawable in KITKAT |
| 438 | + assertEquals("Alpha is not 0", 0, ((ColorDrawable) transparentNoBounds).getAlpha()); |
| 439 | + |
| 440 | + final Drawable transparentWithBounds = Coloring.createColoredDrawable(Color.TRANSPARENT, new Rect(0, 0, 100, 100)); |
| 441 | + assertTrue("Drawable not a ColorDrawable", transparentWithBounds instanceof ColorDrawable); |
| 442 | + assertEquals("Drawable color is not transparent", Color.TRANSPARENT, ((ColorDrawable) transparentWithBounds).getColor()); |
| 443 | + assertEquals("Bounds are not null", new Rect(0, 0, 100, 100), transparentWithBounds.getBounds()); |
| 444 | + // noinspection RedundantCast - it's not. alpha getter was added for Drawable in KITKAT |
| 445 | + assertEquals("Alpha is not 0", 0, ((ColorDrawable) transparentWithBounds).getAlpha()); |
| 446 | + |
| 447 | + final Drawable redNoBounds = Coloring.createColoredDrawable(Color.RED, null); |
| 448 | + assertTrue("Drawable not a ColorDrawable", redNoBounds instanceof ColorDrawable); |
| 449 | + assertEquals("Drawable color is not red", hex(((ColorDrawable) redNoBounds).getColor()), hex(Color.RED)); |
| 450 | + assertEquals("Bounds are not null", new Rect(0, 0, 0, 0), redNoBounds.getBounds()); |
| 451 | + // noinspection RedundantCast - it's not. alpha getter was added for Drawable in KITKAT |
| 452 | + assertEquals("Alpha is not 255", 255, ((ColorDrawable) redNoBounds).getAlpha()); |
| 453 | + |
| 454 | + final Drawable redWithBounds = Coloring.createColoredDrawable(Color.RED, new Rect(0, 0, 100, 100)); |
| 455 | + assertTrue("Drawable not a ColorDrawable", redWithBounds instanceof ColorDrawable); |
| 456 | + assertEquals("Drawable color is not red", hex(((ColorDrawable) redWithBounds).getColor()), hex(Color.RED)); |
| 457 | + assertEquals("Bounds are not null", new Rect(0, 0, 100, 100), redWithBounds.getBounds()); |
| 458 | + // noinspection RedundantCast - it's not. alpha getter was added for Drawable in KITKAT |
| 459 | + assertEquals("Alpha is not 255", 255, ((ColorDrawable) redWithBounds).getAlpha()); |
| 460 | + } |
| 461 | + |
| 462 | + /** |
| 463 | + * Tests the {@link Coloring#colorDrawable(Context, int, int)} method. |
| 464 | + * <p> |
| 465 | + * Due to {@link org.robolectric.shadows.ShadowBitmap}'s empty implementation, this won't really work, so we can only test the transparency. |
| 466 | + */ |
| 467 | + @Test |
| 468 | + public final void testColorDrawableInt() { |
| 469 | + // noinspection deprecation - can't enforce Lollipop here |
| 470 | + final BitmapDrawable colored = (BitmapDrawable) Coloring.colorDrawable(mActivityContext, android.R.drawable.btn_star_big_on, Color.RED); |
| 471 | + final int coloredPixel = colored.getBitmap().getPixel(colored.getBitmap().getWidth() / 2, colored.getBitmap().getHeight() / 2); |
| 472 | + assertEquals("Colored middle pixel is not transparent", hex(Color.TRANSPARENT), hex(coloredPixel)); |
| 473 | + } |
| 474 | + |
| 475 | + /** |
| 476 | + * Tests the {@link Coloring#colorDrawable(Context, Drawable, int)} method. |
| 477 | + * <p> |
| 478 | + * Due to {@link org.robolectric.shadows.ShadowBitmap}'s empty implementation, this won't really work, so we can only test the transparency. |
| 479 | + */ |
| 480 | + @Test |
| 481 | + public final void testColorDrawableObject() { |
| 482 | + // noinspection deprecation - can't enforce Lollipop here |
| 483 | + final BitmapDrawable original = (BitmapDrawable) mActivityContext.getResources().getDrawable(android.R.drawable.btn_star_big_on); |
| 484 | + final int originalPixel = original.getBitmap().getPixel(original.getBitmap().getWidth() / 2, original.getBitmap().getHeight() / 2); |
| 485 | + assertEquals("Original middle pixel is not transparent", hex(Color.TRANSPARENT), hex(originalPixel)); |
| 486 | + |
| 487 | + final BitmapDrawable colored = (BitmapDrawable) Coloring.colorDrawable(mActivityContext, original, Color.RED); |
| 488 | + final int coloredPixel = colored.getBitmap().getPixel(colored.getBitmap().getWidth() / 2, colored.getBitmap().getHeight() / 2); |
| 489 | + assertEquals("Colored middle pixel is not transparent", hex(Color.TRANSPARENT), hex(coloredPixel)); |
| 490 | + } |
| 491 | + |
| 492 | + /** |
| 493 | + * Tests the {@link Coloring#colorDrawableWrapped(Drawable, int)} method. |
| 494 | + * <p> |
| 495 | + * Due to {@link org.robolectric.shadows.ShadowBitmap}'s empty implementation, this won't really work, so we can only test the transparency. |
| 496 | + */ |
| 497 | + @Test |
| 498 | + public final void testColorDrawableWrappedInt() { |
| 499 | + // noinspection deprecation - can't enforce Lollipop here |
| 500 | + final BitmapDrawable original = (BitmapDrawable) mActivityContext.getResources().getDrawable(android.R.drawable.btn_star_big_on); |
| 501 | + final int originalPixel = original.getBitmap().getPixel(original.getBitmap().getWidth() / 2, original.getBitmap().getHeight() / 2); |
| 502 | + assertEquals("Original middle pixel is not transparent", hex(Color.TRANSPARENT), hex(originalPixel)); |
| 503 | + |
| 504 | + final BitmapDrawable colored = (BitmapDrawable) Coloring.colorDrawableWrapped(original, Color.RED); |
| 505 | + final int coloredPixel = colored.getBitmap().getPixel(colored.getBitmap().getWidth() / 2, colored.getBitmap().getHeight() / 2); |
| 506 | + assertEquals("Colored middle pixel is not transparent", hex(Color.TRANSPARENT), hex(coloredPixel)); |
| 507 | + } |
| 508 | + |
| 509 | + /** |
| 510 | + * Tests the {@link Coloring#colorDrawableWrapped(Drawable, ColorStateList)} method. |
| 511 | + * <p> |
| 512 | + * Due to {@link org.robolectric.shadows.ShadowBitmap}'s empty implementation, this won't really work, so we can only test the transparency. |
| 513 | + */ |
| 514 | + @Test |
| 515 | + public final void testColorDrawableWrappedObject() { |
| 516 | + // noinspection deprecation - can't enforce Lollipop here |
| 517 | + final BitmapDrawable original = (BitmapDrawable) mActivityContext.getResources().getDrawable(android.R.drawable.btn_star_big_on); |
| 518 | + final int originalPixel = original.getBitmap().getPixel(original.getBitmap().getWidth() / 2, original.getBitmap().getHeight() / 2); |
| 519 | + assertEquals("Original middle pixel is not transparent", hex(Color.TRANSPARENT), hex(originalPixel)); |
| 520 | + |
| 521 | + final BitmapDrawable colored = (BitmapDrawable) Coloring.colorDrawableWrapped(original, ColorStateList.valueOf(Color.RED)); |
| 522 | + final int coloredPixel = colored.getBitmap().getPixel(colored.getBitmap().getWidth() / 2, colored.getBitmap().getHeight() / 2); |
| 523 | + assertEquals("Colored middle pixel is not transparent", hex(Color.TRANSPARENT), hex(coloredPixel)); |
| 524 | + } |
| 525 | + |
| 526 | + /** |
| 527 | + * Tests the {@link Coloring#colorUnknownDrawable(Drawable, int)} method. |
| 528 | + * <p> |
| 529 | + * Due to {@link org.robolectric.shadows.ShadowBitmap}'s empty implementation, this won't really work, so we can only test the transparency. |
| 530 | + */ |
| 531 | + @Test |
| 532 | + public final void testColorUnknownDrawable() { |
| 533 | + // noinspection deprecation - can't enforce Lollipop here |
| 534 | + final BitmapDrawable original = (BitmapDrawable) mActivityContext.getResources().getDrawable(android.R.drawable.btn_star_big_on); |
| 535 | + final int originalPixel = original.getBitmap().getPixel(original.getBitmap().getWidth() / 2, original.getBitmap().getHeight() / 2); |
| 536 | + assertEquals("Original middle pixel is not transparent", hex(Color.TRANSPARENT), hex(originalPixel)); |
| 537 | + |
| 538 | + final BitmapDrawable colored = (BitmapDrawable) Coloring.colorUnknownDrawable(original, Color.RED); |
| 539 | + final int coloredPixel = colored.getBitmap().getPixel(colored.getBitmap().getWidth() / 2, colored.getBitmap().getHeight() / 2); |
| 540 | + assertEquals("Colored middle pixel is not transparent", hex(Color.TRANSPARENT), hex(coloredPixel)); |
| 541 | + } |
| 542 | + |
| 543 | + /** |
| 544 | + * Tests the {@link Coloring#colorVectorDrawable(VectorDrawable, int)} method. |
| 545 | + * <p> |
| 546 | + * Unfortunately {@link VectorDrawable#setColorFilter(int, PorterDuff.Mode)} is not mocked in Android JAR yet. |
| 547 | + */ |
| 548 | + @Test |
| 549 | + @TargetApi(Build.VERSION_CODES.LOLLIPOP) |
| 550 | + public final void testColorVectorDrawable() { |
| 551 | + try { |
| 552 | + final VectorDrawable vectorDrawable = new VectorDrawable(); |
| 553 | + final VectorDrawable colored = (VectorDrawable) Coloring.colorVectorDrawable(vectorDrawable, Color.RED); |
| 554 | + final PorterDuff.Mode mode = PorterDuff.Mode.SRC_ATOP; |
| 555 | + assertEquals("Vector color filter does not match", new PorterDuffColorFilter(Color.RED, mode), colored.getColorFilter()); |
| 556 | + } catch (RuntimeException e) { |
| 557 | + boolean knownIssue = e.getMessage().contains("not mocked"); |
| 558 | + if (!knownIssue) { |
| 559 | + e.printStackTrace(); |
| 560 | + } |
| 561 | + assertTrue("Unknown error: " + e.getMessage(), knownIssue); |
| 562 | + } |
| 563 | + } |
| 564 | + |
| 565 | + /** |
| 566 | + * Tests the {@link Coloring#colorVectorDrawable(VectorDrawableCompat, int)} method. |
| 567 | + * <p> |
| 568 | + * Unfortunately {@link VectorDrawableCompat#setColorFilter(int, PorterDuff.Mode)} is not shadowed by Robolectric yet. |
| 569 | + */ |
| 570 | + @Test |
| 571 | + @TargetApi(Build.VERSION_CODES.LOLLIPOP) |
| 572 | + public final void testColorVectorDrawableCompat() { |
| 573 | + try { |
| 574 | + // not accessible outside of |
| 575 | + Class<?> cl = Class.forName(VectorDrawableCompat.class.getCanonicalName()); |
| 576 | + Constructor<?> constructor = cl.getConstructor(); |
| 577 | + constructor.setAccessible(true); |
| 578 | + final VectorDrawableCompat vectorDrawable = (VectorDrawableCompat) constructor.newInstance(); |
| 579 | + final VectorDrawableCompat colored = (VectorDrawableCompat) Coloring.colorVectorDrawable(vectorDrawable, Color.RED); |
| 580 | + final PorterDuff.Mode mode = PorterDuff.Mode.SRC_ATOP; |
| 581 | + assertEquals("VectorCompat color filter does not match", null, colored.getColorFilter()); |
| 582 | + } catch (RuntimeException e) { |
| 583 | + boolean knownIssue = e.getMessage().contains("no such method"); |
| 584 | + if (!knownIssue) { |
| 585 | + e.printStackTrace(); |
| 586 | + } |
| 587 | + assertTrue("Unknown error: " + e.getMessage(), knownIssue); |
| 588 | + } catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) { |
| 589 | + e.printStackTrace(); |
| 590 | + } |
| 591 | + } |
| 592 | + |
374 | 593 | // FIXME Untested:
|
375 | 594 | //
|
376 |
| - // |
377 |
| - // public final void testColorBitmap() { |
378 |
| - // |
379 |
| - // } |
380 |
| - // |
381 |
| - // public final void testCreateColoredDrawable() { |
382 |
| - // |
383 |
| - // } |
384 |
| - // |
385 |
| - // public final void testColorDrawable() { |
386 |
| - // |
387 |
| - // } |
388 |
| - // |
389 |
| - // public final void testColorDrawable1() { |
390 |
| - // |
391 |
| - // } |
392 |
| - // |
393 |
| - // public final void testColorDrawableWrapped() { |
394 |
| - // |
395 |
| - // } |
396 |
| - // |
397 |
| - // public final void testColorDrawableWrapped1() { |
398 |
| - // |
399 |
| - // } |
400 |
| - // |
401 |
| - // public final void testColorUnknownDrawable() { |
402 |
| - // |
403 |
| - // } |
404 |
| - // |
405 |
| - // public final void testColorVectorDrawable() { |
406 |
| - // |
407 |
| - // } |
408 |
| - // |
409 |
| - // public final void testColorVectorDrawable1() { |
410 |
| - // |
411 |
| - // } |
412 |
| - // |
413 | 595 | // public final void testCreateStateList() {
|
414 | 596 | //
|
415 | 597 | // }
|
|
0 commit comments