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;
47 public static final int PARAM_STYLE = 1;
48 public static final int PARAM_COLOR = 2;
49 private BasicParameterInt mParamSize = new BasicParameterInt(PARAM_SIZE, 20, 2, 300);
50 private BasicParameterStyle mParamStyle = new BasicParameterStyle(PARAM_STYLE, 5);
51 ParameterColor mParamColor = new ParameterColor(PARAM_COLOR);
53 Parameter mCurrentParam = mParamSize;
54 private static final String SERIAL_COLOR = "color";
55 private static final String SERIAL_RADIUS = "radius";
56 private static final String SERIAL_TYPE = "type";
57 private static final String SERIAL_POINTS_COUNT = "point_count";
58 private static final String SERIAL_POINTS = "points";
59 private static final String SERIAL_PATH = "path";
62 private Parameter[] mAllParam = {
68 public void setPramMode(int mode) {
70 mCurrentParam = mAllParam[mParamMode];
73 public int getParamMode() {
77 public Parameter getCurrentParam() {
78 return mAllParam[mParamMode];
81 public Parameter getParam(int type) {
82 return mAllParam[type];
85 public static class StrokeData implements Cloneable {
90 public int noPoints = 0;
91 public float[] mPoints = new float[20];
96 public StrokeData(StrokeData copy) {
98 mPath = new Path(copy.mPath);
99 mRadius = copy.mRadius;
100 mColor = copy.mColor;
101 noPoints = copy.noPoints;
102 mPoints = Arrays.copyOf(copy.mPoints, copy.mPoints.length);
106 public boolean equals(Object o) {
107 if (!(o instanceof StrokeData)) {
110 StrokeData sd = (StrokeData) o;
111 if (mType != sd.mType
112 || mRadius != sd.mRadius
113 || noPoints != sd.noPoints
114 || mColor != sd.mColor) {
117 return mPath.equals(sd.mPath);
121 public String toString() {
122 return "stroke(" + mType + ", path(" + (mPath) + "), " + mRadius + " , "
123 + Integer.toHexString(mColor) + ")";
127 public StrokeData clone() throws CloneNotSupportedException {
128 return (StrokeData) super.clone();
132 static String colorHexString(int val) {
133 String str = "00000000" + Integer.toHexString(val);
134 str = "0x" + str.substring(str.length() - 8);
138 public String getValueString() {
140 switch (mParamMode) {
142 val = ((ParameterColor) mAllParam[mParamMode]).getValue();
143 return ((val > 0) ? " +" : " ") + colorHexString(val);
145 val = ((BasicParameterInt) mAllParam[mParamMode]).getValue();
146 return ((val > 0) ? " +" : " ") + val;
153 private Vector<StrokeData> mDrawing = new Vector<StrokeData>();
154 private StrokeData mCurrent; // used in the currently drawing style
156 public FilterDrawRepresentation() {
158 setFilterClass(ImageFilterDraw.class);
159 setSerializationName("DRAW");
160 setFilterType(FilterRepresentation.TYPE_VIGNETTE);
161 setTextId(R.string.imageDraw);
162 setEditorId(EditorDraw.ID);
163 setOverlayId(R.drawable.filtershow_drawing);
164 setOverlayOnly(true);
168 public String toString() {
169 return getName() + " : strokes=" + mDrawing.size()
170 + ((mCurrent == null) ? " no current "
171 : ("draw=" + mCurrent.mType + " " + mCurrent.noPoints));
174 public Vector<StrokeData> getDrawing() {
178 public StrokeData getCurrentDrawing() {
183 public FilterRepresentation copy() {
184 FilterDrawRepresentation representation = new FilterDrawRepresentation();
185 copyAllParameters(representation);
186 return representation;
190 protected void copyAllParameters(FilterRepresentation representation) {
191 super.copyAllParameters(representation);
192 representation.useParametersFrom(this);
196 public boolean isNil() {
197 return getDrawing().isEmpty();
201 public void useParametersFrom(FilterRepresentation a) {
202 if (a instanceof FilterDrawRepresentation) {
203 FilterDrawRepresentation representation = (FilterDrawRepresentation) a;
205 if (representation.mCurrent != null) {
206 mCurrent = (StrokeData) representation.mCurrent.clone();
210 if (representation.mDrawing != null) {
211 mDrawing = new Vector<StrokeData>();
212 for (Iterator<StrokeData> elem = representation.mDrawing.iterator(); elem.hasNext(); ) {
213 StrokeData next = elem.next();
214 mDrawing.add(new StrokeData(next));
220 } catch (CloneNotSupportedException e) {
224 Log.v(LOGTAG, "cannot use parameters from " + a);
229 public boolean equals(FilterRepresentation representation) {
230 if (!super.equals(representation)) {
233 if (representation instanceof FilterDrawRepresentation) {
234 FilterDrawRepresentation fdRep = (FilterDrawRepresentation) representation;
235 if (fdRep.mDrawing.size() != mDrawing.size())
237 if (fdRep.mCurrent == null ^ (mCurrent == null || mCurrent.mPath == null)) {
242 if (fdRep.mCurrent != null && mCurrent != null && mCurrent.mPath != null) {
243 if (fdRep.mCurrent.noPoints == mCurrent.noPoints) {
249 int n = mDrawing.size();
250 for (int i = 0; i < n; i++) {
251 StrokeData a = mDrawing.get(i);
252 StrokeData b = mDrawing.get(i);
262 private int computeCurrentColor(){
263 return mParamColor.getValue();
266 public void fillStrokeParameters(StrokeData sd){
267 byte type = (byte) mParamStyle.getSelected();
268 int color = computeCurrentColor();
269 float size = mParamSize.getValue();
275 public void startNewSection(float x, float y) {
276 mCurrent = new StrokeData();
277 fillStrokeParameters(mCurrent);
278 mCurrent.mPath = new Path();
279 mCurrent.mPath.moveTo(x, y);
280 mCurrent.mPoints[0] = x;
281 mCurrent.mPoints[1] = y;
282 mCurrent.noPoints = 1;
285 public void addPoint(float x, float y) {
286 int len = mCurrent.noPoints * 2;
287 mCurrent.mPath.lineTo(x, y);
288 if ((len+2) > mCurrent.mPoints.length) {
289 mCurrent.mPoints = Arrays.copyOf(mCurrent.mPoints, mCurrent.mPoints.length * 2);
291 mCurrent.mPoints[len] = x;
292 mCurrent.mPoints[len + 1] = y;
296 public void endSection(float x, float y) {
298 mDrawing.add(mCurrent);
302 public void clearCurrentSection() {
306 public void clear() {
312 public void serializeRepresentation(JsonWriter writer) throws IOException {
313 writer.beginObject();
314 int len = mDrawing.size();
316 float[] mPosition = new float[2];
317 float[] mTan = new float[2];
319 PathMeasure mPathMeasure = new PathMeasure();
320 for (int i = 0; i < len; i++) {
321 writer.name(SERIAL_PATH + i);
322 writer.beginObject();
323 StrokeData mark = mDrawing.get(i);
324 writer.name(SERIAL_COLOR).value(mark.mColor);
325 writer.name(SERIAL_RADIUS).value(mark.mRadius);
326 writer.name(SERIAL_TYPE).value(mark.mType);
327 writer.name(SERIAL_POINTS_COUNT).value(mark.noPoints);
328 writer.name(SERIAL_POINTS);
331 int npoints = mark.noPoints * 2;
332 for (int j = 0; j < npoints; j++) {
333 writer.value(mark.mPoints[j]);
342 public void deSerializeRepresentation(JsonReader sreader) throws IOException {
343 sreader.beginObject();
344 Vector<StrokeData> strokes = new Vector<StrokeData>();
346 while (sreader.hasNext()) {
348 sreader.beginObject();
349 StrokeData stroke = new StrokeData();
351 while (sreader.hasNext()) {
352 String name = sreader.nextName();
353 if (name.equals(SERIAL_COLOR)) {
354 stroke.mColor = sreader.nextInt();
355 } else if (name.equals(SERIAL_RADIUS)) {
356 stroke.mRadius = (float) sreader.nextDouble();
357 } else if (name.equals(SERIAL_TYPE)) {
358 stroke.mType = (byte) sreader.nextInt();
359 } else if (name.equals(SERIAL_POINTS_COUNT)) {
360 stroke.noPoints = sreader.nextInt();
361 } else if (name.equals(SERIAL_POINTS)) {
364 sreader.beginArray();
365 while (sreader.hasNext()) {
366 if ((count + 1) > stroke.mPoints.length) {
367 stroke.mPoints = Arrays.copyOf(stroke.mPoints, count * 2);
369 stroke.mPoints[count++] = (float) sreader.nextDouble();
371 stroke.mPath = new Path();
372 stroke.mPath.moveTo(stroke.mPoints[0], stroke.mPoints[1]);
373 for (int i = 0; i < count; i += 2) {
374 stroke.mPath.lineTo(stroke.mPoints[i], stroke.mPoints[i + 1]);