Home | History | Annotate | Download | only in filters
      1 /*
      2  * Copyright (C) 2013 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 
     17 package com.android.gallery3d.filtershow.filters;
     18 
     19 import android.graphics.Color;
     20 import android.graphics.Path;
     21 import android.graphics.PathMeasure;
     22 import android.util.JsonReader;
     23 import android.util.JsonWriter;
     24 import android.util.Log;
     25 
     26 import com.android.gallery3d.R;
     27 import com.android.gallery3d.filtershow.controller.BasicParameterInt;
     28 import com.android.gallery3d.filtershow.controller.BasicParameterStyle;
     29 import com.android.gallery3d.filtershow.controller.Parameter;
     30 import com.android.gallery3d.filtershow.controller.ParameterBrightness;
     31 import com.android.gallery3d.filtershow.controller.ParameterColor;
     32 import com.android.gallery3d.filtershow.controller.ParameterHue;
     33 import com.android.gallery3d.filtershow.controller.ParameterOpacity;
     34 import com.android.gallery3d.filtershow.controller.ParameterSaturation;
     35 import com.android.gallery3d.filtershow.editors.EditorDraw;
     36 
     37 import java.io.IOException;
     38 import java.util.Arrays;
     39 import java.util.Iterator;
     40 import java.util.Vector;
     41 
     42 public class FilterDrawRepresentation extends FilterRepresentation {
     43     private static final String LOGTAG = "FilterDrawRepresentation";
     44 
     45     public static final int PARAM_SIZE = 0;
     46     public static final int PARAM_STYLE = 1;
     47     public static final int PARAM_COLOR = 2;
     48     private BasicParameterInt mParamSize = new BasicParameterInt(PARAM_SIZE, 30, 2, 300);
     49     private BasicParameterStyle mParamStyle = new BasicParameterStyle(PARAM_STYLE, 5);
     50     public static int DEFAULT_MENU_COLOR1 = Color.RED & 0x80FFFFFF;
     51     public static int DEFAULT_MENU_COLOR2 = Color.GREEN & 0x80FFFFFF;
     52     public static int DEFAULT_MENU_COLOR3 = Color.BLUE & 0x80FFFFFF;
     53     public static int DEFAULT_MENU_COLOR4 = Color.BLACK & 0x80FFFFFF;
     54     public static int DEFAULT_MENU_COLOR5 = Color.WHITE & 0x80FFFFFF;
     55     ParameterColor mParamColor = new ParameterColor(PARAM_COLOR,DEFAULT_MENU_COLOR1);
     56     int mParamMode;
     57     Parameter mCurrentParam = mParamSize;
     58     private static final String SERIAL_COLOR = "color";
     59     private static final String SERIAL_RADIUS = "radius";
     60     private static final String SERIAL_TYPE = "type";
     61     private static final String SERIAL_POINTS_COUNT = "point_count";
     62     private static final String SERIAL_POINTS = "points";
     63     private static final String SERIAL_PATH =  "path";
     64 
     65 
     66     private Parameter[] mAllParam = {
     67             mParamSize,
     68             mParamStyle,
     69             mParamColor
     70     };
     71 
     72     public void setPramMode(int mode) {
     73         mParamMode = mode;
     74         mCurrentParam = mAllParam[mParamMode];
     75     }
     76 
     77     public int getParamMode() {
     78         return mParamMode;
     79     }
     80 
     81     public Parameter getCurrentParam() {
     82         return  mAllParam[mParamMode];
     83     }
     84 
     85     public Parameter getParam(int type) {
     86         return  mAllParam[type];
     87     }
     88 
     89     public static class StrokeData implements Cloneable {
     90         public byte mType;
     91         public Path mPath;
     92         public float mRadius;
     93         public int mColor;
     94         public int noPoints = 0;
     95         public float[] mPoints = new float[20];
     96 
     97         public StrokeData() {
     98         }
     99 
    100         public StrokeData(StrokeData copy) {
    101             mType = copy.mType;
    102             mPath = new Path(copy.mPath);
    103             mRadius = copy.mRadius;
    104             mColor = copy.mColor;
    105             noPoints = copy.noPoints;
    106             mPoints = Arrays.copyOf(copy.mPoints, copy.mPoints.length);
    107         }
    108 
    109         @Override
    110         public boolean equals(Object o) {
    111             if (!(o instanceof StrokeData)) {
    112                 return false;
    113             }
    114             StrokeData sd = (StrokeData) o;
    115             if (mType != sd.mType
    116                     || mRadius != sd.mRadius
    117                     || noPoints != sd.noPoints
    118                     || mColor != sd.mColor) {
    119                 return false;
    120             }
    121             return mPath.equals(sd.mPath);
    122         }
    123 
    124         @Override
    125         public String toString() {
    126             return "stroke(" + mType + ", path(" + (mPath) + "), " + mRadius + " , "
    127                     + Integer.toHexString(mColor) + ")";
    128         }
    129 
    130         @Override
    131         public StrokeData clone() throws CloneNotSupportedException {
    132             return (StrokeData) super.clone();
    133         }
    134     }
    135 
    136     static String colorHexString(int val) {
    137         String str = "00000000" + Integer.toHexString(val);
    138         str = "0x" + str.substring(str.length() - 8);
    139         return str;
    140     }
    141 
    142     public String getValueString() {
    143         int val;
    144         switch (mParamMode) {
    145             case PARAM_COLOR:
    146                 val = ((ParameterColor) mAllParam[mParamMode]).getValue();
    147                 return "";
    148             case PARAM_SIZE:
    149                 val = ((BasicParameterInt) mAllParam[mParamMode]).getValue();
    150                 return ((val > 0) ? " +" : " ") + val;
    151             case PARAM_STYLE:
    152                 return "";
    153         }
    154         return "";
    155     }
    156 
    157     private Vector<StrokeData> mDrawing = new Vector<StrokeData>();
    158     private StrokeData mCurrent; // used in the currently drawing style
    159 
    160     public FilterDrawRepresentation() {
    161         super("Draw");
    162         setFilterClass(ImageFilterDraw.class);
    163         setSerializationName("DRAW");
    164         setFilterType(FilterRepresentation.TYPE_VIGNETTE);
    165         setTextId(R.string.imageDraw);
    166         setEditorId(EditorDraw.ID);
    167         setOverlayId(R.drawable.filtershow_drawing);
    168         setOverlayOnly(true);
    169     }
    170 
    171     @Override
    172     public String toString() {
    173         return getName() + " : strokes=" + mDrawing.size()
    174                 + ((mCurrent == null) ? " no current "
    175                 : ("draw=" + mCurrent.mType + " " + mCurrent.noPoints));
    176     }
    177 
    178     public Vector<StrokeData> getDrawing() {
    179         return mDrawing;
    180     }
    181 
    182     public StrokeData getCurrentDrawing() {
    183         return mCurrent;
    184     }
    185 
    186     @Override
    187     public FilterRepresentation copy() {
    188         FilterDrawRepresentation representation = new FilterDrawRepresentation();
    189         copyAllParameters(representation);
    190         return representation;
    191     }
    192 
    193     @Override
    194     protected void copyAllParameters(FilterRepresentation representation) {
    195         super.copyAllParameters(representation);
    196         representation.useParametersFrom(this);
    197     }
    198 
    199     @Override
    200     public boolean isNil() {
    201         return getDrawing().isEmpty();
    202     }
    203 
    204     @Override
    205     public void useParametersFrom(FilterRepresentation a) {
    206         if (a instanceof FilterDrawRepresentation) {
    207             FilterDrawRepresentation representation = (FilterDrawRepresentation) a;
    208             mParamColor.copyPalletFrom(representation.mParamColor);
    209             try {
    210                 if (representation.mCurrent != null) {
    211                     mCurrent = (StrokeData) representation.mCurrent.clone();
    212                 } else {
    213                     mCurrent = null;
    214                 }
    215                 if (representation.mDrawing != null) {
    216                     mDrawing = new Vector<StrokeData>();
    217                     for (Iterator<StrokeData> elem = representation.mDrawing.iterator(); elem.hasNext(); ) {
    218                         StrokeData next =  elem.next();
    219                         mDrawing.add(new StrokeData(next));
    220                     }
    221                 } else {
    222                     mDrawing = null;
    223                 }
    224 
    225             } catch (CloneNotSupportedException e) {
    226                 e.printStackTrace();
    227             }
    228         } else {
    229             Log.v(LOGTAG, "cannot use parameters from " + a);
    230         }
    231     }
    232 
    233     @Override
    234     public boolean equals(FilterRepresentation representation) {
    235         if (!super.equals(representation)) {
    236             return false;
    237         }
    238         if (representation instanceof FilterDrawRepresentation) {
    239             FilterDrawRepresentation fdRep = (FilterDrawRepresentation) representation;
    240             if (fdRep.mDrawing.size() != mDrawing.size())
    241                 return false;
    242             if (fdRep.mCurrent == null ^ (mCurrent == null || mCurrent.mPath == null)) {
    243                 return false;
    244             }
    245 
    246 
    247             if (fdRep.mCurrent != null && mCurrent != null && mCurrent.mPath != null) {
    248                 if (fdRep.mCurrent.noPoints == mCurrent.noPoints) {
    249                     return true;
    250                 }
    251                 return false;
    252             }
    253 
    254         int n = mDrawing.size();
    255         for (int i = 0; i < n; i++) {
    256             StrokeData a = mDrawing.get(i);
    257             StrokeData b = mDrawing.get(i);
    258             if (!a.equals(b)){
    259                 return false;
    260             }
    261         }
    262         return true;
    263         }
    264         return false;
    265     }
    266 
    267     private int computeCurrentColor(){
    268         return mParamColor.getValue();
    269     }
    270 
    271     public void fillStrokeParameters(StrokeData sd){
    272         byte type = (byte) mParamStyle.getSelected();
    273         int color = computeCurrentColor();
    274         float size = mParamSize.getValue();
    275         sd.mColor = color;
    276         sd.mRadius = size;
    277         sd.mType = type;
    278     }
    279 
    280     public void startNewSection(float x, float y) {
    281         mCurrent = new StrokeData();
    282         fillStrokeParameters(mCurrent);
    283         mCurrent.mPath = new Path();
    284         mCurrent.mPath.moveTo(x, y);
    285         mCurrent.mPoints[0] = x;
    286         mCurrent.mPoints[1] = y;
    287         mCurrent.noPoints = 1;
    288     }
    289 
    290     public void addPoint(float x, float y) {
    291         int len = mCurrent.noPoints * 2;
    292         mCurrent.mPath.lineTo(x, y);
    293         if ((len+2) > mCurrent.mPoints.length) {
    294             mCurrent.mPoints = Arrays.copyOf(mCurrent.mPoints, mCurrent.mPoints.length * 2);
    295         }
    296         mCurrent.mPoints[len] = x;
    297         mCurrent.mPoints[len + 1] = y;
    298         mCurrent.noPoints++;
    299     }
    300 
    301     public void endSection(float x, float y) {
    302         addPoint(x, y);
    303         mDrawing.add(mCurrent);
    304         mCurrent = null;
    305     }
    306 
    307     public void clearCurrentSection() {
    308         mCurrent = null;
    309     }
    310 
    311     public void clear() {
    312         mCurrent = null;
    313         mDrawing.clear();
    314     }
    315 
    316     @Override
    317     public void serializeRepresentation(JsonWriter writer) throws IOException {
    318         writer.beginObject();
    319         int len = mDrawing.size();
    320         int count = 0;
    321         float[] mPosition = new float[2];
    322         float[] mTan = new float[2];
    323 
    324         PathMeasure mPathMeasure = new PathMeasure();
    325         for (int i = 0; i < len; i++) {
    326             writer.name(SERIAL_PATH + i);
    327             writer.beginObject();
    328             StrokeData mark = mDrawing.get(i);
    329             writer.name(SERIAL_COLOR).value(mark.mColor);
    330             writer.name(SERIAL_RADIUS).value(mark.mRadius);
    331             writer.name(SERIAL_TYPE).value(mark.mType);
    332             writer.name(SERIAL_POINTS_COUNT).value(mark.noPoints);
    333             writer.name(SERIAL_POINTS);
    334 
    335             writer.beginArray();
    336             int npoints = mark.noPoints * 2;
    337             for (int j = 0; j < npoints; j++) {
    338                 writer.value(mark.mPoints[j]);
    339             }
    340             writer.endArray();
    341             writer.endObject();
    342         }
    343         writer.endObject();
    344     }
    345 
    346     @Override
    347     public void deSerializeRepresentation(JsonReader sreader) throws IOException {
    348         sreader.beginObject();
    349         Vector<StrokeData> strokes = new Vector<StrokeData>();
    350 
    351         while (sreader.hasNext()) {
    352             sreader.nextName();
    353             sreader.beginObject();
    354             StrokeData stroke = new StrokeData();
    355 
    356             while (sreader.hasNext()) {
    357                 String name = sreader.nextName();
    358                 if (name.equals(SERIAL_COLOR)) {
    359                     stroke.mColor = sreader.nextInt();
    360                 } else if (name.equals(SERIAL_RADIUS)) {
    361                     stroke.mRadius = (float) sreader.nextDouble();
    362                 } else if (name.equals(SERIAL_TYPE)) {
    363                     stroke.mType = (byte) sreader.nextInt();
    364                 } else if (name.equals(SERIAL_POINTS_COUNT)) {
    365                     stroke.noPoints = sreader.nextInt();
    366                 } else if (name.equals(SERIAL_POINTS)) {
    367 
    368                     int count = 0;
    369                     sreader.beginArray();
    370                     while (sreader.hasNext()) {
    371                         if ((count + 1) > stroke.mPoints.length) {
    372                             stroke.mPoints = Arrays.copyOf(stroke.mPoints, count * 2);
    373                         }
    374                         stroke.mPoints[count++] = (float) sreader.nextDouble();
    375                     }
    376                     stroke.mPath = new Path();
    377                     stroke.mPath.moveTo(stroke.mPoints[0], stroke.mPoints[1]);
    378                     for (int i = 0; i < count; i += 2) {
    379                         stroke.mPath.lineTo(stroke.mPoints[i], stroke.mPoints[i + 1]);
    380                     }
    381                     sreader.endArray();
    382                     strokes.add(stroke);
    383                 } else {
    384                     sreader.skipValue();
    385                 }
    386             }
    387             sreader.endObject();
    388         }
    389 
    390         mDrawing = strokes;
    391 
    392         sreader.endObject();
    393     }
    394 }
    395