/*
* Copyright (C) 2014 Steelkiwi Development, Julia Zudikova
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.skd.sketchview;
import java.util.ArrayList;
import java.util.HashMap;
import android.content.Context;
import android.gesture.Gesture;
import android.gesture.GestureOverlayView;
import android.gesture.GestureOverlayView.OnGestureListener;
import android.gesture.GestureOverlayView.OnGesturePerformedListener;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Pair;
import android.view.MotionEvent;
import android.view.View;
/*
* SketchCanvas is a canvas for GestureOverlayView - all gestures paths drawn by user remain on this canvas.
*/
public class SketchCanvas extends View implements OnGestureListener, OnGesturePerformedListener {
private int canvasW, canvasH;
private Rect bitmapRect, canvasRect;
private Paint defaultPaint, bgPaint;
private HashMap<Pair<Integer, Integer>, Paint> brushes;
private ArrayList<Pair<Path, Paint>> pathes;
private Bitmap bgBitmap;
public SketchCanvas(Context context) {
super(context);
createDefaultPaint();
createBgPaint();
}
public SketchCanvas(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SketchCanvas(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
createDefaultPaint();
createBgPaint();
}
private void createDefaultPaint() {
defaultPaint = new Paint();
defaultPaint.setAntiAlias(true);
defaultPaint.setDither(false);
defaultPaint.setColor(Color.BLACK);
defaultPaint.setStyle(Paint.Style.STROKE);
defaultPaint.setStrokeJoin(Paint.Join.ROUND);
defaultPaint.setStrokeCap(Paint.Cap.ROUND);
defaultPaint.setStrokeWidth(8);
}
private void createBgPaint() {
bgPaint = new Paint();
bgPaint.setAntiAlias(true);
bgPaint.setDither(false);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
this.canvasW = w;
this.canvasH = h;
this.canvasRect = new Rect(0, 0, canvasW, canvasH);
this.bitmapRect = new Rect();
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
protected void onDraw(Canvas canvas) {
setBackgroundColor(Color.WHITE);
if (bgBitmap != null) {
canvas.drawBitmap(bgBitmap, bitmapRect, canvasRect, bgPaint);
}
if (pathes == null) {
return;
}
for (int i = 0, len = pathes.size(); i < len; i++) {
canvas.drawPath(pathes.get(i).first, pathes.get(i).second);
}
}
@Override
public void onGestureStarted(GestureOverlayView overlay, MotionEvent event) {
}
@Override
public void onGesture(GestureOverlayView overlay, MotionEvent event) {
}
@Override
public void onGestureEnded(GestureOverlayView overlay, MotionEvent event) {
int color = overlay.getGestureColor();
int size = (int) overlay.getGestureStrokeWidth();
Paint paint = getBrushByColorAndSize(color, size);
Path path = overlay.getGesture().toPath();
addPath(path, paint);
this.invalidate();
}
@Override
public void onGestureCancelled(GestureOverlayView overlay, MotionEvent event) {
}
@Override
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
}
public void setBrushes(HashMap<Pair<Integer, Integer>, Paint> brushes) {
this.brushes = brushes;
}
private Paint getBrushByColorAndSize(int color, int size) {
Paint paint = brushes.get(new Pair<Integer, Integer>(color, size));
if (paint != null) {
return paint;
}
return defaultPaint;
}
private void addPath(Path path, Paint paint) {
if (pathes == null) {
pathes = new ArrayList<Pair<Path, Paint>>();
}
pathes.add(new Pair<Path, Paint>(path, paint));
}
public boolean removeLastPath() {
if (pathes == null || pathes.size() <= 0) {
return true;
}
pathes.remove(pathes.size() - 1);
this.invalidate();
return false;
}
public void setAsBackground(Bitmap bitmap) {
if (bgBitmap != null) {
bgBitmap.recycle();
}
bgBitmap = bitmap;
int minW = Math.min(canvasW, bitmap.getWidth());
int maxW = Math.max(canvasW, bitmap.getWidth());
int minH = Math.min(canvasH, bitmap.getHeight());
int maxH = Math.max(canvasH, bitmap.getHeight());
int bmX = (maxW == bitmap.getWidth()) ? (maxW - minW) / 2 : 0;
int bmY = (maxH == bitmap.getHeight()) ? (maxH - minH) / 2 : 0;
bitmapRect.set(bmX, bmY, bmX + minW, bmY + minH);
this.invalidate();
}
public Bitmap getBitmap() {
this.setDrawingCacheEnabled(true);
this.buildDrawingCache();
Bitmap bmp = Bitmap.createBitmap(this.getDrawingCache());
this.setDrawingCacheEnabled(false);
return bmp;
}
}