diff --git a/screenshots/gplay/debug/com.nextcloud.client.FileDisplayActivityScreenshotIT_drawer.png b/screenshots/gplay/debug/com.nextcloud.client.FileDisplayActivityScreenshotIT_drawer.png
index a20e7280b4..be47302cb0 100644
Binary files a/screenshots/gplay/debug/com.nextcloud.client.FileDisplayActivityScreenshotIT_drawer.png and b/screenshots/gplay/debug/com.nextcloud.client.FileDisplayActivityScreenshotIT_drawer.png differ
diff --git a/screenshots/gplay/debug/com.nextcloud.client.FileDisplayActivityScreenshotIT_open.png b/screenshots/gplay/debug/com.nextcloud.client.FileDisplayActivityScreenshotIT_open.png
index a7896adb5c..78f13a1e93 100644
Binary files a/screenshots/gplay/debug/com.nextcloud.client.FileDisplayActivityScreenshotIT_open.png and b/screenshots/gplay/debug/com.nextcloud.client.FileDisplayActivityScreenshotIT_open.png differ
diff --git a/screenshots/gplay/debug/com.owncloud.android.ui.activity.ManageAccountsActivityIT_open.png b/screenshots/gplay/debug/com.owncloud.android.ui.activity.ManageAccountsActivityIT_open.png
index 793fc3768b..bab3c63e9e 100644
Binary files a/screenshots/gplay/debug/com.owncloud.android.ui.activity.ManageAccountsActivityIT_open.png and b/screenshots/gplay/debug/com.owncloud.android.ui.activity.ManageAccountsActivityIT_open.png differ
diff --git a/screenshots/gplay/debug/com.owncloud.android.ui.dialog.DialogFragmentIT_testAccountChooserDialog.png b/screenshots/gplay/debug/com.owncloud.android.ui.dialog.DialogFragmentIT_testAccountChooserDialog.png
index 69d4abdb45..5f0ec53953 100644
Binary files a/screenshots/gplay/debug/com.owncloud.android.ui.dialog.DialogFragmentIT_testAccountChooserDialog.png and b/screenshots/gplay/debug/com.owncloud.android.ui.dialog.DialogFragmentIT_testAccountChooserDialog.png differ
diff --git a/scripts/analysis/findbugs-results.txt b/scripts/analysis/findbugs-results.txt
index 9573848579..18eed1357e 100644
--- a/scripts/analysis/findbugs-results.txt
+++ b/scripts/analysis/findbugs-results.txt
@@ -1 +1 @@
-326
\ No newline at end of file
+320
diff --git a/src/androidTest/java/com/owncloud/android/utils/BitmapUtilsIT.kt b/src/androidTest/java/com/owncloud/android/utils/BitmapUtilsIT.kt
new file mode 100644
index 0000000000..abe4c722e6
--- /dev/null
+++ b/src/androidTest/java/com/owncloud/android/utils/BitmapUtilsIT.kt
@@ -0,0 +1,79 @@
+/*
+ *
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2020 Tobias Kaminsky
+ * Copyright (C) 2020 Nextcloud GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+package com.owncloud.android.utils
+
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotEquals
+import org.junit.Test
+
+class BitmapUtilsIT {
+ @Test
+ @Suppress("MagicNumber")
+ fun usernameToColor() {
+ assertEquals(BitmapUtils.Color(0, 0, 0), BitmapUtils.Color(0, 0, 0))
+ assertEquals(BitmapUtils.Color(221, 203, 85), BitmapUtils.usernameToColor("User"))
+ assertEquals(BitmapUtils.Color(208, 158, 109), BitmapUtils.usernameToColor("Admin"))
+ assertEquals(BitmapUtils.Color(0, 130, 201), BitmapUtils.usernameToColor(""))
+ assertEquals(BitmapUtils.Color(201, 136, 121), BitmapUtils.usernameToColor("68b329da9893e34099c7d8ad5cb9c940"))
+
+ // tests from server
+ assertEquals(BitmapUtils.Color(208, 158, 109), BitmapUtils.usernameToColor("Alishia Ann Lowry"))
+ assertEquals(BitmapUtils.Color(0, 130, 201), BitmapUtils.usernameToColor("Arham Johnson"))
+ assertEquals(BitmapUtils.Color(208, 158, 109), BitmapUtils.usernameToColor("Brayden Truong"))
+ assertEquals(BitmapUtils.Color(151, 80, 164), BitmapUtils.usernameToColor("Daphne Roy"))
+ assertEquals(BitmapUtils.Color(195, 114, 133), BitmapUtils.usernameToColor("Ellena Wright Frederic Conway"))
+ assertEquals(BitmapUtils.Color(214, 180, 97), BitmapUtils.usernameToColor("Gianluca Hills"))
+ assertEquals(BitmapUtils.Color(214, 180, 97), BitmapUtils.usernameToColor("Haseeb Stephens"))
+ assertEquals(BitmapUtils.Color(151, 80, 164), BitmapUtils.usernameToColor("Idris Mac"))
+ assertEquals(BitmapUtils.Color(0, 130, 201), BitmapUtils.usernameToColor("Kristi Fisher"))
+ assertEquals(BitmapUtils.Color(188, 92, 145), BitmapUtils.usernameToColor("Lillian Wall"))
+ assertEquals(BitmapUtils.Color(221, 203, 85), BitmapUtils.usernameToColor("Lorelai Taylor"))
+ assertEquals(BitmapUtils.Color(151, 80, 164), BitmapUtils.usernameToColor("Madina Knight"))
+ assertEquals(BitmapUtils.Color(121, 90, 171), BitmapUtils.usernameToColor("Rae Hope"))
+ assertEquals(BitmapUtils.Color(188, 92, 145), BitmapUtils.usernameToColor("Santiago Singleton"))
+ assertEquals(BitmapUtils.Color(208, 158, 109), BitmapUtils.usernameToColor("Sid Combs"))
+ assertEquals(BitmapUtils.Color(30, 120, 193), BitmapUtils.usernameToColor("Vivienne Jacobs"))
+ assertEquals(BitmapUtils.Color(110, 166, 143), BitmapUtils.usernameToColor("Zaki Cortes"))
+ assertEquals(BitmapUtils.Color(91, 100, 179), BitmapUtils.usernameToColor("a user"))
+ assertEquals(BitmapUtils.Color(208, 158, 109), BitmapUtils.usernameToColor("admin"))
+ assertEquals(BitmapUtils.Color(151, 80, 164), BitmapUtils.usernameToColor("admin@cloud.example.com"))
+ assertEquals(BitmapUtils.Color(221, 203, 85), BitmapUtils.usernameToColor("another user"))
+ assertEquals(BitmapUtils.Color(36, 142, 181), BitmapUtils.usernameToColor("asd"))
+ assertEquals(BitmapUtils.Color(0, 130, 201), BitmapUtils.usernameToColor("bar"))
+ assertEquals(BitmapUtils.Color(208, 158, 109), BitmapUtils.usernameToColor("foo"))
+ assertEquals(BitmapUtils.Color(182, 70, 157), BitmapUtils.usernameToColor("wasd"))
+ }
+
+ @Test
+ @Suppress("MagicNumber")
+ fun checkEqual() {
+ assertEquals(BitmapUtils.Color(208, 158, 109), BitmapUtils.Color(208, 158, 109))
+ assertNotEquals(BitmapUtils.Color(208, 158, 109), BitmapUtils.Color(208, 158, 100))
+ }
+
+ @Test
+ @Suppress("MagicNumber")
+ fun checkHashCode() {
+ assertEquals(BitmapUtils.Color(208, 158, 109).hashCode(), BitmapUtils.Color(208, 158, 109).hashCode())
+ assertNotEquals(BitmapUtils.Color(208, 158, 109).hashCode(), BitmapUtils.Color(208, 158, 100).hashCode())
+ }
+}
diff --git a/src/main/java/com/nextcloud/client/account/UserAccountManager.java b/src/main/java/com/nextcloud/client/account/UserAccountManager.java
index 5d864f0a66..8eca155bf4 100644
--- a/src/main/java/com/nextcloud/client/account/UserAccountManager.java
+++ b/src/main/java/com/nextcloud/client/account/UserAccountManager.java
@@ -20,12 +20,15 @@
package com.nextcloud.client.account;
import android.accounts.Account;
+import android.accounts.AccountManager;
import android.app.Activity;
import android.content.Intent;
import com.nextcloud.java.util.Optional;
+import com.owncloud.android.MainApp;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.lib.common.OwnCloudAccount;
+import com.owncloud.android.lib.common.accounts.AccountUtils;
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
import java.util.List;
@@ -154,13 +157,14 @@ public interface UserAccountManager extends CurrentAccountProvider {
/**
* Extract username from account.
- *
+ *
* Full account name is in form of "username@nextcloud.domain".
*
* @param account Account instance
* @return User name (without domain) or null, if name cannot be extracted.
*/
- static String getUsername(Account account) {
+ static @Nullable
+ String getUsername(Account account) {
if (account != null && account.name != null) {
return account.name.substring(0, account.name.lastIndexOf('@'));
} else {
@@ -168,9 +172,15 @@ public interface UserAccountManager extends CurrentAccountProvider {
}
}
+ static @Nullable
+ String getDisplayName(Account account) {
+ return AccountManager.get(MainApp.getAppContext()).getUserData(account,
+ AccountUtils.Constants.KEY_DISPLAY_NAME);
+ }
+
/**
* Launch account registration activity.
- *
+ *
* This method returns immediately. Authenticator activity will be launched asynchronously.
*
* @param activity Activity used to launch authenticator flow via {@link Activity#startActivity(Intent)}
diff --git a/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java b/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java
index 02641a98ba..6b527d2a78 100644
--- a/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java
+++ b/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java
@@ -1136,13 +1136,10 @@ public final class ThumbnailsCacheManager {
}
public static class AsyncMediaThumbnailDrawable extends BitmapDrawable {
- private final WeakReference bitmapWorkerTaskReference;
- public AsyncMediaThumbnailDrawable(Resources res, Bitmap bitmap,
- MediaThumbnailGenerationTask bitmapWorkerTask) {
+ public AsyncMediaThumbnailDrawable(Resources res, Bitmap bitmap) {
super(res, bitmap);
- bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask);
}
}
diff --git a/src/main/java/com/owncloud/android/ui/TextDrawable.java b/src/main/java/com/owncloud/android/ui/TextDrawable.java
index 3e5f45e715..f2106f1b5f 100644
--- a/src/main/java/com/owncloud/android/ui/TextDrawable.java
+++ b/src/main/java/com/owncloud/android/ui/TextDrawable.java
@@ -69,19 +69,17 @@ public class TextDrawable extends Drawable {
* Create a TextDrawable with the given radius.
*
* @param text the text to be rendered
- * @param r rgb red value
- * @param g rgb green value
- * @param b rgb blue value
+ * @param color color
* @param radius circle radius
*/
- public TextDrawable(String text, int r, int g, int b, float radius) {
+ public TextDrawable(String text, BitmapUtils.Color color, float radius) {
mRadius = radius;
mText = text;
mBackground = new Paint();
mBackground.setStyle(Paint.Style.FILL);
mBackground.setAntiAlias(true);
- mBackground.setColor(Color.rgb(r, g, b));
+ mBackground.setColor(Color.rgb(color.r, color.g, color.b));
mTextPaint = new Paint();
mTextPaint.setColor(Color.WHITE);
@@ -101,8 +99,9 @@ public class TextDrawable extends Drawable {
*/
@NonNull
@NextcloudServer(max = 12)
- public static TextDrawable createAvatar(Account account, float radiusInDp) throws NoSuchAlgorithmException {
- String username = UserAccountManager.getUsername(account);
+ public static TextDrawable createAvatar(Account account, float radiusInDp) throws
+ NoSuchAlgorithmException {
+ String username = UserAccountManager.getDisplayName(account);
return createNamedAvatar(username, radiusInDp);
}
@@ -132,11 +131,8 @@ public class TextDrawable extends Drawable {
*/
@NonNull
public static TextDrawable createNamedAvatar(String name, float radiusInDp) throws NoSuchAlgorithmException {
- int[] hsl = BitmapUtils.calculateHSL(name);
- int[] rgb = BitmapUtils.HSLtoRGB(hsl[0], hsl[1], hsl[2], 1);
-
- return new TextDrawable(extractCharsFromDisplayName(name), rgb[0], rgb[1], rgb[2],
- radiusInDp);
+ BitmapUtils.Color color = BitmapUtils.usernameToColor(name);
+ return new TextDrawable(extractCharsFromDisplayName(name), color, radiusInDp);
}
@VisibleForTesting
diff --git a/src/main/java/com/owncloud/android/ui/adapter/SyncedFolderAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/SyncedFolderAdapter.java
index 7720eb7f11..89bbff62d2 100644
--- a/src/main/java/com/owncloud/android/ui/adapter/SyncedFolderAdapter.java
+++ b/src/main/java/com/owncloud/android/ui/adapter/SyncedFolderAdapter.java
@@ -337,8 +337,7 @@ public class SyncedFolderAdapter extends SectionedRecyclerViewAdapter private constructor
}
/**
- * Decodes a bitmap from a file containing it minimizing the memory use, known that the bitmap
- * will be drawn in a surface of reqWidth x reqHeight
+ * Decodes a bitmap from a file containing it minimizing the memory use, known that the bitmap will be drawn in a
+ * surface of reqWidth x reqHeight
*
- * @param srcPath Absolute path to the file containing the image.
- * @param reqWidth Width of the surface where the Bitmap will be drawn on, in pixels.
- * @param reqHeight Height of the surface where the Bitmap will be drawn on, in pixels.
+ * @param srcPath Absolute path to the file containing the image.
+ * @param reqWidth Width of the surface where the Bitmap will be drawn on, in pixels.
+ * @param reqHeight Height of the surface where the Bitmap will be drawn on, in pixels.
* @return decoded bitmap
*/
public static Bitmap decodeSampledBitmapFromFile(String srcPath, int reqWidth, int reqHeight) {
@@ -93,16 +88,14 @@ public final class BitmapUtils {
/**
- * Calculates a proper value for options.inSampleSize in order to decode a Bitmap minimizing
- * the memory overload and covering a target surface of reqWidth x reqHeight if the original
- * image is big enough.
+ * Calculates a proper value for options.inSampleSize in order to decode a Bitmap minimizing the memory overload and
+ * covering a target surface of reqWidth x reqHeight if the original image is big enough.
*
- * @param options Bitmap decoding options; options.outHeight and options.inHeight should
- * be set.
- * @param reqWidth Width of the surface where the Bitmap will be drawn on, in pixels.
- * @param reqHeight Height of the surface where the Bitmap will be drawn on, in pixels.
- * @return The largest inSampleSize value that is a power of 2 and keeps both
- * height and width larger than reqWidth and reqHeight.
+ * @param options Bitmap decoding options; options.outHeight and options.inHeight should be set.
+ * @param reqWidth Width of the surface where the Bitmap will be drawn on, in pixels.
+ * @param reqHeight Height of the surface where the Bitmap will be drawn on, in pixels.
+ * @return The largest inSampleSize value that is a power of 2 and keeps both height and width larger than reqWidth
+ * and reqHeight.
*/
public static int calculateSampleFactor(Options options, int reqWidth, int reqHeight) {
@@ -142,9 +135,9 @@ public final class BitmapUtils {
}
/**
- * Rotate bitmap according to EXIF orientation.
- * Cf. http://www.daveperrett.com/articles/2012/07/28/exif-orientation-handling-is-a-ghetto/
- * @param bitmap Bitmap to be rotated
+ * Rotate bitmap according to EXIF orientation. Cf. http://www.daveperrett.com/articles/2012/07/28/exif-orientation-handling-is-a-ghetto/
+ *
+ * @param bitmap Bitmap to be rotated
* @param storagePath Path to source file of bitmap. Needed for EXIF information.
* @return correctly EXIF-rotated bitmap
*/
@@ -201,167 +194,115 @@ public final class BitmapUtils {
return resultBitmap;
}
- /**
- * Convert HSL values to a RGB Color.
- *
- * @param h Hue is specified as degrees in the range 0 - 360.
- * @param s Saturation is specified as a percentage in the range 1 - 100.
- * @param l Luminance is specified as a percentage in the range 1 - 100.
- * @param alpha the alpha value between 0 - 1
- * adapted from https://svn.codehaus.org/griffon/builders/gfxbuilder/tags/GFXBUILDER_0.2/
- * gfxbuilder-core/src/main/com/camick/awt/HSLColor.java
- */
- @SuppressWarnings("PMD.MethodNamingConventions")
- public static int[] HSLtoRGB(float h, float s, float l, float alpha) {
- if (s < 0.0f || s > 100.0f) {
- String message = "Color parameter outside of expected range - Saturation";
- throw new IllegalArgumentException(message);
- }
+ public static Color usernameToColor(String name) throws NoSuchAlgorithmException {
+ String hash = name.toLowerCase(Locale.ROOT);
- if (l < 0.0f || l > 100.0f) {
- String message = "Color parameter outside of expected range - Luminance";
- throw new IllegalArgumentException(message);
- }
-
- if (alpha < 0.0f || alpha > 1.0f) {
- String message = "Color parameter outside of expected range - Alpha";
- throw new IllegalArgumentException(message);
- }
-
- // Formula needs all values between 0 - 1.
-
- h = h % 360.0f;
- h /= 360f;
- s /= 100f;
- l /= 100f;
-
- float q;
-
- if (l < 0.5) {
- q = l * (1 + s);
- } else {
- q = (l + s) - (s * l);
- }
-
- float p = 2 * l - q;
-
- int r = Math.round(Math.max(0, HueToRGB(p, q, h + (1.0f / 3.0f)) * 256));
- int g = Math.round(Math.max(0, HueToRGB(p, q, h) * 256));
- int b = Math.round(Math.max(0, HueToRGB(p, q, h - (1.0f / 3.0f)) * 256));
-
- return new int[]{r, g, b};
- }
-
- @SuppressWarnings("PMD.MethodNamingConventions")
- private static float HueToRGB(float p, float q, float h) {
- if (h < 0) {
- h += 1;
- }
-
- if (h > 1) {
- h -= 1;
- }
-
- if (6 * h < 1) {
- return p + ((q - p) * 6 * h);
- }
-
- if (2 * h < 1) {
- return q;
- }
-
- if (3 * h < 2) {
- return p + ((q - p) * 6 * (2.0f / 3.0f - h));
- }
-
- return p;
- }
-
- /**
- * calculates the RGB value based on a given account name.
- *
- * @param name The name
- * @return corresponding RGB color
- * @throws NoSuchAlgorithmException if the specified algorithm is not available
- */
- public static int[] calculateHSL(String name) throws NoSuchAlgorithmException {
- // using adapted algorithm from https://github.com/nextcloud/server/blob/master/core/js/placeholder.js#L126
-
- String[] result = new String[]{"0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"};
- double[] rgb = new double[]{0, 0, 0};
- int sat = 70;
- int lum = 68;
- int modulo = 16;
-
- String hash = name.toLowerCase(Locale.ROOT).replaceAll("[^0-9a-f]", "");
-
- if (!hash.matches("^[0-9a-f]{32}")) {
+ // already a md5 hash?
+ if (!hash.matches("([0-9a-f]{4}-?){8}$")) {
hash = md5(hash);
}
- // Splitting evenly the string
- for (int i = 0; i < hash.length(); i++) {
- result[i % modulo] = result[i % modulo] + Integer.parseInt(hash.substring(i, i + 1), 16);
- }
+ hash = hash.replaceAll("[^0-9a-f]", "");
+ int steps = 6;
- // Converting our data into a usable rgb format
- // Start at 1 because 16%3=1 but 15%3=0 and makes the repartition even
- for (int count = 1; count < modulo; count++) {
- rgb[count % 3] += Integer.parseInt(result[count]);
- }
+ Color[] finalPalette = generateColors(steps);
- // Reduce values bigger than rgb requirements
- rgb[INDEX_RED] = rgb[INDEX_RED] % 255;
- rgb[INDEX_GREEN] = rgb[INDEX_GREEN] % 255;
- rgb[INDEX_BLUE] = rgb[INDEX_BLUE] % 255;
-
- double[] hsl = rgbToHsl(rgb[INDEX_RED], rgb[INDEX_GREEN], rgb[INDEX_BLUE]);
-
- // Classic formula to check the brightness for our eye
- // If too bright, lower the sat
- double bright = Math.sqrt(0.299 * Math.pow(rgb[INDEX_RED], 2) + 0.587 * Math.pow(rgb[INDEX_GREEN], 2) + 0.114
- * Math.pow(rgb[INDEX_BLUE], 2));
-
- if (bright >= 200) {
- sat = 60;
- }
-
- return new int[]{(int) (hsl[INDEX_HUE] * 360), sat, lum};
+ return finalPalette[hashToInt(hash, steps * 3)];
}
- private static double[] rgbToHsl(double rUntrimmed, double gUntrimmed, double bUntrimmed) {
- double r = rUntrimmed / 255;
- double g = gUntrimmed / 255;
- double b = bUntrimmed / 255;
+ private static int hashToInt(String hash, int maximum) {
+ int finalInt = 0;
+ int[] result = new int[hash.length()];
- double max = Math.max(r, Math.max(g, b));
- double min = Math.min(r, Math.min(g, b));
- double h = (max + min) / 2;
- double s;
- double l = (max + min) / 2;
-
- if (max == min) {
- h = s = 0; // achromatic
- } else {
- double d = max - min;
- s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
-
- if (max == r) {
- h = (g - b) / d + (g < b ? 6 : 0);
- } else if (max == g) {
- h = (b - r) / d + 2;
- } else if (max == b) {
- h = (r - g) / d + 4;
- }
- h /= 6;
+ // splitting evenly the string
+ for (int i = 0; i < hash.length(); i++) {
+ // chars in md5 goes up to f, hex: 16
+ result[i] = Integer.parseInt(String.valueOf(hash.charAt(i)), 16) % 16;
}
- double[] hsl = new double[]{0.0, 0.0, 0.0};
- hsl[INDEX_HUE] = h;
- hsl[INDEX_SATURATION] = s;
- hsl[INDEX_LUMINATION] = l;
+ // adds up all results
+ for (int value : result) {
+ finalInt += value;
+ }
- return hsl;
+ // chars in md5 goes up to f, hex:16
+ // make sure we're always using int in our operation
+ return Integer.parseInt(String.valueOf(Integer.parseInt(String.valueOf(finalInt), 10) % maximum), 10);
+ }
+
+ private static Color[] generateColors(int steps) {
+ Color red = new Color(182, 70, 157);
+ Color yellow = new Color(221, 203, 85);
+ Color blue = new Color(0, 130, 201); // Nextcloud blue
+
+ Color[] palette1 = mixPalette(steps, red, yellow);
+ Color[] palette2 = mixPalette(steps, yellow, blue);
+ Color[] palette3 = mixPalette(steps, blue, red);
+
+ Color[] resultPalette = new Color[palette1.length + palette2.length + palette3.length];
+ System.arraycopy(palette1, 0, resultPalette, 0, palette1.length);
+ System.arraycopy(palette2, 0, resultPalette, palette1.length, palette2.length);
+ System.arraycopy(palette3,
+ 0,
+ resultPalette,
+ palette1.length + palette2.length,
+ palette1.length);
+
+ return resultPalette;
+ }
+
+ @SuppressFBWarnings("CLI_CONSTANT_LIST_INDEX")
+ private static Color[] mixPalette(int steps, Color color1, Color color2) {
+ Color[] palette = new Color[steps];
+ palette[0] = color1;
+
+ float[] step = stepCalc(steps, color1, color2);
+ for (int i = 1; i < steps; i++) {
+ int r = (int) (color1.r + step[0] * i);
+ int g = (int) (color1.g + step[1] * i);
+ int b = (int) (color1.b + step[2] * i);
+
+ palette[i] = new Color(r, g, b);
+ }
+
+ return palette;
+ }
+
+ private static float[] stepCalc(int steps, Color color1, Color color2) {
+ float[] step = new float[3];
+
+ step[0] = (color2.r - color1.r) / (float) steps;
+ step[1] = (color2.g - color1.g) / (float) steps;
+ step[2] = (color2.b - color1.b) / (float) steps;
+
+ return step;
+ }
+
+ public static class Color {
+ public int r;
+ public int g;
+ public int b;
+
+ public Color(int r, int g, int b) {
+ this.r = r;
+ this.g = g;
+ this.b = b;
+ }
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
+ if (!(obj instanceof Color)) {
+ return false;
+ }
+
+ Color other = (Color) obj;
+ return this.r == other.r && this.g == other.g && this.b == other.b;
+ }
+
+ @Override
+ public int hashCode() {
+ return r * 10000 + g * 1000 + b;
+ }
}
public static String md5(String string) throws NoSuchAlgorithmException {
@@ -372,11 +313,11 @@ public final class BitmapUtils {
}
/**
- * Returns a new circular bitmap drawable by creating it from a bitmap, setting initial target density based on
- * the display metrics of the resources.
+ * Returns a new circular bitmap drawable by creating it from a bitmap, setting initial target density based on the
+ * display metrics of the resources.
*
* @param resources the resources for initial target density
- * @param bitmap the original bitmap
+ * @param bitmap the original bitmap
* @return the circular bitmap
*/
public static RoundedBitmapDrawable bitmapToCircularBitmapDrawable(Resources resources,
@@ -420,7 +361,7 @@ public final class BitmapUtils {
bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
} else {
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
- Bitmap.Config.ARGB_8888);
+ Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(bitmap);
@@ -436,14 +377,14 @@ public final class BitmapUtils {
imageView);
}
- public static void setRoundedBitmapForGridMode(Bitmap thumbnail, ImageView imageView){
+ public static void setRoundedBitmapForGridMode(Bitmap thumbnail, ImageView imageView) {
BitmapUtils.setRoundedBitmap(getResources(),
thumbnail,
getResources().getDimension(R.dimen.file_icon_rounded_corner_radius_for_grid_mode),
imageView);
}
- private static Resources getResources(){
+ private static Resources getResources() {
return MainApp.getAppContext().getResources();
}
}