package com.lfk.justwetools.View.NewPaint; import android.content.ContentResolver; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.RectF; import android.net.Uri; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.TextView; import android.widget.Toast; import com.lfk.justwetools.R; import com.lfk.justwetools.View.NewPaint.Graph.DrawBase; import com.lfk.justwetools.View.NewPaint.Graph.DrawCircle; import com.lfk.justwetools.View.NewPaint.Graph.DrawLine; import com.lfk.justwetools.View.NewPaint.Graph.DrawPath; import com.lfk.justwetools.View.NewPaint.Graph.DrawRect; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.charset.Charset; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; public class PaintView extends View { // drawing board private Bitmap mBitmap; // if you set a picture in you will use it private Bitmap mBitmapInit; private int mBitmapBackGround = R.drawable.whitbackground; private Canvas mCanvas; // private Path mPath; private Paint mBitmapPaint; // private Paint mEraserPaint; // private Paint mPaint; // width of screen private int width; // height of screen private int height; private Context context; // pass judgement on paint/eraser public static boolean IsPaint = true; // drawing x,y // private float mX, mY; // judge your fingers' tremble public static final float TOUCH_TOLERANCE = 4; // judge long pressed private static final long TOUCH_LONG_PRESSED = 500; public static boolean IsRecordPath = true; // private PathNode pathNode; private boolean mIsLongPressed; private boolean IsShowing = false; private boolean IsFirstTime = true; private long Touch_Down_Time; private long Touch_Up_Time; private OnPathListener listener; private static final int CHOOSEPATH = 0; private static final int INDIVIDE = 1; private boolean ReDoOrUnDoFlag = false; private PathNode pathNode; private ArrayList<PathNode.Node> ReDoNodes = new ArrayList<>(); private DrawBase drawBase = null; public enum mode { PATH, CIRCLE, LINE, RECT; } public PaintView(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; // mPaint = new Paint(); // mEraserPaint = new Paint(); // Init_Paint(UserInfo.PaintColor,UserInfo.PaintWidth); // Init_Eraser(UserInfo.EraserWidth); WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); width = manager.getDefaultDisplay().getWidth(); height = manager.getDefaultDisplay().getHeight(); mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); // mPath = new Path(); mBitmapPaint = new Paint(Paint.DITHER_FLAG); drawBase = new DrawRect(mCanvas); } public PaintView(Context context) { super(context); this.context = context; // mPaint = new Paint(); // mEraserPaint = new Paint(); // Init_Paint(UserInfo.PaintColor, UserInfo.PaintWidth); // Init_Eraser(UserInfo.EraserWidth); WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); width = manager.getDefaultDisplay().getWidth(); height = manager.getDefaultDisplay().getHeight(); // mBitmap = BitmapFactory.decodeResource(context.getResources(), mBitmapBackGround). // copy(Bitmap.Config.ARGB_8888, false); // mBitmap = Bitmap.createScaledBitmap(mBitmap,width,height,false); mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); // mPath = new Path(); mBitmapPaint = new Paint(Paint.DITHER_FLAG); } // init paint // private void Init_Paint(int color ,int width){ // mPaint.setAntiAlias(true); // mPaint.setDither(true); // mPaint.setColor(color); // mPaint.setStyle(Paint.Style.STROKE); // mPaint.setStrokeJoin(Paint.Join.ROUND); // mPaint.setStrokeCap(Paint.Cap.ROUND); // mPaint.setStrokeWidth(width); // } // // // // init eraser // private void Init_Eraser(int width){ // mEraserPaint.setAntiAlias(true); // mEraserPaint.setDither(true); // mEraserPaint.setColor(0xFF000000); // mEraserPaint.setStrokeWidth(width); // mEraserPaint.setStyle(Paint.Style.STROKE); // mEraserPaint.setStrokeJoin(Paint.Join.ROUND); // mEraserPaint.setStrokeCap(Paint.Cap.SQUARE); // // The most important // mEraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); // } // // while size is changed // @Override // protected void onSizeChanged(int w, int h, int oldw, int oldh) { // super.onSizeChanged(w, h, oldw, oldh); // if(IsPaint) // Init_Paint(UserInfo.PaintColor, UserInfo.PaintWidth); // else // Init_Eraser(UserInfo.EraserWidth); // } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint); drawBase.onDraw(canvas); // if(IsPaint) // canvas.drawPath(mPath, mPaint); // else // canvas.drawPath(mPath, mEraserPaint); } // private void Touch_Down(float x, float y) { // mPath.reset(); // mPath.moveTo(x, y); // mX = x; // mY = y; // if(IsRecordPath) { // listener.addNodeToPath(x, y, MotionEvent.ACTION_DOWN, IsPaint); // } // } // // // private void Touch_Move(float x, float y) { // float dx = Math.abs(x - mX); // float dy = Math.abs(y - mY); // if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { // mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2); // mX = x; // mY = y; // if(IsRecordPath) { // listener.addNodeToPath(x, y, MotionEvent.ACTION_MOVE, IsPaint); // } // } // } // private void Touch_Up(Paint paint){ // mPath.lineTo(mX, mY); // mCanvas.drawPath(mPath, paint); // mPath.reset(); // if(IsRecordPath) { // listener.addNodeToPath(mX, mY, MotionEvent.ACTION_UP, IsPaint); // } // } // public void setColor(int color) { // showCustomToast("已选择颜色" + colorToHexString(color)); // mPaint.setColor(color); // } // // // public void setPenWidth(int width) { // showCustomToast("设定笔粗为:" + width); // mPaint.setStrokeWidth(width); // } public void save() { mCanvas.save(); } public void setIsPaint(boolean isPaint) { IsPaint = isPaint; } public void setOnPathListener(OnPathListener listener) { this.listener = listener; } // public void setmEraserPaint(int width){ // showCustomToast("设定橡皮粗为:"+width); // mEraserPaint.setStrokeWidth(width); // } public OnPathListener getListener() { return listener; } public void setIsRecordPath(boolean isRecordPath, PathNode pathNode) { this.pathNode = pathNode; IsRecordPath = isRecordPath; } public void setIsRecordPath(boolean isRecordPath) { IsRecordPath = isRecordPath; } public boolean isShowing() { return IsShowing; } private static String colorToHexString(int color) { return String.format("#%06X", 0xFFFFFFFF & color); } // switch eraser/paint public void Eraser() { showCustomToast("切换为橡皮"); IsPaint = false; // Init_Eraser(UserInfo.EraserWidth); } public void Paint() { showCustomToast("切换为铅笔"); IsPaint = true; // Init_Paint(UserInfo.PaintColor, UserInfo.PaintWidth); } // public Paint getmEraserPaint() { // return mEraserPaint; // } // // public Paint getmPaint() { // return mPaint; // } /** * @author lfk_dsk@hotmail.com * clean the canvas */ public void clean() { mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); mCanvas.setBitmap(mBitmap); try { Message msg = new Message(); msg.obj = PaintView.this; msg.what = INDIVIDE; handler.sendMessage(msg); Thread.sleep(0); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } IsFirstTime = true; } /** * @param uri get the uri of a picture * @author lfk_dsk@hotmail.com */ public void setmBitmap(Uri uri) { Log.e("图片路径", String.valueOf(uri)); ContentResolver cr = context.getContentResolver(); try { mBitmapInit = BitmapFactory.decodeStream(cr.openInputStream(uri)); drawBitmapToCanvas(mBitmapInit); } catch (FileNotFoundException e) { e.printStackTrace(); } invalidate(); } private void drawBitmapToCanvas(Bitmap bitmap) { if (bitmap.getHeight() > height || bitmap.getWidth() > width) { RectF rectF = new RectF(0, 0, width, height); mCanvas.drawBitmap(bitmap, null, rectF, mBitmapPaint); } else { mCanvas.drawBitmap(bitmap, 0, 0, mBitmapPaint); } } /** * @param file Pictures' file * @author lfk_dsk@hotmail.com */ public void BitmapToPicture(File file) { FileOutputStream fileOutputStream; try { SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); Date now = new Date(); File tempfile = new File(file + "/" + formatter.format(now) + ".jpg"); fileOutputStream = new FileOutputStream(tempfile); Bitmap mBitmapbg = BitmapFactory.decodeResource(context.getResources(), mBitmapBackGround). copy(Bitmap.Config.ARGB_8888, false); mBitmapbg = Bitmap.createScaledBitmap(mBitmapbg, width, height, false); if (mBitmapInit != null) { mBitmapbg = toConformBitmap(mBitmapbg, mBitmapInit); mBitmapbg = toConformBitmap(mBitmapbg, mBitmap); } else { mBitmapbg = toConformBitmap(mBitmapbg, mBitmap); } mBitmapbg.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream); showCustomToast(tempfile.getName() + "已保存"); } catch (FileNotFoundException e) { e.printStackTrace(); } } public void PathNodeToJson(PathNode pathNode, File file) { ArrayList<PathNode.Node> arrayList = pathNode.getPathList(); String json = "["; for (int i = 0; i < arrayList.size(); i++) { PathNode.Node node = arrayList.get(i); json += "{" + "\"" + "x" + "\"" + ":" + node.x + "," + "\"" + "y" + "\"" + ":" + node.y + "," + "\"" + "PenColor" + "\"" + ":" + node.PenColor + "," + "\"" + "PenWidth" + "\"" + ":" + node.PenWidth + "," + "\"" + "EraserWidth" + "\"" + ":" + node.EraserWidth + "," + "\"" + "TouchEvent" + "\"" + ":" + node.TouchEvent + "," + "\"" + "IsPaint" + "\"" + ":" + "\"" + node.IsPaint + "\"" + "," + "\"" + "time" + "\"" + ":" + node.time + "},"; } json = json.substring(0, json.length() - 1); json += "]"; try { json = enCrypto(json, "lfk_dsk@hotmail.com"); } catch (InvalidKeySpecException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchPaddingException e) { e.printStackTrace(); } SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); Date now = new Date(); File tempfile = new File(file + "/" + formatter.format(now) + ".lfk"); try { FileOutputStream fileOutputStream = new FileOutputStream(tempfile); byte[] bytes = json.getBytes(); fileOutputStream.write(bytes); fileOutputStream.close(); showCustomToast(tempfile.getName() + "已保存"); } catch (IOException e) { e.printStackTrace(); } } private Bitmap toConformBitmap(Bitmap background, Bitmap foreground) { if (background == null) { return null; } int bgWidth = background.getWidth(); int bgHeight = background.getHeight(); Bitmap bitmap = Bitmap.createBitmap(bgWidth, bgHeight, Bitmap.Config.ARGB_8888); Canvas cv = new Canvas(bitmap); cv.drawBitmap(background, 0, 0, null);//在 0,0坐标开始画入bg cv.drawBitmap(foreground, 0, 0, null);//在 0,0坐标开始画入fg ,可以从任意位置画入 cv.save(Canvas.ALL_SAVE_FLAG);//保存 cv.restore();//存储 return bitmap; } public void clearReUnList() { ReDoNodes.clear(); mBitmapInit = null; } public void JsonToPathNodeToHandle(Uri uri) { Message message = new Message(); message.obj = uri.getPath(); message.what = CHOOSEPATH; handler.sendMessage(message); } /** * @param file the file of .lfk * @author lfk_dsk@hotmail.com */ private void JsonToPathNode(String file) { String res = ""; ArrayList<PathNode.Node> arrayList = new ArrayList<>(); try { Log.e("绝对路径", file); FileInputStream in = new FileInputStream(file); ByteArrayOutputStream bufferOut = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; for (int i = in.read(buffer, 0, buffer.length); i > 0; i = in.read(buffer, 0, buffer.length)) { bufferOut.write(buffer, 0, i); } res = new String(bufferOut.toByteArray(), Charset.forName("utf-8")); } catch (IOException e) { e.printStackTrace(); } try { res = deCrypto(res, "lfk_dsk@hotmail.com"); } catch (InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchPaddingException | InvalidKeySpecException e) { e.printStackTrace(); } try { JSONArray jsonArray = new JSONArray(res); for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonObject = new JSONObject(jsonArray.getString(i)); PathNode.Node node = new PathNode().NewAnode(); // dp node.x = jsonObject.getInt("x"); node.y = jsonObject.getInt("y"); node.TouchEvent = jsonObject.getInt("TouchEvent"); node.PenWidth = jsonObject.getInt("PenWidth"); node.PenColor = jsonObject.getInt("PenColor"); node.EraserWidth = jsonObject.getInt("EraserWidth"); node.IsPaint = jsonObject.getBoolean("IsPaint"); node.time = jsonObject.getLong("time"); arrayList.add(node); } } catch (JSONException e) { e.printStackTrace(); } pathNode.setPathList(arrayList); } public int px2dip(float pxValue) { final float scale = this.getResources().getDisplayMetrics().density; return (int) (pxValue / scale + 0.5f); } public int dip2px(float dpValue) { final float scale = this.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } @Override public boolean onTouchEvent(MotionEvent event) { float l = event.getPressure() * 500; Log.e("笔刷值", l * 500 + ""); if (event.getPressure() - l > 28431) { l = l + 10000; } else if (event.getPressure() - l < -28431) { l = l - 10000; } drawBase.setmPaintWidth((float) Math.sqrt(l)); if (!isShowing()) { float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: drawBase.Touch_Down(x, y); invalidate(); break; case MotionEvent.ACTION_MOVE: drawBase.Touch_Move(x, y); invalidate(); break; case MotionEvent.ACTION_UP: if (IsPaint) { drawBase.Touch_Up(); } else { drawBase.Touch_Up(); } invalidate(); break; } } return true; } // public void preview(ArrayList<PathNode.Node> arrayList) { // IsRecordPath = false; // PreviewThread previewThread = new PreviewThread(this, arrayList); // Thread thread = new Thread(previewThread); // thread.start(); // } private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case INDIVIDE: ((View) msg.obj).invalidate(); break; case CHOOSEPATH: JsonToPathNode(msg.obj.toString()); break; } super.handleMessage(msg); } }; public void showCustomToast(String toast) { LayoutInflater inflater = LayoutInflater.from(context); View view = inflater.inflate(R.layout.toast_item, (ViewGroup) findViewById(R.id.toast_item)); TextView text = (TextView) view.findViewById(R.id.toast_text); text.setText(toast); Toast tempToast = new Toast(context); tempToast.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER, 0, 0); tempToast.setDuration(Toast.LENGTH_SHORT); tempToast.setView(view); tempToast.show(); } // class PreviewThread implements Runnable{ // private long time; // private ArrayList<PathNode.Node> nodes; // private View view; // public PreviewThread(View view, ArrayList<PathNode.Node> arrayList) { // this.view = view; // this.nodes = arrayList; // } // public void run() { // time = 0; // IsShowing = true; // clean(); // if(mBitmapInit != null){ // drawBitmapToCanvas(mBitmapInit); // } // for(int i = 0 ;i < nodes.size();i++) { // PathNode.Node node = nodes.get(i); // float x = dip2px(node.x); // float y = dip2px(node.y); // Log.e("pre"+x,"pre"+y); // if(i < nodes.size() - 1) { // time = nodes.get(i+1).time - node.time; // } // IsPaint = node.IsPaint; // if(node.IsPaint){ // UserInfo.PaintColor = node.PenColor; // UserInfo.PaintWidth = node.PenWidth; // Init_Paint(node.PenColor,node.PenWidth); // }else { // UserInfo.EraserWidth = node.EraserWidth; // Init_Eraser(node.EraserWidth); // } // switch (node.TouchEvent) { // case MotionEvent.ACTION_DOWN: // Touch_Down(x,y); // break; // case MotionEvent.ACTION_MOVE: // Touch_Move(x,y); // break; // case MotionEvent.ACTION_UP: // if(node.IsPaint){ // Touch_Up(mPaint); // }else { // Touch_Up(mEraserPaint); // } // break; // } // Message msg = new Message(); // msg.obj = view; // msg.what = INDIVIDE; // handler.sendMessage(msg); // if(!ReDoOrUnDoFlag) { // try { // Thread.sleep(time); // } catch (InterruptedException e) { // e.printStackTrace(); // } // } // } // ReDoOrUnDoFlag = false; // IsShowing = false; // IsRecordPath = true; // } // } /** * 加密(使用DES算法) * * @param txt 需要加密的文本 * @param key 密钥 * @return 成功加密的文本 * @throws InvalidKeySpecException * @throws InvalidKeyException * @throws NoSuchPaddingException * @throws IllegalBlockSizeException * @throws BadPaddingException */ private static String enCrypto(String txt, String key) throws InvalidKeySpecException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException { StringBuffer sb = new StringBuffer(); DESKeySpec desKeySpec = new DESKeySpec(key.getBytes()); SecretKeyFactory skeyFactory = null; Cipher cipher = null; try { skeyFactory = SecretKeyFactory.getInstance("DES"); cipher = Cipher.getInstance("DES"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } SecretKey deskey = skeyFactory != null ? skeyFactory.generateSecret(desKeySpec) : null; if (cipher != null) { cipher.init(Cipher.ENCRYPT_MODE, deskey); } byte[] cipherText = cipher != null ? cipher.doFinal(txt.getBytes()) : new byte[0]; for (int n = 0; n < cipherText.length; n++) { String stmp = (Integer.toHexString(cipherText[n] & 0XFF)); if (stmp.length() == 1) { sb.append("0" + stmp); } else { sb.append(stmp); } } return sb.toString().toUpperCase(); } /** * 解密(使用DES算法) * * @param txt 需要解密的文本 * @param key 密钥 * @return 成功解密的文本 * @throws InvalidKeyException * @throws InvalidKeySpecException * @throws NoSuchPaddingException * @throws IllegalBlockSizeException * @throws BadPaddingException */ private static String deCrypto(String txt, String key) throws InvalidKeyException, InvalidKeySpecException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException { DESKeySpec desKeySpec = new DESKeySpec(key.getBytes()); SecretKeyFactory skeyFactory = null; Cipher cipher = null; try { skeyFactory = SecretKeyFactory.getInstance("DES"); cipher = Cipher.getInstance("DES"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } SecretKey deskey = skeyFactory != null ? skeyFactory.generateSecret(desKeySpec) : null; if (cipher != null) { cipher.init(Cipher.DECRYPT_MODE, deskey); } byte[] btxts = new byte[txt.length() / 2]; for (int i = 0, count = txt.length(); i < count; i += 2) { btxts[i / 2] = (byte) Integer.parseInt(txt.substring(i, i + 2), 16); } return (new String(cipher.doFinal(btxts))); } public void ReDoORUndo(boolean flag) { if (!IsShowing) { ReDoOrUnDoFlag = true; try { if (flag) { Log.e("redo", ""); ReDoNodes.add(pathNode.getTheLastNote()); pathNode.deleteTheLastNote(); // preview(pathNode.getPathList()); invalidate(); // ReDoOrUnDoFlag = true; // if(!isShowing()) // preview(pathNode.getPathList()); } else { Log.e("undo", ""); pathNode.addNode(ReDoNodes.get(ReDoNodes.size() - 1)); ReDoNodes.remove(ReDoNodes.size() - 1); // preview(pathNode.getPathList()); // ReDoOrUnDoFlag = true; // if(!isShowing()) // preview(pathNode.getPathList()); } } catch (ArrayIndexOutOfBoundsException e) { e.printStackTrace(); showCustomToast("无法操作=-="); } } } public void setDrawBase(DrawBase drawBase) { this.drawBase = drawBase; } public void setDrawBase(mode data) { switch (data) { case PATH: setDrawBase(new DrawPath(mCanvas)); break; case RECT: setDrawBase(new DrawRect(mCanvas)); break; case LINE: setDrawBase(new DrawLine(mCanvas)); break; case CIRCLE: setDrawBase(new DrawCircle(mCanvas)); break; } } }