mirror of
https://github.com/SimpleMobileTools/Simple-Draw.git
synced 2025-04-26 08:08:40 +02:00
commit
6e7b73b681
@ -94,6 +94,10 @@ public class MyCanvas extends View {
|
|||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<MyPath,PaintOptions> getPaths() {
|
||||||
|
return mPaths;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(Canvas canvas) {
|
protected void onDraw(Canvas canvas) {
|
||||||
super.onDraw(canvas);
|
super.onDraw(canvas);
|
||||||
|
@ -2,6 +2,11 @@ package com.simplemobiletools.draw;
|
|||||||
|
|
||||||
import android.graphics.Path;
|
import android.graphics.Path;
|
||||||
|
|
||||||
|
import com.simplemobiletools.draw.actions.Action;
|
||||||
|
import com.simplemobiletools.draw.actions.Line;
|
||||||
|
import com.simplemobiletools.draw.actions.Move;
|
||||||
|
import com.simplemobiletools.draw.actions.Quad;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@ -45,54 +50,7 @@ class MyPath extends Path implements Serializable {
|
|||||||
super.quadTo(x1, y1, x2, y2);
|
super.quadTo(x1, y1, x2, y2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private interface Action extends Serializable {
|
List<Action> getActions() {
|
||||||
void perform(Path path);
|
return actions;
|
||||||
}
|
|
||||||
|
|
||||||
private static final class Move implements Action {
|
|
||||||
|
|
||||||
private final float x, y;
|
|
||||||
|
|
||||||
Move(float x, float y) {
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void perform(Path path) {
|
|
||||||
path.moveTo(x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class Line implements Action {
|
|
||||||
|
|
||||||
private final float x, y;
|
|
||||||
|
|
||||||
Line(float x, float y) {
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void perform(Path path) {
|
|
||||||
path.lineTo(x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class Quad implements Action {
|
|
||||||
|
|
||||||
private final float x1, y1, x2, y2;
|
|
||||||
|
|
||||||
private Quad(float x1, float y1, float x2, float y2) {
|
|
||||||
this.x1 = x1;
|
|
||||||
this.y1 = y1;
|
|
||||||
this.x2 = x2;
|
|
||||||
this.y2 = y2;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void perform(Path path) {
|
|
||||||
path.quadTo(x1, y1, x2, y2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
69
app/src/main/java/com/simplemobiletools/draw/Svg.java
Normal file
69
app/src/main/java/com/simplemobiletools/draw/Svg.java
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package com.simplemobiletools.draw;
|
||||||
|
|
||||||
|
import android.graphics.drawable.ColorDrawable;
|
||||||
|
|
||||||
|
import com.simplemobiletools.draw.actions.Action;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class Svg {
|
||||||
|
|
||||||
|
public static void saveSvg(File output, MyCanvas canvas)
|
||||||
|
throws Exception {
|
||||||
|
// This might throw ClassCastException
|
||||||
|
int backgroundColor = ((ColorDrawable) canvas.getBackground()).getColor();
|
||||||
|
|
||||||
|
// This might throw IOException
|
||||||
|
FileOutputStream out = new FileOutputStream(output);
|
||||||
|
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
|
||||||
|
writeSvg(writer, backgroundColor, canvas.getPaths(), canvas.getWidth(), canvas.getHeight());
|
||||||
|
writer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void writeSvg(Writer writer, int backgroundColor,
|
||||||
|
Map<MyPath, PaintOptions> paths, int width, int height)
|
||||||
|
throws IOException {
|
||||||
|
writer.write("<svg width=\"");
|
||||||
|
writer.write(String.valueOf(width));
|
||||||
|
writer.write("\" height=\"");
|
||||||
|
writer.write(String.valueOf(height));
|
||||||
|
writer.write("\" xmlns=\"http://www.w3.org/2000/svg\">");
|
||||||
|
|
||||||
|
// Background color (use a rect)
|
||||||
|
writer.write("<rect width=\"");
|
||||||
|
writer.write(String.valueOf(width));
|
||||||
|
writer.write("\" height=\"");
|
||||||
|
writer.write(String.valueOf(height));
|
||||||
|
writer.write("\" fill=\"#");
|
||||||
|
writer.write(Integer.toHexString(backgroundColor).substring(2)); // Skip the alpha FF
|
||||||
|
writer.write("\"/>");
|
||||||
|
|
||||||
|
// Write the paths
|
||||||
|
for (Map.Entry<MyPath, PaintOptions> entry : paths.entrySet()) {
|
||||||
|
writePath(writer, entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
writer.write("</svg>");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void writePath(Writer writer, MyPath path, PaintOptions options)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
writer.write("<path d=\"");
|
||||||
|
for (Action action : path.getActions()) {
|
||||||
|
action.perform(writer);
|
||||||
|
writer.write(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.write("\" fill=\"none\" stroke=\"#");
|
||||||
|
writer.write(Integer.toHexString(options.color).substring(2)); // Skip the alpha FF
|
||||||
|
writer.write("\" stroke-width=\"");
|
||||||
|
writer.write(String.valueOf(options.strokeWidth));
|
||||||
|
writer.write("\" stroke-linecap=\"round\"/>");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package com.simplemobiletools.draw.actions;
|
||||||
|
|
||||||
|
import android.graphics.Path;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.io.Writer;
|
||||||
|
|
||||||
|
public interface Action extends Serializable {
|
||||||
|
void perform(Path path);
|
||||||
|
void perform(Writer writer) throws IOException;
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.simplemobiletools.draw.actions;
|
||||||
|
|
||||||
|
import android.graphics.Path;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
|
|
||||||
|
public final class Line implements Action {
|
||||||
|
|
||||||
|
private final float x, y;
|
||||||
|
|
||||||
|
public Line(float x, float y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void perform(Path path) {
|
||||||
|
path.lineTo(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void perform(Writer writer) throws IOException {
|
||||||
|
writer.write("L");
|
||||||
|
writer.write(String.valueOf(x));
|
||||||
|
writer.write(",");
|
||||||
|
writer.write(String.valueOf(y));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.simplemobiletools.draw.actions;
|
||||||
|
|
||||||
|
|
||||||
|
import android.graphics.Path;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
|
|
||||||
|
public final class Move implements Action {
|
||||||
|
|
||||||
|
private final float x, y;
|
||||||
|
|
||||||
|
public Move(float x, float y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void perform(Path path) {
|
||||||
|
path.moveTo(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void perform(Writer writer) throws IOException {
|
||||||
|
writer.write('M');
|
||||||
|
writer.write(String.valueOf(x));
|
||||||
|
writer.write(',');
|
||||||
|
writer.write(String.valueOf(y));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.simplemobiletools.draw.actions;
|
||||||
|
|
||||||
|
import android.graphics.Path;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
|
|
||||||
|
public final class Quad implements Action {
|
||||||
|
|
||||||
|
private final float x1, y1, x2, y2;
|
||||||
|
|
||||||
|
public Quad(float x1, float y1, float x2, float y2) {
|
||||||
|
this.x1 = x1;
|
||||||
|
this.y1 = y1;
|
||||||
|
this.x2 = x2;
|
||||||
|
this.y2 = y2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void perform(Path path) {
|
||||||
|
path.quadTo(x1, y1, x2, y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void perform(Writer writer) throws IOException {
|
||||||
|
writer.write('Q');
|
||||||
|
writer.write(String.valueOf(x1));
|
||||||
|
writer.write(',');
|
||||||
|
writer.write(String.valueOf(y1));
|
||||||
|
writer.write(' ');
|
||||||
|
writer.write(String.valueOf(x2));
|
||||||
|
writer.write(',');
|
||||||
|
writer.write(String.valueOf(y2));
|
||||||
|
}
|
||||||
|
}
|
@ -19,12 +19,14 @@ import android.view.MenuItem;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
import android.widget.RadioGroup;
|
||||||
import android.widget.SeekBar;
|
import android.widget.SeekBar;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.simplemobiletools.draw.Config;
|
import com.simplemobiletools.draw.Config;
|
||||||
import com.simplemobiletools.draw.MyCanvas;
|
import com.simplemobiletools.draw.MyCanvas;
|
||||||
import com.simplemobiletools.draw.R;
|
import com.simplemobiletools.draw.R;
|
||||||
|
import com.simplemobiletools.draw.Svg;
|
||||||
import com.simplemobiletools.draw.Utils;
|
import com.simplemobiletools.draw.Utils;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
@ -50,6 +52,7 @@ public class MainActivity extends SimpleActivity implements MyCanvas.PathsChange
|
|||||||
@BindView(R.id.stroke_width_bar) SeekBar mStrokeWidthBar;
|
@BindView(R.id.stroke_width_bar) SeekBar mStrokeWidthBar;
|
||||||
|
|
||||||
private String curFileName;
|
private String curFileName;
|
||||||
|
private int curExtensionId;
|
||||||
|
|
||||||
private int color;
|
private int color;
|
||||||
private float strokeWidth;
|
private float strokeWidth;
|
||||||
@ -163,6 +166,11 @@ public class MainActivity extends SimpleActivity implements MyCanvas.PathsChange
|
|||||||
|
|
||||||
final EditText fileNameET = (EditText) saveFileView.findViewById(R.id.file_name);
|
final EditText fileNameET = (EditText) saveFileView.findViewById(R.id.file_name);
|
||||||
fileNameET.setText(curFileName);
|
fileNameET.setText(curFileName);
|
||||||
|
|
||||||
|
final RadioGroup fileExtensionRG = (RadioGroup) saveFileView.findViewById(R.id.extension_radio_group);
|
||||||
|
if (curExtensionId != 0) {
|
||||||
|
fileExtensionRG.check(curExtensionId);
|
||||||
|
}
|
||||||
builder.setView(saveFileView);
|
builder.setView(saveFileView);
|
||||||
|
|
||||||
builder.setPositiveButton(R.string.ok, null);
|
builder.setPositiveButton(R.string.ok, null);
|
||||||
@ -174,10 +182,18 @@ public class MainActivity extends SimpleActivity implements MyCanvas.PathsChange
|
|||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
final String fileName = fileNameET.getText().toString().trim();
|
final String fileName = fileNameET.getText().toString().trim();
|
||||||
|
|
||||||
if (!fileName.isEmpty()) {
|
if (!fileName.isEmpty()) {
|
||||||
if (saveFile(fileName + ".png")) {
|
final String extension;
|
||||||
|
switch (fileExtensionRG.getCheckedRadioButtonId()) {
|
||||||
|
default:
|
||||||
|
case R.id.extension_radio_png: extension = ".png"; break;
|
||||||
|
case R.id.extension_radio_svg: extension = ".svg"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveFile(fileName, extension)) {
|
||||||
curFileName = fileName;
|
curFileName = fileName;
|
||||||
|
curExtensionId = fileExtensionRG.getCheckedRadioButtonId();
|
||||||
|
|
||||||
Utils.showToast(getApplicationContext(), R.string.saving_ok);
|
Utils.showToast(getApplicationContext(), R.string.saving_ok);
|
||||||
alertDialog.dismiss();
|
alertDialog.dismiss();
|
||||||
} else {
|
} else {
|
||||||
@ -190,7 +206,7 @@ public class MainActivity extends SimpleActivity implements MyCanvas.PathsChange
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean saveFile(final String fileName) {
|
private boolean saveFile(final String fileName, final String extension) {
|
||||||
final String path = Environment.getExternalStorageDirectory().toString();
|
final String path = Environment.getExternalStorageDirectory().toString();
|
||||||
final File directory = new File(path, SAVE_FOLDER_NAME);
|
final File directory = new File(path, SAVE_FOLDER_NAME);
|
||||||
if (!directory.exists()) {
|
if (!directory.exists()) {
|
||||||
@ -199,24 +215,41 @@ public class MainActivity extends SimpleActivity implements MyCanvas.PathsChange
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final Bitmap bitmap = mMyCanvas.getBitmap();
|
final File file = new File(directory, fileName+extension);
|
||||||
FileOutputStream out = null;
|
switch (extension) {
|
||||||
try {
|
case ".png":
|
||||||
final File file = new File(directory, fileName);
|
final Bitmap bitmap = mMyCanvas.getBitmap();
|
||||||
out = new FileOutputStream(file);
|
FileOutputStream out = null;
|
||||||
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
|
try {
|
||||||
MediaScannerConnection.scanFile(getApplicationContext(), new String[]{file.getAbsolutePath()}, null, null);
|
out = new FileOutputStream(file);
|
||||||
} catch (Exception e) {
|
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
|
||||||
Log.e(TAG, "MainActivity SaveFile " + e.getMessage());
|
MediaScannerConnection.scanFile(getApplicationContext(),
|
||||||
return false;
|
new String[]{file.getAbsolutePath()}, null, null);
|
||||||
} finally {
|
} catch (Exception e) {
|
||||||
try {
|
Log.e(TAG, "MainActivity SaveFile (.png) " + e.getMessage());
|
||||||
if (out != null) {
|
return false;
|
||||||
out.close();
|
} finally {
|
||||||
|
try {
|
||||||
|
if (out != null) {
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(TAG, "MainActivity SaveFile (.png) 2 " + e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
break;
|
||||||
Log.e(TAG, "MainActivity SaveFile 2 " + e.getMessage());
|
|
||||||
}
|
case ".svg":
|
||||||
|
try {
|
||||||
|
Svg.saveSvg(file, mMyCanvas);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "MainActivity SaveFile (.svg) " + e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -17,18 +17,26 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@+id/file_name_label"
|
android:layout_below="@+id/file_name_label"
|
||||||
android:layout_marginBottom="@dimen/activity_margin"
|
android:layout_marginBottom="@dimen/activity_margin"
|
||||||
android:layout_toLeftOf="@+id/file_extension"
|
|
||||||
android:singleLine="true"/>
|
android:singleLine="true"/>
|
||||||
|
|
||||||
<TextView
|
<RadioGroup
|
||||||
android:id="@+id/file_extension"
|
android:id="@+id/extension_radio_group"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignBottom="@+id/file_name"
|
android:layout_below="@+id/file_name"
|
||||||
android:layout_alignParentRight="true"
|
android:checkedButton="@+id/extension_radio_png">
|
||||||
android:layout_alignTop="@+id/file_name"
|
|
||||||
android:layout_below="@+id/file_name_label"
|
<RadioButton
|
||||||
android:gravity="center_vertical"
|
android:id="@+id/extension_radio_png"
|
||||||
android:text=".png"/>
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text=".png"/>
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/extension_radio_svg"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text=".svg"/>
|
||||||
|
</RadioGroup>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user