2 * Copyright (C) 2013 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.gallery3d.filtershow.filters;
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;
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;
37 import java.io.IOException;
38 import java.util.Arrays;
39 import java.util.Iterator;
40 import java.util.Vector;
42 public class FilterDrawRepresentation extends FilterRepresentation {
43 private static final String LOGTAG = "FilterDrawRepresentation";
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, 20, 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);
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";
66 private Parameter[] mAllParam = {
72 public void setPramMode(int mode) {
74 mCurrentParam = mAllParam[mParamMode];
77 public int getParamMode() {
81 public Parameter getCurrentParam() {
82 return mAllParam[mParamMode];
85 public Parameter getParam(int type) {
86 return mAllParam[type];
89 public static class StrokeData implements Cloneable {
94 public int noPoints = 0;
95 public float[] mPoints = new float[20];
100 public StrokeData(StrokeData copy) {
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);
110 public boolean equals(Object o) {
111 if (!(o instanceof StrokeData)) {
114 StrokeData sd = (StrokeData) o;
115 if (mType != sd.mType
116 || mRadius != sd.mRadius
117 || noPoints != sd.noPoints
118 || mColor != sd.mColor) {
121 return mPath.equals(sd.mPath);
125 public String toString() {
126 return "stroke(" + mType + ", path(" + (mPath) + "), " + mRadius + " , "
127 + Integer.toHexString(mColor) + ")";
131 public StrokeData clone() throws CloneNotSupportedException {
132 return (StrokeData) super.clone();
136 static String colorHexString(int val) {
137 String str = "00000000" + Integer.toHexString(val);
138 str = "0x" + str.substring(str.length() - 8);
142 public String getValueString() {
144 switch (mParamMode) {
146 val = ((ParameterColor) mAllParam[mParamMode]).getValue();
147 return ((val > 0) ? " +" : " ") + colorHexString(val);
149 val = ((BasicParameterInt) mAllParam[mParamMode]).getValue();
150 return ((val > 0) ? " +" : " ") + val;
157 private Vector<StrokeData> mDrawing = new Vector<StrokeData>();
158 private StrokeData mCurrent; // used in the currently drawing style
160 public FilterDrawRepresentation() {
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);
172 public String toString() {
173 return getName() + " : strokes=" + mDrawing.size()
174 + ((mCurrent == null) ? " no current "
175 : ("draw=" + mCurrent.mType + " " + mCurrent.noPoints));
178 public Vector<StrokeData> getDrawing() {
182 public StrokeData getCurrentDrawing() {
187 public FilterRepresentation copy() {
188 FilterDrawRepresentation representation = new FilterDrawRepresentation();
189 copyAllParameters(representation);
190 return representation;
194 protected void copyAllParameters(FilterRepresentation representation) {
195 super.copyAllParameters(representation);
196 representation.useParametersFrom(this);
200 public boolean isNil() {
201 return getDrawing().isEmpty();
205 public void useParametersFrom(FilterRepresentation a) {
206 if (a instanceof FilterDrawRepresentation) {
207 FilterDrawRepresentation representation = (FilterDrawRepresentation) a;
208 mParamColor.copyPalletFrom(representation.mParamColor);
210 if (representation.mCurrent != null) {
211 mCurrent = (StrokeData) representation.mCurrent.clone();
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));
225 } catch (CloneNotSupportedException e) {
229 Log.v(LOGTAG, "cannot use parameters from " + a);
234 public boolean equals(FilterRepresentation representation) {
235 if (!super.equals(representation)) {
238 if (representation instanceof FilterDrawRepresentation) {
239 FilterDrawRepresentation fdRep = (FilterDrawRepresentation) representation;
240 if (fdRep.mDrawing.size() != mDrawing.size())
242 if (fdRep.mCurrent == null ^ (mCurrent == null || mCurrent.mPath == null)) {
247 if (fdRep.mCurrent != null && mCurrent != null && mCurrent.mPath != null) {
248 if (fdRep.mCurrent.noPoints == mCurrent.noPoints) {
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);
267 private int computeCurrentColor(){
268 return mParamColor.getValue();
271 public void fillStrokeParameters(StrokeData sd){
272 byte type = (byte) mParamStyle.getSelected();
273 int color = computeCurrentColor();
274 float size = mParamSize.getValue();
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;
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);
296 mCurrent.mPoints[len] = x;
297 mCurrent.mPoints[len + 1] = y;
301 public void endSection(float x, float y) {
303 mDrawing.add(mCurrent);
307 public void clearCurrentSection() {
311 public void clear() {
317 public void serializeRepresentation(JsonWriter writer) throws IOException {
318 writer.beginObject();
319 int len = mDrawing.size();
321 float[] mPosition = new float[2];
322 float[] mTan = new float[2];
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);
336 int npoints = mark.noPoints * 2;
337 for (int j = 0; j < npoints; j++) {
338 writer.value(mark.mPoints[j]);
347 public void deSerializeRepresentation(JsonReader sreader) throws IOException {
348 sreader.beginObject();
349 Vector<StrokeData> strokes = new Vector<StrokeData>();
351 while (sreader.hasNext()) {
353 sreader.beginObject();
354 StrokeData stroke = new StrokeData();
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)) {
369 sreader.beginArray();
370 while (sreader.hasNext()) {
371 if ((count + 1) > stroke.mPoints.length) {
372 stroke.mPoints = Arrays.copyOf(stroke.mPoints, count * 2);
374 stroke.mPoints[count++] = (float) sreader.nextDouble();
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]);