blob: d3960493950d0aa589126f8e8562a804088863f5 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* 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.android.gallery3d.photoeditor.actions;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
/**
* A view that tracks touch motions as paths and paints them as doodles.
*/
class DoodleView extends FullscreenToolView {
/**
* Listener of doodle paths.
*/
public interface OnDoodleChangeListener {
void onDoodleChanged(Doodle doodle);
void onDoodleFinished(Doodle doodle);
}
private final Paint bitmapPaint = new Paint(Paint.DITHER_FLAG);
private final Paint doodlePaint = Doodle.createPaint();
private final PointF lastPoint = new PointF();
private final Path drawingPath = new Path();
private final Matrix drawingMatrix = new Matrix();
private final Matrix displayMatrix = new Matrix();
private Bitmap bitmap;
private Canvas bitmapCanvas;
private Doodle doodle;
private int color;
private OnDoodleChangeListener listener;
public DoodleView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setOnDoodleChangeListener(OnDoodleChangeListener listener) {
this.listener = listener;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
RectF r = new RectF(0, 0, getPhotoWidth(), getPhotoHeight());
if ((bitmap == null) && !r.isEmpty()) {
bitmap = Bitmap.createBitmap((int) r.width(), (int) r.height(),
Bitmap.Config.ARGB_8888);
bitmapCanvas = new Canvas(bitmap);
// Set up a matrix that maps back normalized paths to be drawn on the bitmap or canvas.
drawingMatrix.setRectToRect(new RectF(0, 0, 1, 1), r, Matrix.ScaleToFit.FILL);
}
displayMatrix.setRectToRect(r, displayBounds, Matrix.ScaleToFit.FILL);
}
private void drawDoodle(Canvas canvas) {
if ((canvas != null) && (doodle != null)) {
doodlePaint.setColor(doodle.getColor());
doodle.getDrawingPath(drawingMatrix, drawingPath);
canvas.drawPath(drawingPath, doodlePaint);
}
}
public void setColor(int color) {
// Restart doodle to draw in a new color.
this.color = color;
finishDoodle();
startDoodle();
}
private void startDoodle() {
doodle = new Doodle(color, new PointF(lastPoint.x, lastPoint.y));
}
private void finishDoodle() {
if ((doodle != null) && !doodle.isEmpty()) {
// Update the finished non-empty doodle to the bitmap.
drawDoodle(bitmapCanvas);
if (listener != null) {
listener.onDoodleFinished(doodle);
}
invalidate();
}
doodle = null;
}
private void addLastPointIntoDoodle() {
if (doodle != null) {
doodle.addControlPoint(new PointF(lastPoint.x, lastPoint.y));
if (listener != null) {
listener.onDoodleChanged(doodle);
}
invalidate();
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
if (isEnabled()) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mapPhotoPoint(x, y, lastPoint);
startDoodle();
break;
case MotionEvent.ACTION_MOVE:
mapPhotoPoint(x, y, lastPoint);
addLastPointIntoDoodle();
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
// Line to last position with offset to draw at least dots for single clicks.
mapPhotoPoint(x + 1, y + 1, lastPoint);
addLastPointIntoDoodle();
finishDoodle();
break;
}
}
return true;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.clipRect(displayBounds);
canvas.concat(displayMatrix);
if (bitmap != null) {
canvas.drawBitmap(bitmap, 0, 0, bitmapPaint);
}
drawDoodle(canvas);
canvas.restore();
}
}