mirror of
				https://github.com/SimpleMobileTools/Simple-Draw.git
				synced 2025-06-05 21:59:17 +02:00 
			
		
		
		
	| @@ -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> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user