Fix borders

Change-Id: Ia77660872f3baf10968e20b5656d97c4fbfc815e
diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
index d3fb7d0..47334fe 100644
--- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java
+++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
@@ -79,7 +79,6 @@
 import com.android.gallery3d.filtershow.tools.SaveCopyTask;
 import com.android.gallery3d.filtershow.ui.FilterIconButton;
 import com.android.gallery3d.filtershow.ui.FramedTextButton;
-import com.android.gallery3d.filtershow.ui.ImageCurves;
 import com.android.gallery3d.filtershow.ui.Spline;
 import com.android.gallery3d.util.GalleryUtils;
 
@@ -376,37 +375,34 @@
     }
 
     private class LoadBordersTask extends AsyncTask<Void, Boolean, Boolean> {
-        Vector<ImageFilter> mBorders;
+        Vector<FilterRepresentation> mBorders;
         LinearLayout mList;
 
         public LoadBordersTask(LinearLayout list) {
             mList = list;
-            mBorders = new Vector<ImageFilter>();
+            mBorders = new Vector<FilterRepresentation>();
         }
 
         @Override
         protected Boolean doInBackground(Void... params) {
-            mBorders.add(new ImageFilterBorder(null));
+            mBorders.add(new FilterImageBorderRepresentation(0, null));
             Drawable npd1 = getResources().getDrawable(R.drawable.filtershow_border_4x5);
-            mBorders.add(new ImageFilterBorder(npd1));
+            mBorders.add(new FilterImageBorderRepresentation(R.drawable.filtershow_border_4x5, npd1));
             Drawable npd2 = getResources().getDrawable(R.drawable.filtershow_border_brush);
-            mBorders.add(new ImageFilterBorder(npd2));
+            mBorders.add(new FilterImageBorderRepresentation(R.drawable.filtershow_border_brush, npd2));
             Drawable npd3 = getResources().getDrawable(R.drawable.filtershow_border_grunge);
-            mBorders.add(new ImageFilterBorder(npd3));
+            mBorders.add(new FilterImageBorderRepresentation(R.drawable.filtershow_border_grunge, npd3));
             Drawable npd4 = getResources().getDrawable(R.drawable.filtershow_border_sumi_e);
-            mBorders.add(new ImageFilterBorder(npd4));
+            mBorders.add(new FilterImageBorderRepresentation(R.drawable.filtershow_border_sumi_e, npd4));
             Drawable npd5 = getResources().getDrawable(R.drawable.filtershow_border_tape);
-            mBorders.add(new ImageFilterBorder(npd5));
-            mBorders.add(new ImageFilterParametricBorder(Color.BLACK, mImageBorderSize, 0));
-            mBorders.add(new ImageFilterParametricBorder(Color.BLACK, mImageBorderSize,
-                    mImageBorderSize));
-            mBorders.add(new ImageFilterParametricBorder(Color.WHITE, mImageBorderSize, 0));
-            mBorders.add(new ImageFilterParametricBorder(Color.WHITE, mImageBorderSize,
-                    mImageBorderSize));
+            mBorders.add(new FilterImageBorderRepresentation(R.drawable.filtershow_border_tape, npd5));
+            mBorders.add(new FilterColorBorderRepresentation(Color.BLACK, mImageBorderSize, 0));
+            mBorders.add(new FilterColorBorderRepresentation(Color.BLACK, mImageBorderSize, mImageBorderSize));
+            mBorders.add(new FilterColorBorderRepresentation(Color.WHITE, mImageBorderSize, 0));
+            mBorders.add(new FilterColorBorderRepresentation(Color.WHITE, mImageBorderSize, mImageBorderSize));
             int creamColor = Color.argb(255, 237, 237, 227);
-            mBorders.add(new ImageFilterParametricBorder(creamColor, mImageBorderSize, 0));
-            mBorders.add(new ImageFilterParametricBorder(creamColor, mImageBorderSize,
-                    mImageBorderSize));
+            mBorders.add(new FilterColorBorderRepresentation(creamColor, mImageBorderSize, 0));
+            mBorders.add(new FilterColorBorderRepresentation(creamColor, mImageBorderSize, mImageBorderSize));
             return true;
         }
 
@@ -416,9 +412,12 @@
                 return;
             }
             for (int i = 0; i < mBorders.size(); i++) {
-                ImageFilter filter = mBorders.elementAt(i);
+                FilterRepresentation filter = mBorders.elementAt(i);
                 filter.setName(getString(R.string.borders));
-                FilterIconButton b = setupFilterButton(filter, mList, mBorderButton);
+                if (i == 0) {
+                    filter.setName(getString(R.string.none));
+                }
+                FilterIconButton b = setupFilterRepresentationButton(filter, mList, mBorderButton);
                 if (i == 0) {
                     mNullBorderFilter = b;
                     mNullBorderFilter.setSelected(true);
@@ -1006,7 +1005,7 @@
         if (representation == null) {
             copy.addFilter(filterRepresentation);
         } else {
-            if (filterRepresentation instanceof FilterFxRepresentation) {
+            if (filterRepresentation.allowsMultipleInstances()) {
                 representation.useParametersFrom(filterRepresentation);
                 copy.setHistoryName(filterRepresentation.getName());
             }
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java
new file mode 100644
index 0000000..3ea678c
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+public class FilterColorBorderRepresentation extends FilterRepresentation {
+    private int mColor;
+    private int mBorderSize;
+    private int mBorderRadius;
+
+    public FilterColorBorderRepresentation(int color, int size, int radius) {
+        super("ColorBorder");
+        mColor = color;
+        mBorderSize = size;
+        mBorderRadius = radius;
+        setFilterClass(ImageFilterParametricBorder.class);
+        setPriority(ImageFilter.TYPE_BORDER);
+    }
+
+    public String toString() {
+        return "FilterBorder: " + getName();
+    }
+
+    @Override
+    public FilterRepresentation clone() throws CloneNotSupportedException {
+        FilterColorBorderRepresentation representation = (FilterColorBorderRepresentation) super.clone();
+        representation.setName(getName());
+        representation.setColor(getColor());
+        representation.setBorderSize(getBorderSize());
+        representation.setBorderRadius(getBorderRadius());
+        return representation;
+    }
+
+    public void useParametersFrom(FilterRepresentation a) {
+        if (a instanceof FilterColorBorderRepresentation) {
+            FilterColorBorderRepresentation representation = (FilterColorBorderRepresentation) a;
+            setName(representation.getName());
+            setColor(representation.getColor());
+            setBorderSize(representation.getBorderSize());
+            setBorderRadius(representation.getBorderRadius());
+        }
+    }
+
+    @Override
+    public boolean equals(FilterRepresentation representation) {
+        if (!super.equals(representation)) {
+            return false;
+        }
+        if (representation instanceof FilterColorBorderRepresentation) {
+            FilterColorBorderRepresentation border = (FilterColorBorderRepresentation) representation;
+            if (border.mColor == mColor
+                    && border.mBorderSize == mBorderSize
+                    && border.mBorderRadius == mBorderRadius) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean allowsMultipleInstances() {
+        return true;
+    }
+
+    public int getColor() {
+        return mColor;
+    }
+
+    public void setColor(int color) {
+        mColor = color;
+    }
+
+    public int getBorderSize() {
+        return mBorderSize;
+    }
+
+    public void setBorderSize(int borderSize) {
+        mBorderSize = borderSize;
+    }
+
+    public int getBorderRadius() {
+        return mBorderRadius;
+    }
+
+    public void setBorderRadius(int borderRadius) {
+        mBorderRadius = borderRadius;
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java
index 54a227f..06987d2 100644
--- a/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java
+++ b/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java
@@ -72,6 +72,10 @@
         return false;
     }
 
+    public boolean allowsMultipleInstances() {
+        return false;
+    }
+
     public Bitmap getFxBitmap() {
         return mFxBitmap;
     }
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java
new file mode 100644
index 0000000..467409f
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.graphics.drawable.Drawable;
+
+public class FilterImageBorderRepresentation extends FilterRepresentation {
+    private Drawable mDrawable;
+    private int mDrawableResource = 0;
+
+    public FilterImageBorderRepresentation(int drawableResource, Drawable drawable) {
+        super("ImageBorder");
+        mDrawableResource = drawableResource;
+        mDrawable = drawable;
+        setFilterClass(ImageFilterBorder.class);
+        setPriority(ImageFilter.TYPE_BORDER);
+    }
+
+    public String toString() {
+        return "FilterBorder: " + getName();
+    }
+
+    @Override
+    public FilterRepresentation clone() throws CloneNotSupportedException {
+        FilterImageBorderRepresentation representation = (FilterImageBorderRepresentation) super.clone();
+        representation.setName(getName());
+        representation.setDrawable(getDrawable());
+        representation.setDrawableResource(getDrawableResource());
+        return representation;
+    }
+
+    public void useParametersFrom(FilterRepresentation a) {
+        if (a instanceof FilterImageBorderRepresentation) {
+            FilterImageBorderRepresentation representation = (FilterImageBorderRepresentation) a;
+            setName(representation.getName());
+            setDrawable(representation.getDrawable());
+            setDrawableResource(representation.getDrawableResource());
+        }
+    }
+
+    @Override
+    public boolean equals(FilterRepresentation representation) {
+        if (!super.equals(representation)) {
+            return false;
+        }
+        if (representation instanceof FilterImageBorderRepresentation) {
+            FilterImageBorderRepresentation border = (FilterImageBorderRepresentation) representation;
+            if (border.mDrawableResource == mDrawableResource) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean allowsMultipleInstances() {
+        return true;
+    }
+
+    public Drawable getDrawable() {
+        return mDrawable;
+    }
+
+    public void setDrawable(Drawable drawable) {
+        mDrawable = drawable;
+    }
+
+    public int getDrawableResource() {
+        return mDrawableResource;
+    }
+
+    public void setDrawableResource(int drawableResource) {
+        mDrawableResource = drawableResource;
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java
index 1415f14..d92b323 100644
--- a/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java
+++ b/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java
@@ -46,6 +46,9 @@
     }
 
     public boolean equals(FilterRepresentation representation) {
+        if (representation == null) {
+            return false;
+        }
         if (representation.mFilterClass == representation.mFilterClass
                 && representation.mName.equalsIgnoreCase(mName)
                 && representation.mPriority == mPriority
@@ -94,6 +97,10 @@
         return mShowParameterValue;
     }
 
+    public boolean allowsMultipleInstances() {
+        return false;
+    }
+
     public Class getFilterClass() {
         return mFilterClass;
     }
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java
index 7d8152b..646a6b4 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java
@@ -27,6 +27,7 @@
     private static final float NINEPATCH_ICON_SCALING = 10;
     private static final float BITMAP_ICON_SCALING = 1 / 3.0f;
     Drawable mNinePatch = null;
+    private FilterImageBorderRepresentation mParameters = null;
 
     @Override
     public ImageFilter clone() throws CloneNotSupportedException {
@@ -35,12 +36,25 @@
         return filter;
     }
 
+    public ImageFilterBorder() {
+
+    }
+
     public ImageFilterBorder(Drawable ninePatch) {
         setFilterType(TYPE_BORDER);
         mName = "Border";
         mNinePatch = ninePatch;
     }
 
+    public void useRepresentation(FilterRepresentation representation) {
+        FilterImageBorderRepresentation parameters = (FilterImageBorderRepresentation) representation;
+        mParameters = parameters;
+    }
+
+    public FilterImageBorderRepresentation getParameters() {
+        return mParameters;
+    }
+
     public boolean isNil() {
         if (mNinePatch == null) {
             return true;
@@ -95,14 +109,14 @@
         Rect bounds = new Rect(0, 0, (int) (w * scale1), (int) (h * scale1));
         Canvas canvas = new Canvas(bitmap);
         canvas.scale(scale2, scale2);
-        mNinePatch.setBounds(bounds);
-        mNinePatch.draw(canvas);
+        getParameters().getDrawable().setBounds(bounds);
+        getParameters().getDrawable().draw(canvas);
         return bitmap;
     }
 
     @Override
     public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
-        if (mNinePatch == null) {
+        if (getParameters() == null || getParameters().getDrawable() == null) {
             return bitmap;
         }
         float scale2 = scaleFactor * 2.0f;
@@ -112,7 +126,7 @@
 
     @Override
     public Bitmap iconApply(Bitmap bitmap, float scaleFactor, boolean highQuality) {
-        if (mNinePatch == null) {
+        if (getParameters() == null || getParameters().getDrawable() == null) {
             return bitmap;
         }
         float scale1 = NINEPATCH_ICON_SCALING;
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java
index 1e75eb2..ca98069 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java
@@ -29,12 +29,22 @@
     private int mBorderColor = Color.WHITE;
     private int mBorderSize = 10;
     private int mBorderCornerRadius = 10;
+    private FilterColorBorderRepresentation mParameters = null;
 
     public ImageFilterParametricBorder() {
         setFilterType(TYPE_BORDER);
         mName = "Border";
     }
 
+    public void useRepresentation(FilterRepresentation representation) {
+        FilterColorBorderRepresentation parameters = (FilterColorBorderRepresentation) representation;
+        mParameters = parameters;
+    }
+
+    public FilterColorBorderRepresentation getParameters() {
+        return mParameters;
+    }
+
     @Override
     public int getTextId() {
         return R.string.borders;
@@ -100,10 +110,13 @@
     }
 
     private void applyHelper(Canvas canvas, int w, int h) {
+        if (getParameters() == null) {
+            return;
+        }
         Path border = new Path();
         border.moveTo(0, 0);
-        float bs = mBorderSize / 100.0f * w;
-        float r = mBorderCornerRadius / 100.0f * w;
+        float bs = getParameters().getBorderSize() / 100.0f * w;
+        float r = getParameters().getBorderRadius() / 100.0f * w;
         border.lineTo(0, h);
         border.lineTo(w, h);
         border.lineTo(w, 0);
@@ -113,7 +126,7 @@
 
         Paint paint = new Paint();
         paint.setAntiAlias(true);
-        paint.setColor(mBorderColor);
+        paint.setColor(getParameters().getColor());
         canvas.drawPath(border, paint);
     }
 
diff --git a/src/com/android/gallery3d/filtershow/presets/ImagePreset.java b/src/com/android/gallery3d/filtershow/presets/ImagePreset.java
index aba8688..fb58d1f 100644
--- a/src/com/android/gallery3d/filtershow/presets/ImagePreset.java
+++ b/src/com/android/gallery3d/filtershow/presets/ImagePreset.java
@@ -24,19 +24,16 @@
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
 import com.android.gallery3d.filtershow.filters.FiltersManager;
 import com.android.gallery3d.filtershow.filters.ImageFilter;
-import com.android.gallery3d.filtershow.filters.ImageFilterCurves;
 import com.android.gallery3d.filtershow.imageshow.GeometryMetadata;
-import com.android.gallery3d.filtershow.imageshow.ImageShow;
 import com.android.gallery3d.filtershow.imageshow.MasterImage;
 
-import java.util.HashMap;
 import java.util.Vector;
 
 public class ImagePreset {
 
     private static final String LOGTAG = "ImagePreset";
 
-    private FilterRepresentation mImageBorder = null;
+    private FilterRepresentation mBorder = null;
     private float mScaleFactor = 1.0f;
     private boolean mIsHighQuality = false;
     private ImageLoader mImageLoader = null;
@@ -70,8 +67,8 @@
 
     public ImagePreset(ImagePreset source) {
         try {
-            if (source.mImageBorder != null) {
-                mImageBorder = source.mImageBorder.clone();
+            if (source.mBorder != null) {
+                mBorder = source.mBorder.clone();
             }
             for (int i = 0; i < source.mFilters.size(); i++) {
                 FilterRepresentation representation = source.mFilters.elementAt(i).clone();
@@ -152,7 +149,7 @@
     }
 
     public boolean hasModifications() {
-        if (mImageBorder != null && !mImageBorder.isNil()) {
+        if (mBorder != null && !mBorder.isNil()) {
             return true;
         }
         if (mGeoData.hasModifications()) {
@@ -168,7 +165,7 @@
     }
 
     public boolean isPanoramaSafe() {
-        if (mImageBorder != null && !mImageBorder.isNil()) {
+        if (mBorder != null && !mBorder.isNil()) {
             return false;
         }
         if (mGeoData.hasModifications()) {
@@ -192,7 +189,7 @@
     }
 
     private void setBorder(FilterRepresentation filter) {
-        mImageBorder = filter;
+        mBorder = filter;
     }
 
     public boolean isFx() {
@@ -257,11 +254,11 @@
             return false;
         }
 
-        if (mDoApplyGeometry && mImageBorder != preset.mImageBorder) {
+        if (mDoApplyGeometry && mBorder != preset.mBorder) {
             return false;
         }
 
-        if (mImageBorder != null && !mImageBorder.equals(preset.mImageBorder)) {
+        if (mBorder != null && !mBorder.equals(preset.mBorder)) {
             return false;
         }
 
@@ -364,6 +361,9 @@
                 return representation;
             }
         }
+        if (mBorder != null && mBorder.getFilterClass() == filterRepresentation.getFilterClass()) {
+            return mBorder;
+        }
         return null;
     }
 
@@ -384,8 +384,9 @@
     }
 
     public Bitmap applyBorder(Bitmap bitmap) {
-        if (mImageBorder != null && mDoApplyGeometry) {
-            ImageFilter filter = FiltersManager.getManager().getFilterForRepresentation(mImageBorder);
+        if (mBorder != null && mDoApplyGeometry) {
+            ImageFilter filter = FiltersManager.getManager().getFilterForRepresentation(mBorder);
+            filter.useRepresentation(mBorder);
             bitmap = filter.apply(bitmap, mScaleFactor, mIsHighQuality);
         }
         return bitmap;
diff --git a/src_pd/com/android/gallery3d/filtershow/filters/FiltersManager.java b/src_pd/com/android/gallery3d/filtershow/filters/FiltersManager.java
index f7e0406..3a259e9 100644
--- a/src_pd/com/android/gallery3d/filtershow/filters/FiltersManager.java
+++ b/src_pd/com/android/gallery3d/filtershow/filters/FiltersManager.java
@@ -31,6 +31,8 @@
         Vector<ImageFilter> filters = new Vector<ImageFilter>();
         FiltersManager.addFilters(filters);
         filters.add(new ImageFilterFx());
+        filters.add(new ImageFilterBorder());
+        filters.add(new ImageFilterParametricBorder());
         for (ImageFilter filter : filters) {
             mFilters.put(filter.getClass(), filter);
         }