package edu.purdue.pivot.skwiki.client.sketch; import edu.purdue.pivot.skwiki.shared.CanvasPack; import edu.purdue.pivot.skwiki.shared.DataPack; import edu.purdue.pivot.skwiki.shared.history.AbstractHistory; import edu.purdue.pivot.skwiki.shared.history.AddHistory; import edu.purdue.pivot.skwiki.shared.history.HistoryManager; import edu.purdue.pivot.skwiki.shared.history.MyColor; import edu.purdue.pivot.skwiki.shared.history.PathHeadHistory; import edu.purdue.pivot.skwiki.shared.history.Point; import edu.purdue.pivot.skwiki.shared.history.RemoveHistory; import gwt.g2d.client.graphics.KnownColor; import gwt.g2d.client.graphics.Surface; import gwt.g2d.shared.Color; import gwt.g2d.shared.math.Rectangle; import gwt.g2d.shared.math.Vector2; import java.util.ArrayList; import java.util.Date; import java.util.logging.Level; import java.util.logging.Logger; import com.google.gwt.canvas.dom.client.Context2d; import com.google.gwt.canvas.dom.client.Context2d.LineCap; import com.google.gwt.canvas.dom.client.Context2d.LineJoin; import com.google.gwt.dom.client.Style.Cursor; import com.google.gwt.event.dom.client.FocusEvent; import com.google.gwt.event.dom.client.FocusHandler; import com.google.gwt.event.dom.client.MouseDownEvent; import com.google.gwt.event.dom.client.MouseDownHandler; import com.google.gwt.event.dom.client.MouseMoveEvent; import com.google.gwt.event.dom.client.MouseMoveHandler; import com.google.gwt.event.dom.client.MouseUpEvent; import com.google.gwt.event.dom.client.MouseUpHandler; import com.google.gwt.event.dom.client.TouchEndEvent; import com.google.gwt.event.dom.client.TouchEndHandler; import com.google.gwt.event.dom.client.TouchMoveEvent; import com.google.gwt.event.dom.client.TouchMoveHandler; import com.google.gwt.event.dom.client.TouchStartEvent; import com.google.gwt.event.dom.client.TouchStartHandler; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.SimplePanel; import com.mogaleaf.client.common.widgets.ColorHandler; import com.mogaleaf.client.common.widgets.SimpleColorPicker; import com.smartgwt.client.widgets.Slider; import com.smartgwt.client.widgets.events.CloseClickEvent; import com.smartgwt.client.widgets.events.ValueChangedEvent; import com.smartgwt.client.widgets.events.ValueChangedHandler; public class TouchPad extends Surface implements AttachedPanel { CanvasToolbar toolbar; TouchPad surface = this; /* history stack */ private HistoryManager myHistoryManager; private HistoryManager myHistoryManagerRedoStack; Boolean inFocus = false; static int WIDTH = 1100; static int HEIGHT = 630; /* strokeSize, currentColor, and eraserSize */ private int strokeSize = 2; private Color currentColor = KnownColor.BLACK; private int eraserSize = 5; Date lastTime = new Date(); public final static long SECOND_MILLIS = 1000; public final static long MINUTE_MILLIS = SECOND_MILLIS * 60; double totalSampling = 0; // /* slider for strokeSize */ // Slider hSlider = new Slider("Stroke Size"); // HorizontalPanel sliderPanel = new HorizontalPanel(); //Logger logger = Logger.getLogger("Skwiki"); // com.smartgwt.client.widgets.Window colorWin = new com.smartgwt.client.widgets.Window(); // com.smartgwt.client.widgets.Window sliderWin = new com.smartgwt.client.widgets.Window(); int left; int top; int right; int bottom; int windowWidth; int windowHeight; /* canvas identifiers */ String uuid; String uid; /* variables to store previous x and y */ double oldx = -1; double oldy = -1; double prevx = -1; double prevy = -1; /* indexes of touch start events */ ArrayList<Integer> indexes = new ArrayList<Integer>(); ArrayList<Integer> strokeSizes = new ArrayList<Integer>(); ArrayList<MyColor> colorCache = new ArrayList<MyColor>(); ArrayList<Vector2> cache = new ArrayList<Vector2>(); //private ArrayList<CanvasToolbar> toolbars; Boolean leftMouseDown = false; /* buffer 4 points before drawing a curve */ Vector2 p0 = new Vector2(); Vector2 p1 = new Vector2(); Vector2 p2 = new Vector2(); Vector2 p3 = new Vector2(); int strokePointCount = 0; int bufferCount = 3; ArrayList<Vector2> buffList = new ArrayList<Vector2>(); /* context2d */ Context2d canvas_context; /* Boolean to check if the sketch is a preview */ Boolean preview = false; public TouchPad(String uuid, String uid, float scaleWidth, float scaleHeight, int windowWidth, int windowHeight) { super((int) (5 * windowWidth * scaleWidth / 6), (int) (5 * windowHeight / 6 * scaleHeight)); WIDTH = (int) (5 * windowWidth / 6 * scaleWidth); HEIGHT = (int) (5 * windowHeight / 6 * scaleHeight); this.windowWidth = windowWidth; this.windowHeight = windowHeight; this.uuid = uuid; this.uid = uid; this.fillBackground(KnownColor.TRANSPARENT); myHistoryManager = new HistoryManager(this); myHistoryManagerRedoStack = new HistoryManager(this); canvas_context = this.getContext(); preview = true; } public static int minutesDiff(Date earlierDate, Date laterDate) { if (earlierDate == null || laterDate == null) return 0; return (int) ((laterDate.getTime() / MINUTE_MILLIS) - (earlierDate .getTime() / MINUTE_MILLIS)); } public TouchPad(String uuid, String uid, ArrayList<CanvasToolbar> toolbars2, int windowWidth, int windowHeight) { super(windowWidth / 2, windowHeight / 2); WIDTH = windowWidth / 2; HEIGHT = windowHeight / 2; erase = false; this.uuid = uuid; this.uid = uid; this.windowWidth = windowWidth; this.windowHeight = windowHeight; this.fillBackground(KnownColor.TRANSPARENT); myHistoryManager = new HistoryManager(this); myHistoryManagerRedoStack = new HistoryManager(this); left = this.getAbsoluteLeft(); top = this.getAbsoluteTop(); right = left + WIDTH; bottom = top + HEIGHT; toolbar = CanvasToolbar.getInstance(); toolbar.addTouchPad(this); canvas_context = this.getContext(); /* add focus handler that works now */ this.addFocusHandler(new FocusHandler() { @Override public void onFocus(FocusEvent event) { toolbar.setFocus(); inFocus = true; } }); inFocus = true; /* needs a mouse handler for M.S. Surface */ this.addMouseDownHandler(new MouseDownHandler() { @Override public void onMouseDown(MouseDownEvent event) { myHistoryManagerRedoStack.clearHistory(); leftMouseDown = true; if (erase == true) { } else { surface.getElement().getStyle().setCursor(Cursor.CROSSHAIR); lastTime = new Date(); int x = event.getX(); int y = event.getY(); oldx = x; oldy = y; prevx = x; prevy = y; PathHeadHistory aPathHeadHistory = new PathHeadHistory( new Point(x, y), strokeSize, currentColor); myHistoryManager.addHistory(aPathHeadHistory); /* touch start */ if (strokePointCount == 0) { p1.x = x; p1.y = y; p2.x = x; p2.y = y; strokePointCount++; strokePointCount++; canvas_context.setStrokeStyle(currentColor.getColorCode()); canvas_context.setFillStyle(currentColor.getColorCode()); canvas_context .setLineWidth(((double) strokeSize) * 0.4); canvas_context.beginPath(); canvas_context.arc(x, y, ((double) strokeSize) * 0.4, 0, 2 * Math.PI); canvas_context.fill(); indexes.add(cache.size()); cache.add(new Vector2(x, y)); strokeSizes.add(strokeSize); colorCache.add(new MyColor(currentColor.getR(), currentColor.getG(), currentColor.getB())); } } event.preventDefault(); event.stopPropagation(); } }); this.addTouchStartHandler(new TouchStartHandler() { @Override public void onTouchStart(TouchStartEvent event) { myHistoryManagerRedoStack.clearHistory(); leftMouseDown = true; if (erase == true) { } else { surface.getElement().getStyle().setCursor(Cursor.CROSSHAIR); lastTime = new Date(); int x = event.getTouches().get(0).getPageX() - surface.getAbsoluteLeft(); int y = event.getTouches().get(0).getPageY() - surface.getAbsoluteTop(); oldx = x; oldy = y; prevx = x; prevy = y; PathHeadHistory aPathHeadHistory = new PathHeadHistory( new Point(x, y), strokeSize, currentColor); myHistoryManager.addHistory(aPathHeadHistory); /* touch start */ if (strokePointCount == 0) { p1.x = x; p1.y = y; p2.x = x; p2.y = y; strokePointCount++; strokePointCount++; canvas_context.setStrokeStyle(currentColor.getColorCode()); canvas_context.setFillStyle(currentColor.getColorCode()); canvas_context .setLineWidth(((double) strokeSize) * 0.4); canvas_context.beginPath(); canvas_context.arc(x, y, ((double) strokeSize) * 0.4, 0, 2 * Math.PI); canvas_context.fill(); indexes.add(cache.size()); cache.add(new Vector2(x, y)); strokeSizes.add(strokeSize); colorCache.add(new MyColor(currentColor.getR(), currentColor.getG(), currentColor.getB())); } } event.preventDefault(); event.stopPropagation(); } }); /* mouse move handler */ this.addMouseMoveHandler(new MouseMoveHandler() { @Override public void onMouseMove(MouseMoveEvent event) { double x = event.getX(); double y = event.getY(); if (erase && leftMouseDown) { eraserSize = 20; Rectangle rectangle = new Rectangle(x, y, eraserSize, +eraserSize); surface.save().setFillStyle(KnownColor.WHITE) .fillRectangle(rectangle); RemoveHistory aRemoveHistory = new RemoveHistory(new Point( (int) x, (int) y), eraserSize); myHistoryManager.addHistory(aRemoveHistory); } else if (leftMouseDown) { Date currentTime = new Date(); double distance2 = Math.sqrt(Math.pow(x - prevx, 2) + Math.pow(y - prevy, 2)); double samplingSpeed = distance2/((double)minutesDiff(lastTime, currentTime)); //logger.log(Level.SEVERE, "time "+(double)minutesDiff(lastTime, currentTime)); //logger.log(Level.SEVERE, "Sampling speed "+distance2); //totalSampling = (myHistoryManager.historys.size()*totalSampling + samplingSpeed)/((double)myHistoryManager.historys.size()+1.0); //logger.log(Level.SEVERE, "Sampling speed "+totalSampling); AddHistory addHistory = new AddHistory(new Point((int) x, (int) y), new Point((int) x, (int) y), strokeSize, currentColor); myHistoryManager.addHistory(addHistory); if (strokePointCount == 2) { canvas_context.setLineCap(LineCap.ROUND); canvas_context.setLineJoin(LineJoin.ROUND); if (currentColor != KnownColor.WHITE) { /* set stroke color and shadow */ canvas_context.setStrokeStyle(currentColor .getColorCode()); canvas_context.setFillStyle(currentColor.getColorCode()); canvas_context .setLineWidth(((double) strokeSize) * 0.5); canvas_context .setShadowBlur(((double) strokeSize) * 0.3); canvas_context.setShadowColor(currentColor .getColorCode()); } else { /* set stroke color and shadow */ canvas_context.setStrokeStyle(currentColor.getColorCode()); canvas_context.setFillStyle(currentColor.getColorCode()); canvas_context.setLineWidth(((double) strokeSize)); canvas_context .setShadowBlur(0); } /* latest touch point */ p3.x = x; p3.y = y; p0.x = p1.x + (p1.x - p2.x); p0.y = p1.y + (p1.y - p2.y); strokePointCount++; /* buffer list */ get_buffer(p0, p1, p2, p3, bufferCount); bufferCount = buffList.size(); oldx = (int) buffList.get(0).x; oldy = (int) buffList.get(0).y; canvas_context.beginPath(); canvas_context.moveTo(oldx, oldy); cache.add(new Vector2(oldx, oldy)); /* * draw all interpolated points found through Hermite * interpolation */ int i = 0; for (i = 1; i < bufferCount - 2; i++) { x = buffList.get(i).x; y = buffList.get(i).y; cache.add(new Vector2(x, y)); double nextx = buffList.get(i + 1).x; double nexty = buffList.get(i + 1).y; double c = (x + nextx) / 2; double d = (y + nexty) / 2; canvas_context.quadraticCurveTo(x, y, c, d); } x = buffList.get(i).x; y = buffList.get(i).y; cache.add(new Vector2(x, y)); double nextx = buffList.get(i + 1).x; double nexty = buffList.get(i + 1).y; cache.add(new Vector2(nextx, nexty)); canvas_context.quadraticCurveTo(x, y, nextx, nexty); /* adaptive buffering! based on distance between points */ int distance = (int) Math.sqrt(Math.pow(x - p2.x, 2) + Math.pow(y - p2.y, 2)); bufferCount = ((int) distance / 10) > 6 ? 6 : 3; bufferCount = bufferCount < 10 ? bufferCount : 10; // logger.log(Level.SEVERE, "bufferCount "+ // bufferCount); } else { /* update the touch point list */ p0.x = p1.x; p0.y = p1.y; p1.x = p2.x; p1.y = p2.y; p2.x = p3.x; p2.y = p3.y; p3.x = x; p3.y = y; get_buffer(p0, p1, p2, p3, bufferCount); /* * draw all interpolated points found through Hermite * interpolation */ bufferCount = buffList.size(); int i = 1; for (i = 1; i < bufferCount - 2; i++) { x = buffList.get(i).x; y = buffList.get(i).y; cache.add(new Vector2(x, y)); double nextx = buffList.get(i + 1).x; double nexty = buffList.get(i + 1).y; double c = (x + nextx) / 2; double d = (y + nexty) / 2; canvas_context.quadraticCurveTo(x, y, c, d); } x = buffList.get(i).x; y = buffList.get(i).y; cache.add(new Vector2(x, y)); double nextx = buffList.get(i + 1).x; double nexty = buffList.get(i + 1).y; cache.add(new Vector2(nextx, nexty)); canvas_context.quadraticCurveTo(x, y, nextx, nexty); canvas_context.stroke(); surface.restore(); /* adaptive buffering using Hermite interpolation */ int distance = (int) Math.sqrt(Math.pow(x - p2.x, 2) + Math.pow(y - p2.y, 2)); bufferCount = ((int) distance / 10) > 6 ? 6 : 3; bufferCount = bufferCount < 10 ? bufferCount : 10; // logger.log(Level.SEVERE, "bufferCount "+ // bufferCount); } } event.preventDefault(); event.stopPropagation(); } }); /* touch move handler */ this.addTouchMoveHandler(new TouchMoveHandler() { @Override public void onTouchMove(TouchMoveEvent event) { double x = event.getTouches().get(0).getPageX() - surface.getAbsoluteLeft(); double y = event.getTouches().get(0).getPageY() - surface.getAbsoluteTop(); if (erase && leftMouseDown) { eraserSize = 20; Rectangle rectangle = new Rectangle(x, y, eraserSize, +eraserSize); surface.save().setFillStyle(KnownColor.WHITE) .fillRectangle(rectangle); RemoveHistory aRemoveHistory = new RemoveHistory(new Point( (int) x, (int) y), eraserSize); myHistoryManager.addHistory(aRemoveHistory); } else if (leftMouseDown) { Date currentTime = new Date(); double distance2 = Math.sqrt(Math.pow(x - prevx, 2) + Math.pow(y - prevy, 2)); double samplingSpeed = distance2/((double)minutesDiff(lastTime, currentTime)); //logger.log(Level.SEVERE, "time "+(double)minutesDiff(lastTime, currentTime)); //logger.log(Level.SEVERE, "Sampling speed "+distance2); //totalSampling = (myHistoryManager.historys.size()*totalSampling + samplingSpeed)/((double)myHistoryManager.historys.size()+1.0); //logger.log(Level.SEVERE, "Sampling speed "+totalSampling); AddHistory addHistory = new AddHistory(new Point((int) x, (int) y), new Point((int) x, (int) y), strokeSize, currentColor); myHistoryManager.addHistory(addHistory); if (strokePointCount == 2) { canvas_context.setLineCap(LineCap.ROUND); canvas_context.setLineJoin(LineJoin.ROUND); if (currentColor != KnownColor.WHITE) { /* set stroke color and shadow */ canvas_context.setStrokeStyle(currentColor .getColorCode()); canvas_context.setFillStyle(currentColor.getColorCode()); canvas_context .setLineWidth(((double) strokeSize) * 0.5); canvas_context .setShadowBlur(((double) strokeSize) * 0.3); canvas_context.setShadowColor(currentColor .getColorCode()); } else { /* set stroke color and shadow */ canvas_context.setStrokeStyle(currentColor.getColorCode()); canvas_context.setFillStyle(currentColor.getColorCode()); canvas_context.setLineWidth(((double) strokeSize)); canvas_context .setShadowBlur(0); } /* latest touch point */ p3.x = x; p3.y = y; p0.x = p1.x + (p1.x - p2.x); p0.y = p1.y + (p1.y - p2.y); strokePointCount++; /* buffer list */ get_buffer(p0, p1, p2, p3, bufferCount); bufferCount = buffList.size(); oldx = (int) buffList.get(0).x; oldy = (int) buffList.get(0).y; canvas_context.beginPath(); canvas_context.moveTo(oldx, oldy); cache.add(new Vector2(oldx, oldy)); /* * draw all interpolated points found through Hermite * interpolation */ int i = 0; for (i = 1; i < bufferCount - 2; i++) { x = buffList.get(i).x; y = buffList.get(i).y; cache.add(new Vector2(x, y)); double nextx = buffList.get(i + 1).x; double nexty = buffList.get(i + 1).y; double c = (x + nextx) / 2; double d = (y + nexty) / 2; canvas_context.quadraticCurveTo(x, y, c, d); } x = buffList.get(i).x; y = buffList.get(i).y; cache.add(new Vector2(x, y)); double nextx = buffList.get(i + 1).x; double nexty = buffList.get(i + 1).y; cache.add(new Vector2(nextx, nexty)); canvas_context.quadraticCurveTo(x, y, nextx, nexty); /* adaptive buffering! based on distance between points */ int distance = (int) Math.sqrt(Math.pow(x - p2.x, 2) + Math.pow(y - p2.y, 2)); bufferCount = ((int) distance / 10) > 6 ? 6 : 3; bufferCount = bufferCount < 10 ? bufferCount : 10; // logger.log(Level.SEVERE, "bufferCount "+ // bufferCount); } else { /* update the touch point list */ p0.x = p1.x; p0.y = p1.y; p1.x = p2.x; p1.y = p2.y; p2.x = p3.x; p2.y = p3.y; p3.x = x; p3.y = y; get_buffer(p0, p1, p2, p3, bufferCount); /* * draw all interpolated points found through Hermite * interpolation */ bufferCount = buffList.size(); int i = 1; for (i = 1; i < bufferCount - 2; i++) { x = buffList.get(i).x; y = buffList.get(i).y; cache.add(new Vector2(x, y)); double nextx = buffList.get(i + 1).x; double nexty = buffList.get(i + 1).y; double c = (x + nextx) / 2; double d = (y + nexty) / 2; canvas_context.quadraticCurveTo(x, y, c, d); } x = buffList.get(i).x; y = buffList.get(i).y; cache.add(new Vector2(x, y)); double nextx = buffList.get(i + 1).x; double nexty = buffList.get(i + 1).y; cache.add(new Vector2(nextx, nexty)); canvas_context.quadraticCurveTo(x, y, nextx, nexty); canvas_context.stroke(); surface.restore(); /* adaptive buffering using Hermite interpolation */ int distance = (int) Math.sqrt(Math.pow(x - p2.x, 2) + Math.pow(y - p2.y, 2)); bufferCount = ((int) distance / 10) > 6 ? 6 : 3; bufferCount = bufferCount < 10 ? bufferCount : 10; // logger.log(Level.SEVERE, "bufferCount "+ // bufferCount); } } event.preventDefault(); event.stopPropagation(); } }); this.addTouchEndHandler(new TouchEndHandler() { @Override public void onTouchEnd(TouchEndEvent event) { leftMouseDown = false; event.preventDefault(); surface.setStyleName("gwt-TouchPanelWidget"); if (erase == true) { } else { surface.getElement().getStyle().setCursor(Cursor.DEFAULT); } event.stopPropagation(); // erase = false; strokePointCount = 0; bufferCount = 3; } }); this.addMouseUpHandler(new MouseUpHandler() { @Override public void onMouseUp(MouseUpEvent event) { leftMouseDown = false; event.preventDefault(); surface.setStyleName("gwt-TouchPanelWidget"); if (erase == true) { } else { surface.getElement().getStyle().setCursor(Cursor.DEFAULT); } event.stopPropagation(); // erase = false; strokePointCount = 0; bufferCount = 3; } }); } /* Cubic Hermite interpolation */ private void get_buffer(Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3, int bufferCount) { buffList.clear(); double steps = 0; double step = 0.0; double t = 0.0; double tt = 0.0; double ttt = 0.0; double p0x = p0.x; double p1x = p1.x; double p2x = p2.x; double p3x = p3.x; double p0y = p0.y; double p1y = p1.y; double p2y = p2.y; double p3y = p3.y; int ipps = bufferCount; int i = 0; steps = ipps - 1; if (steps > 0) { step = 1.0 / steps; buffList.add(new Vector2(p1.x, p1.y)); for (i = 1; i < steps; ++i) { t += step; tt = t * t; ttt = tt * t; buffList.add(new Vector2(0.5 * ((2 * p1x) + (-p0x + p2x) * t + (2 * p0x - 5 * p1x + 4 * p2x - p3x) * tt + (-p0x + 3 * p1x - 3 * p2x + p3x) * ttt), 0.5 * ((2 * p1y) + (-p0y + p2y) * t + (2 * p0y - 5 * p1y + 4 * p2y - p3y) * tt + (-p0y + 3 * p1y - 3 * p2y + p3y) * ttt))); } buffList.add(new Vector2(p2.x, p2.y)); } } // public CanvasToolbar getToolbar() { // return toolbar; // } public void updateDataPack(DataPack data, int startIndex) { int i = 0; for (AbstractHistory tempHistory : myHistoryManager.historys) { if (i >= startIndex) data.updatedHistory.add(tempHistory); i++; } } @Override public Surface scale(double scale) { return this.scale(scale, scale); } public void updateDataPack(CanvasPack data, int startIndex) { int i = 0; for (AbstractHistory tempHistory : myHistoryManager.historys) { if (i >= startIndex) data.updatedHistory.add(tempHistory); i++; } } public void renewImage(ArrayList<AbstractHistory> newHistorys) { myHistoryManager.clearHistory(); indexes.clear(); cache.clear(); colorCache.clear(); strokeSizes.clear(); for (AbstractHistory tempHistory : newHistorys) { myHistoryManager.addHistory(tempHistory); } surface.clear(); if (preview) { renewPreview(); } else { renewImage(); } } /* when the sketch is previewed */ private void renewPreview() { int start = 0; surface.clear(); for (start = 0; start < myHistoryManager.historys.size(); start++) { AbstractHistory history = myHistoryManager.historys.get(start); if (history.getType() == "AddHistory") { Point endPos = ((AddHistory) history).endPos; MyColor pathColor = ((AddHistory) history).pathColor; strokeSize = ((AddHistory) history).strokeSize; double x = endPos.getVector2().getX(); double y = endPos.getVector2().getY(); if (strokePointCount == 1) { /* set stroke color, size, and shadow */ canvas_context.setStrokeStyle(pathColor.getColorCode()); canvas_context.setFillStyle(pathColor.getColorCode()); canvas_context.setLineWidth(strokeSize); canvas_context.setLineCap(LineCap.ROUND); canvas_context.setLineJoin(LineJoin.ROUND); canvas_context.stroke(); canvas_context.beginPath(); canvas_context.moveTo(x, y); } canvas_context.lineTo(x, y); strokePointCount++; } else if (history.getType() == "PathHeadHistory") { strokePointCount = 0; strokePointCount++; } } canvas_context.stroke(); } /* when the sketch is downloaded */ public void renewImage() { //myHistoryManager.clearHistory(); indexes.clear(); cache.clear(); colorCache.clear(); strokeSizes.clear(); // for (AbstractHistory tempHistory : newHistorys) { // myHistoryManager.addHistory(tempHistory); // } surface.clear(); int start = 0; for (start = 0; start < myHistoryManager.historys.size(); start++) { AbstractHistory history = myHistoryManager.historys.get(start); if (history.getType() == "AddHistory") { Point endPos = ((AddHistory) history).endPos; MyColor pathColor = ((AddHistory) history).pathColor; strokeSize = ((AddHistory) history).strokeSize; double x = endPos.getVector2().getX(); double y = endPos.getVector2().getY(); if (strokePointCount == 2) { canvas_context.setStrokeStyle(pathColor.getColorCode()); canvas_context.setFillStyle(pathColor.getColorCode()); canvas_context.setLineWidth(((double) strokeSize) * 0.5); canvas_context.setLineCap(LineCap.ROUND); canvas_context.setLineJoin(LineJoin.ROUND); canvas_context.setShadowBlur(((double) strokeSize) * 0.3); canvas_context.setShadowColor(pathColor.getColorCode()); /* get the x, y */ p3.x = x; p3.y = y; p0.x = p1.x + (p1.x - p2.x); p0.y = p1.y + (p1.y - p2.y); strokePointCount++; get_buffer(p0, p1, p2, p3, bufferCount); bufferCount = buffList.size(); oldx = (int) buffList.get(0).x; oldy = (int) buffList.get(0).y; canvas_context.beginPath(); canvas_context.moveTo(oldx, oldy); cache.add(new Vector2(oldx, oldy)); /* * draw all interpolated points found through Hermite * interpolation */ int i = 1; for (i = 1; i < bufferCount - 2; i++) { x = buffList.get(i).x; y = buffList.get(i).y; cache.add(new Vector2(x, y)); double nextx = buffList.get(i + 1).x; double nexty = buffList.get(i + 1).y; double c = (x + nextx) / 2; double d = (y + nexty) / 2; canvas_context.quadraticCurveTo(x, y, c, d); } x = buffList.get(i).x; y = buffList.get(i).y; cache.add(new Vector2(x, y)); double nextx = buffList.get(i + 1).x; double nexty = buffList.get(i + 1).y; cache.add(new Vector2(nextx, nexty)); canvas_context.quadraticCurveTo(x, y, nextx, nexty); /* adaptive buffering using Hermite interpolation */ int distance = (int) Math.sqrt(Math.pow(x - p2.x, 2) + Math.pow(y - p2.y, 2)); bufferCount = ((int) distance / 10) > 6 ? 6 : 3; bufferCount = bufferCount < 10 ? bufferCount : 10; colorCache.remove(colorCache.size()-1); colorCache.add(pathColor); } else { /* update the touch point list */ p0.x = p1.x; p0.y = p1.y; p1.x = p2.x; p1.y = p2.y; p2.x = p3.x; p2.y = p3.y; p3.x = x; p3.y = y; get_buffer(p0, p1, p2, p3, bufferCount); /* * draw all interpolated points found through Hermite * interpolation */ bufferCount = buffList.size(); int i = 1; for (i = 1; i < bufferCount - 2; i++) { x = buffList.get(i).x; y = buffList.get(i).y; cache.add(new Vector2(x, y)); double nextx = buffList.get(i + 1).x; double nexty = buffList.get(i + 1).y; double c = (x + nextx) / 2; double d = (y + nexty) / 2; canvas_context.quadraticCurveTo(x, y, c, d); } x = buffList.get(i).x; y = buffList.get(i).y; cache.add(new Vector2(x, y)); double nextx = buffList.get(i + 1).x; double nexty = buffList.get(i + 1).y; cache.add(new Vector2(nextx, nexty)); canvas_context.quadraticCurveTo(x, y, nextx, nexty); /* adaptive buffering using Hermite interpolation */ int distance = (int) Math.sqrt(Math.pow(x - p2.x, 2) + Math.pow(y - p2.y, 2)); bufferCount = ((int) distance / 10) > 6 ? 6 : 3; bufferCount = bufferCount < 10 ? bufferCount : 10; // logger.log(Level.SEVERE, "bufferCount "+ // bufferCount); } } else if (history.getType() == "PathHeadHistory") { MyColor pathColor = ((PathHeadHistory) history).pathColor; strokeSize = ((PathHeadHistory) history).strokeSize; Point position = ((PathHeadHistory) history).position; double x = position.getVector2().getX(); double y = position.getVector2().getY(); strokePointCount = 0; /* initialize the points */ p1.x = x; p1.y = y; p2.x = x; p2.y = y; strokePointCount++; strokePointCount++; canvas_context.stroke(); /* add index to indexes list */ indexes.add(cache.size()); cache.add(new Vector2(x, y)); strokeSizes.add(strokeSize); colorCache.add(pathColor); /* set stroke color, size, and shadow */ canvas_context.setStrokeStyle(pathColor.getColorCode()); canvas_context.setFillStyle(pathColor.getColorCode()); canvas_context.setLineWidth(((double) strokeSize) * 0.4); canvas_context.beginPath(); canvas_context.arc(x, y, ((double) strokeSize) * 0.4, 0, 2 * Math.PI); canvas_context.fill(); bufferCount = 3; } } canvas_context.stroke(); strokePointCount = 0; } private void redrawfromCache() { surface.clear(); for (int i = 0; i < indexes.size(); i++) { int index = indexes.get(i); Vector2 touchStart = cache.get(index); MyColor color = colorCache.get(i); int strokeSize = strokeSizes.get(i); double x = touchStart.getX(); double y = touchStart.getY(); if (index > 0) { canvas_context.stroke(); surface.restore(); } canvas_context.setStrokeStyle(color.getColorCode()); canvas_context.setFillStyle(color.getColorCode()); canvas_context.setLineWidth(((double) strokeSize) * 0.4); canvas_context.beginPath(); canvas_context.arc(x, y, ((double) strokeSize) * 0.4, 0, 2 * Math.PI); canvas_context.fill(); canvas_context.beginPath(); canvas_context.setStrokeStyle(color.getColorCode()); canvas_context.setFillStyle(color.getColorCode()); canvas_context.setLineWidth(((double) strokeSize)); canvas_context.setLineCap(LineCap.ROUND); canvas_context.setLineJoin(LineJoin.ROUND); canvas_context.setShadowBlur(((double) strokeSize) * 0.3); canvas_context.setShadowColor(color.getColorCode()); canvas_context.moveTo(x, y); Vector2 touchMove; for (int j = index+1; j < cache.size() - 1; j++) { if (i == indexes.size()-1) { } else if ( j < indexes.get(i + 1) - 1) { } else { canvas_context.stroke(); break; } touchMove = cache.get(j); x = touchMove.getX(); y = touchMove.getY(); double nextx = cache.get(j+1).getX(); double nexty = cache.get(j+1).getY(); double c = (x + nextx) / 2; double d = (y + nexty) / 2; canvas_context.quadraticCurveTo(x, y, c, d); } canvas_context.stroke(); } } public int getHistorySize() { return myHistoryManager.historys.size(); } public int chopHistory(float factor) { int removeNumber = Math.round(myHistoryManager.historys.size() * (1 - factor)); int i; for (i = 0; i < removeNumber; i++) { myHistoryManager.historys .remove(myHistoryManager.historys.size() - 1); } return removeNumber; } public TouchPad getDrawingSurface() { return this; } public void UpdateSize() { WIDTH = this.getCoordinateSpaceWidth(); HEIGHT = this.getCoordinateSpaceHeight(); } protected void setColor(int red, int green, int blue) { currentColor = new Color(red, green, blue); } // public void changeColor() { // colorWin.show(); // colorWin.setLeft(windowWidth - colorWin.getWidth() - 10); // colorWin.setTop(60); // colorWin.getHeader().setHeight(28); // } public void changeColor(Color tempColor) { currentColor = tempColor; } // public void changeStrokeSize() { // if (currentColor == KnownColor.WHITE) { // currentColor = KnownColor.BLACK; // return; // } // // if (erase) { // erase = false; // return; // } // // sliderWin.show(); // sliderWin.setLeft(windowWidth - sliderWin.getWidth() - 10); // sliderWin.setTop(windowHeight - sliderWin.getHeight() - 20); // sliderWin.getHeader().setHeight(28); // // erase = false; // } public void changeStrokeSize(int tempStrokeSize) { if (currentColor == KnownColor.WHITE) { currentColor = KnownColor.BLACK; } strokeSize = tempStrokeSize; erase = false; } public void changeOpacity() { } double currentState = 1.0; public void undo() { int size = myHistoryManager.historys.size(); for (int i = size - 1; i > 0; i--) { AbstractHistory tempHistory = myHistoryManager.historys.get(i); if (tempHistory.getType() == "PathHeadHistory") { tempHistory = myHistoryManager.historys.remove(i); myHistoryManagerRedoStack.historys.add(tempHistory); break; } tempHistory = myHistoryManager.historys.remove(i); myHistoryManagerRedoStack.historys.add(tempHistory); } renewImage(); // renewImage(); // clearSurface(); // currentState = currentState - 0.03; // myHistoryManager.moveToState(currentState); } public void redo() { int redoStackSize = myHistoryManagerRedoStack.historys.size(); for (int i = redoStackSize - 1; i > 0; i--) { AbstractHistory tempHistory = myHistoryManagerRedoStack.historys.get(i); if (tempHistory.getType() == "PathHeadHistory") { tempHistory = myHistoryManagerRedoStack.historys.remove(i); myHistoryManager.addHistory(tempHistory); break; } tempHistory = myHistoryManagerRedoStack.historys.remove(i); myHistoryManager.addHistory(tempHistory); } renewImage(); } public void redraw() { redrawfromCache(); } @Override public String getID() { return uuid; } boolean erase = false; public void erase() { // if (erase == false) { // erase = true; // } else { // erase = false; // } if (currentColor == KnownColor.WHITE) { currentColor = KnownColor.BLACK; } else { currentColor = KnownColor.WHITE; } } }