package com.kreative.paint.draw;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.PathIterator;
import java.awt.image.BufferedImage;
import com.kreative.paint.document.draw.PaintSettings;
import com.kreative.paint.document.draw.Path;
import com.kreative.paint.powerbrush.BrushSettings;
public class PowerBrushStrokeDrawObject extends StrokeDrawObject {
private BrushSettings brush;
private transient BufferedImage cache;
private transient int cachex, cachey;
public PowerBrushStrokeDrawObject(PaintSettings ps, Path path, BrushSettings brush) {
super(ps, path);
this.brush = brush;
this.cache = null;
}
public PowerBrushStrokeDrawObject(PaintSettings ps, Shape path, BrushSettings brush) {
super(ps, path);
this.brush = brush;
this.cache = null;
}
private PowerBrushStrokeDrawObject(PowerBrushStrokeDrawObject o) {
super(o);
this.brush = o.brush;
this.cache = null;
}
@Override
public PowerBrushStrokeDrawObject clone() {
return new PowerBrushStrokeDrawObject(this);
}
@Override
protected void notifyDrawObjectListeners(int id) {
this.cache = null;
super.notifyDrawObjectListeners(id);
}
@Override
protected int getStrokeWidth() {
return (int)Math.ceil(Math.max(brush.getOuterWidth(), brush.getOuterHeight()));
}
public BrushSettings getBrush() { return brush; }
@Override
protected void preTxPaintImpl(Graphics2D g, AffineTransform tx) {
if (cache == null) {
Shape s = path.toAWTShape();
if (tx != null) {
try { s = tx.createTransformedShape(s); }
catch (Exception e) { s = path.toAWTShape(); }
}
Rectangle b = s.getBounds();
this.cachex = (int)Math.floor(b.x - brush.getOuterWidth());
this.cachey = (int)Math.floor(b.y - brush.getOuterHeight());
this.cache = new BufferedImage(
(int)Math.ceil(b.width + brush.getOuterWidth() * 2),
(int)Math.ceil(b.height + brush.getOuterHeight() * 2),
BufferedImage.TYPE_INT_ARGB
);
if (ps.isFilled()) {
Graphics2D gc = cache.createGraphics();
gc.translate(-cachex, -cachey);
ps.applyFill(gc);
drag(gc, s);
gc.dispose();
}
}
g.drawImage(cache, null, cachex, cachey);
}
private void drag(Graphics2D g, Shape s) {
double sx = 0, sy = 0;
double cx = 0, cy = 0;
double[] c = new double[6];
for (PathIterator i = s.getPathIterator(null, 1); !i.isDone(); i.next()) {
switch (i.currentSegment(c)) {
case PathIterator.SEG_MOVETO:
brush.paint(g, (float)c[0], (float)c[1]);
sx = cx = c[0]; sy = cy = c[1];
break;
case PathIterator.SEG_LINETO:
brush.paint(g, false, (float)cx, (float)cy, (float)c[0], (float)c[1]);
cx = c[0]; cy = c[1];
break;
case PathIterator.SEG_QUADTO:
brush.paint(g, false, (float)cx, (float)cy, (float)c[2], (float)c[3]);
cx = c[2]; cy = c[3];
break;
case PathIterator.SEG_CUBICTO:
brush.paint(g, false, (float)cx, (float)cy, (float)c[4], (float)c[5]);
cx = c[4]; cy = c[5];
break;
case PathIterator.SEG_CLOSE:
brush.paint(g, false, (float)cx, (float)cy, (float)sx, (float)sy);
cx = sx; cy = sy;
break;
}
}
}
}