From d645c435fd2205eb5710f946dc2ed6a4338f3da1 Mon Sep 17 00:00:00 2001
From: str4d <str4d@mail.i2p>
Date: Tue, 5 Jan 2016 03:38:26 +0000
Subject: [PATCH] Identicon generation code from Android-Identicons Source:
 https://github.com/saiimons/Android-Identicons License: Apache License,
 Version 2.0

---
 .../identicons/AsymmetricIdenticon.java       |  71 +++++++++++
 .../android/identicons/IdenticonBase.java     | 120 ++++++++++++++++++
 .../android/identicons/IdenticonDrawable.java |  85 +++++++++++++
 .../android/identicons/IdenticonView.java     | 118 +++++++++++++++++
 .../identicons/SymmetricIdenticon.java        |  81 ++++++++++++
 5 files changed, 475 insertions(+)
 create mode 100644 briar-android/src/im/delight/android/identicons/AsymmetricIdenticon.java
 create mode 100644 briar-android/src/im/delight/android/identicons/IdenticonBase.java
 create mode 100644 briar-android/src/im/delight/android/identicons/IdenticonDrawable.java
 create mode 100644 briar-android/src/im/delight/android/identicons/IdenticonView.java
 create mode 100644 briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java

diff --git a/briar-android/src/im/delight/android/identicons/AsymmetricIdenticon.java b/briar-android/src/im/delight/android/identicons/AsymmetricIdenticon.java
new file mode 100644
index 0000000000..bce32ff9e1
--- /dev/null
+++ b/briar-android/src/im/delight/android/identicons/AsymmetricIdenticon.java
@@ -0,0 +1,71 @@
+package im.delight.android.identicons;
+
+/**
+ * Copyright 2014 www.delight.im <info@delight.im>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import android.content.Context;
+import android.graphics.Color;
+import android.util.AttributeSet;
+
+public class AsymmetricIdenticon extends IdenticonView {
+
+    private IdenticonBase mDelegate;
+
+    public AsymmetricIdenticon(Context context) {
+        super(context);
+        initDelegate();
+    }
+
+    public AsymmetricIdenticon(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        initDelegate();
+    }
+
+    public AsymmetricIdenticon(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        initDelegate();
+    }
+
+    @Override
+    protected IdenticonBase getDelegate() {
+        return mDelegate;
+    }
+
+    private void initDelegate() {
+        mDelegate = new IdenticonBase() {
+            @Override
+            protected int getRowCount() {
+                return 4;
+            }
+
+            @Override
+            protected int getColumnCount() {
+                return 4;
+            }
+
+            @Override
+            protected boolean isCellVisible(int row, int column) {
+                return getByte(3 + row * getColumnCount() + column) >= 0;
+            }
+
+            @Override
+            protected int getIconColor() {
+                return Color.rgb(getByte(0) + 128, getByte(1) + 128, getByte(2) + 128);
+            }
+        };
+    }
+
+}
diff --git a/briar-android/src/im/delight/android/identicons/IdenticonBase.java b/briar-android/src/im/delight/android/identicons/IdenticonBase.java
new file mode 100644
index 0000000000..a1a5d5dd30
--- /dev/null
+++ b/briar-android/src/im/delight/android/identicons/IdenticonBase.java
@@ -0,0 +1,120 @@
+package im.delight.android.identicons;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+
+import java.security.MessageDigest;
+
+/**
+ * Created by saiimons on 05/10/14.
+ */
+public abstract class IdenticonBase {
+    private static final String HASH_ALGORITHM = "SHA-256";
+
+
+    private final int mRowCount;
+    private final int mColumnCount;
+    private final Paint mPaint;
+    private volatile int mCellWidth;
+    private volatile int mCellHeight;
+    private volatile byte[] mHash;
+    private volatile int[][] mColors;
+    private volatile boolean mReady;
+
+    public IdenticonBase() {
+        mRowCount = getRowCount();
+        mColumnCount = getColumnCount();
+        mPaint = new Paint();
+
+        mPaint.setStyle(Paint.Style.FILL);
+        mPaint.setAntiAlias(true);
+        mPaint.setDither(true);
+    }
+
+    public static byte[] getHash(String input) {
+        byte[] mHash;
+        // if the input was null
+        if (input == null) {
+            // we can't create a hash value and have nothing to show (draw to the view)
+            mHash = null;
+        }
+        // if the input was a proper string (non-null)
+        else {
+            // generate a hash from the string to get unique but deterministic byte values
+            try {
+                final MessageDigest digest = java.security.MessageDigest.getInstance(HASH_ALGORITHM);
+                digest.update(input == null ? new byte[0] : input.getBytes());
+                mHash = digest.digest();
+            } catch (Exception e) {
+                mHash = null;
+            }
+        }
+        return mHash;
+    }
+
+    protected void setupColors() {
+        mColors = new int[mRowCount][mColumnCount];
+        int colorVisible = getIconColor();
+
+        for (int r = 0; r < mRowCount; r++) {
+            for (int c = 0; c < mColumnCount; c++) {
+                if (isCellVisible(r, c)) {
+                    mColors[r][c] = colorVisible;
+                } else {
+                    mColors[r][c] = Color.TRANSPARENT;
+                }
+            }
+        }
+    }
+
+    public void show(String input) {
+        if(input != null) {
+            mHash = IdenticonBase.getHash(input);
+        } else {
+            mHash = null;
+        }
+        // set up the cell colors according to the input that was provided via show(...)
+        setupColors();
+
+        // this view may now be drawn (and thus must be re-drawn)
+        mReady = true;
+    }
+
+    public byte getByte(int index) {
+        if (mHash == null) {
+            return -128;
+        } else {
+            return mHash[index % mHash.length];
+        }
+    }
+
+    abstract protected int getRowCount();
+
+    abstract protected int getColumnCount();
+
+    abstract protected boolean isCellVisible(int row, int column);
+
+    abstract protected int getIconColor();
+
+    public void updateSize(int w, int h) {
+        mCellWidth = w / mColumnCount;
+        mCellHeight = h / mRowCount;
+    }
+
+    protected void draw(Canvas canvas) {
+        if (mReady) {
+            int x, y;
+            for (int r = 0; r < mRowCount; r++) {
+                for (int c = 0; c < mColumnCount; c++) {
+                    x = mCellWidth * c;
+                    y = mCellHeight * r;
+
+                    mPaint.setColor(mColors[r][c]);
+
+                    canvas.drawRect(x, y + mCellHeight, x + mCellWidth, y, mPaint);
+                }
+            }
+        }
+    }
+}
diff --git a/briar-android/src/im/delight/android/identicons/IdenticonDrawable.java b/briar-android/src/im/delight/android/identicons/IdenticonDrawable.java
new file mode 100644
index 0000000000..19a5094b91
--- /dev/null
+++ b/briar-android/src/im/delight/android/identicons/IdenticonDrawable.java
@@ -0,0 +1,85 @@
+package im.delight.android.identicons;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+
+/**
+ * Created by saiimons on 05/10/14.
+ */
+public class IdenticonDrawable extends Drawable {
+    private IdenticonBase mDelegate;
+
+    private static final int CENTER_COLUMN_INDEX = 3;
+
+    public IdenticonDrawable(String toShow) {
+        super();
+        mDelegate = new IdenticonBase() {
+            @Override
+            protected int getRowCount() {
+                return 5;
+            }
+
+            @Override
+            protected int getColumnCount() {
+                return 5;
+            }
+
+            @Override
+            protected boolean isCellVisible(int row, int column) {
+                return getByte(3 + row * CENTER_COLUMN_INDEX + getSymmetricColumnIndex(column)) >= 0;
+            }
+
+            @Override
+            protected int getIconColor() {
+                return Color.rgb(getByte(0) + 128, getByte(1) + 128, getByte(2) + 128);
+            }
+        };
+        mDelegate.show(toShow);
+    }
+
+    @Override
+    public void setBounds(Rect bounds) {
+        super.setBounds(bounds);
+        Log.d("IDENTICON", "SIZE : " + (bounds.right - bounds.left) + " " + (bounds.bottom - bounds.top));
+        mDelegate.updateSize(bounds.right - bounds.left, bounds.bottom - bounds.top);
+    }
+
+    @Override
+    public void setBounds(int left, int top, int right, int bottom) {
+        super.setBounds(left, top, right, bottom);
+        mDelegate.updateSize(right - left, bottom - top);
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        Log.d("IDENTICON", "DRAW IN PROGRESS");
+        mDelegate.draw(canvas);
+    }
+
+    @Override
+    public void setAlpha(int alpha) {
+
+    }
+
+    @Override
+    public void setColorFilter(ColorFilter cf) {
+
+    }
+
+    @Override
+    public int getOpacity() {
+        return 0;
+    }
+
+    protected int getSymmetricColumnIndex(int row) {
+        if (row < CENTER_COLUMN_INDEX) {
+            return row;
+        } else {
+            return mDelegate.getColumnCount() - row - 1;
+        }
+    }
+}
diff --git a/briar-android/src/im/delight/android/identicons/IdenticonView.java b/briar-android/src/im/delight/android/identicons/IdenticonView.java
new file mode 100644
index 0000000000..061ba953cb
--- /dev/null
+++ b/briar-android/src/im/delight/android/identicons/IdenticonView.java
@@ -0,0 +1,118 @@
+package im.delight.android.identicons;
+
+/**
+ * Copyright 2014 www.delight.im <info@delight.im>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.view.View;
+
+abstract public class IdenticonView extends View {
+
+
+    public IdenticonView(Context context) {
+        super(context);
+        init();
+    }
+
+    public IdenticonView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public IdenticonView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        init();
+    }
+
+    @SuppressLint("NewApi")
+    protected void init() {
+        setWillNotDraw(false);
+        if (Build.VERSION.SDK_INT >= 11) {
+            setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+        }
+    }
+
+    public void show(String input) {
+        getDelegate().show(input);
+        invalidate();
+    }
+
+    public void show(int input) {
+        show(String.valueOf(input));
+    }
+
+    public void show(long input) {
+        show(String.valueOf(input));
+    }
+
+    public void show(float input) {
+        show(String.valueOf(input));
+    }
+
+    public void show(double input) {
+        show(String.valueOf(input));
+    }
+
+    public void show(byte input) {
+        show(String.valueOf(input));
+    }
+
+    public void show(char input) {
+        show(String.valueOf(input));
+    }
+
+    public void show(boolean input) {
+        show(String.valueOf(input));
+    }
+
+    public void show(Object input) {
+        if (input == null) {
+            getDelegate().show(null);
+        } else {
+            show(String.valueOf(input));
+        }
+    }
+
+    protected byte getByte(int index) {
+        return getDelegate().getByte(index);
+    }
+
+    abstract protected IdenticonBase getDelegate();
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        getDelegate().updateSize(w, h);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
+        setMeasuredDimension(size, size);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        getDelegate().draw(canvas);
+    }
+
+}
diff --git a/briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java b/briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java
new file mode 100644
index 0000000000..170ed77ef5
--- /dev/null
+++ b/briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java
@@ -0,0 +1,81 @@
+package im.delight.android.identicons;
+
+/**
+ * Copyright 2014 www.delight.im <info@delight.im>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import android.content.Context;
+import android.graphics.Color;
+import android.util.AttributeSet;
+
+public class SymmetricIdenticon extends IdenticonView {
+
+    private static final int CENTER_COLUMN_INDEX = 3;
+
+    private IdenticonBase mDelegate;
+
+    public SymmetricIdenticon(Context context) {
+        super(context);
+        initDelegate();
+    }
+
+    public SymmetricIdenticon(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        initDelegate();
+    }
+
+    public SymmetricIdenticon(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        initDelegate();
+    }
+
+    private void initDelegate() {
+        mDelegate = new IdenticonBase() {
+            @Override
+            protected int getRowCount() {
+                return 5;
+            }
+
+            @Override
+            protected int getColumnCount() {
+                return 5;
+            }
+
+            @Override
+            protected boolean isCellVisible(int row, int column) {
+                return getByte(3 + row * CENTER_COLUMN_INDEX + getSymmetricColumnIndex(column)) >= 0;
+            }
+
+            @Override
+            protected int getIconColor() {
+                return Color.rgb(getByte(0) + 128, getByte(1) + 128, getByte(2) + 128);
+            }
+        };
+    }
+
+    @Override
+    protected IdenticonBase getDelegate() {
+        return mDelegate;
+    }
+
+    protected int getSymmetricColumnIndex(int row) {
+        if (row < CENTER_COLUMN_INDEX) {
+            return row;
+        } else {
+            return getDelegate().getColumnCount() - row - 1;
+        }
+    }
+
+}
-- 
GitLab