package com.kreative.paint.document.draw;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.RenderableImage;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class ImageDrawObject extends DrawObject {
private BufferedImage image;
private double x1, y1, x2, y2;
public ImageDrawObject(
PaintSettings ps,
BufferedImage image,
double x, double y,
double width, double height
) {
super(ps);
this.image = image;
this.x1 = x;
this.y1 = y;
this.x2 = x + width;
this.y2 = y + width;
}
private ImageDrawObject(ImageDrawObject o) {
super(o);
this.image = o.image;
this.x1 = o.x1;
this.y1 = o.y1;
this.x2 = o.x2;
this.y2 = o.y2;
}
@Override
public ImageDrawObject clone() {
return new ImageDrawObject(this);
}
public BufferedImage getImage() { return image; }
public double getX() { return x1; }
public double getY() { return y1; }
public double getWidth() { return x2 - x1; }
public double getHeight() { return y2 - y1; }
@Override
protected Shape getBoundaryImpl() {
return new Rectangle2D.Double(
Math.min(x1, x2), Math.min(y1, y2),
Math.abs(x2 - x1), Math.abs(y2 - y1)
);
}
@Override
protected Shape getHitAreaImpl() {
return new Rectangle2D.Double(
Math.min(x1, x2), Math.min(y1, y2),
Math.abs(x2 - x1), Math.abs(y2 - y1)
);
}
@Override
protected Object getControlState() {
return new double[]{ x1, y1, x2, y2 };
}
@Override
protected void setControlState(Object o) {
double[] state = (double[])o;
x1 = state[0]; y1 = state[1];
x2 = state[2]; y2 = state[3];
}
@Override
public int getControlPointCount() {
return 9;
}
@Override
protected ControlPoint getControlPointImpl(int i) {
switch (i) {
case 0: return new ControlPoint(ControlPointType.CENTER, (x1 + x2) / 2, (y1 + y2) / 2);
case 1: return new ControlPoint(ControlPointType.NORTHWEST, x1, y1);
case 2: return new ControlPoint(ControlPointType.NORTHEAST, x2, y1);
case 3: return new ControlPoint(ControlPointType.SOUTHWEST, x1, y2);
case 4: return new ControlPoint(ControlPointType.SOUTHEAST, x2, y2);
case 5: return new ControlPoint(ControlPointType.NORTH, (x1 + x2) / 2, y1);
case 6: return new ControlPoint(ControlPointType.SOUTH, (x1 + x2) / 2, y2);
case 7: return new ControlPoint(ControlPointType.WEST, x1, (y1 + y2) / 2);
case 8: return new ControlPoint(ControlPointType.EAST, x2, (y1 + y2) / 2);
default: return null;
}
}
@Override
protected List<ControlPoint> getControlPointsImpl() {
List<ControlPoint> cpts = new ArrayList<ControlPoint>();
cpts.add(new ControlPoint(ControlPointType.CENTER, (x1 + x2) / 2, (y1 + y2) / 2));
cpts.add(new ControlPoint(ControlPointType.NORTHWEST, x1, y1));
cpts.add(new ControlPoint(ControlPointType.NORTHEAST, x2, y1));
cpts.add(new ControlPoint(ControlPointType.SOUTHWEST, x1, y2));
cpts.add(new ControlPoint(ControlPointType.SOUTHEAST, x2, y2));
cpts.add(new ControlPoint(ControlPointType.NORTH, (x1 + x2) / 2, y1));
cpts.add(new ControlPoint(ControlPointType.SOUTH, (x1 + x2) / 2, y2));
cpts.add(new ControlPoint(ControlPointType.WEST, x1, (y1 + y2) / 2));
cpts.add(new ControlPoint(ControlPointType.EAST, x2, (y1 + y2) / 2));
return cpts;
}
@Override
protected Collection<Line2D> getControlLinesImpl() {
return null;
}
@Override
protected int setControlPointImpl(int i, double x, double y) {
switch (i) {
case 0:
double width2 = (x2 - x1) / 2;
double height2 = (y2 - y1) / 2;
x1 = x - width2;
y1 = y - height2;
x2 = x + width2;
y2 = y + height2;
break;
case 1: x1 = x; y1 = y; break;
case 2: x2 = x; y1 = y; break;
case 3: x1 = x; y2 = y; break;
case 4: x2 = x; y2 = y; break;
case 5: y1 = y; break;
case 6: y2 = y; break;
case 7: x1 = x; break;
case 8: x2 = x; break;
}
return i;
}
@Override
protected Point2D getLocationImpl() {
return new Point2D.Double(x1, y1);
}
@Override
protected void setLocationImpl(double x, double y) {
this.x2 = x + (this.x2 - this.x1);
this.y2 = y + (this.y2 - this.y1);
this.x1 = x;
this.y1 = y;
}
@Override
protected void paintImpl(Graphics2D g) {
Shape ca = new Rectangle2D.Double(
Math.min(x1, x2), Math.min(y1, y2),
Math.abs(x2 - x1), Math.abs(y2 - y1)
);
if (ps.isFilled()) {
ps.applyFill(g);
g.fill(ca);
}
AffineTransform t = g.getTransform();
g.translate(x1, y1);
g.scale((x2 - x1) / image.getWidth(), (y2 - y1) / image.getHeight());
g.drawImage(image, null, 0, 0);
g.setTransform(t);
if (ps.isDrawn()) {
ps.applyDraw(g);
g.draw(ca);
}
}
public static ImageDrawObject forGraphicsDrawImage(PaintSettings ps, Image image, int x, int y) {
return forGraphicsDrawImage(ps, image, x, y, null);
}
public static ImageDrawObject forGraphicsDrawImage(PaintSettings ps, Image image, int x, int y, Color bgcolor) {
Dimension d = prepareImage(image); if (d == null) return null;
BufferedImage i = new BufferedImage(d.width, d.height, BufferedImage.TYPE_INT_ARGB);
i.createGraphics().drawImage(image, 0, 0, null);
return new ImageDrawObject(ps.deriveFillPaint(bgcolor), i, x, y, d.width, d.height);
}
public static ImageDrawObject forGraphicsDrawImage(PaintSettings ps, Image image, int x, int y, int width, int height) {
return forGraphicsDrawImage(ps, image, x, y, width, height, null);
}
public static ImageDrawObject forGraphicsDrawImage(PaintSettings ps, Image image, int x, int y, int width, int height, Color bgcolor) {
Dimension d = prepareImage(image); if (d == null) return null;
BufferedImage i = new BufferedImage(d.width, d.height, BufferedImage.TYPE_INT_ARGB);
i.createGraphics().drawImage(image, 0, 0, null);
return new ImageDrawObject(ps.deriveFillPaint(bgcolor), i, x, y, width, height);
}
public static ImageDrawObject forGraphicsDrawImage(PaintSettings ps, Image image, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2) {
return forGraphicsDrawImage(ps, image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null);
}
public static ImageDrawObject forGraphicsDrawImage(PaintSettings ps, Image image, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor) {
if (prepareImage(image) == null) return null;
int width = Math.abs(sx2 - sx1), height = Math.abs(sy2 - sy1);
BufferedImage i = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
i.createGraphics().drawImage(image, 0, 0, width, height, sx1, sy1, sx2, sy2, null);
return new ImageDrawObject(ps.deriveFillPaint(bgcolor), i, dx1, dy1, dx2 - dx1, dy2 - dy1);
}
public static ImageDrawObject forGraphicsDrawImage(PaintSettings ps, Image image, AffineTransform tx) {
ImageDrawObject ido = forGraphicsDrawImage(ps, image, 0, 0);
ido.setTransform(tx);
return ido;
}
public static ImageDrawObject forGraphicsDrawImage(PaintSettings ps, BufferedImage image, BufferedImageOp op, int x, int y) {
Rectangle b = (op != null) ? op.getBounds2D(image).getBounds()
: new Rectangle(0, 0, image.getWidth(), image.getHeight());
BufferedImage i = new BufferedImage(b.width, b.height, BufferedImage.TYPE_INT_ARGB);
Graphics2D ig = i.createGraphics();
ig.drawImage(image, op, -b.x, -b.y);
ig.dispose();
return new ImageDrawObject(ps, i, x + b.x, y + b.y, b.width, b.height);
}
public static ImageDrawObject forGraphicsDrawRenderableImage(PaintSettings ps, RenderableImage image, AffineTransform tx) {
int width = (int)Math.ceil(image.getWidth());
int height = (int)Math.ceil(image.getHeight());
BufferedImage i = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D ig = i.createGraphics();
ig.drawRenderableImage(image, null);
ig.dispose();
ImageDrawObject ido = new ImageDrawObject(ps, i, 0, 0, width, height);
ido.setTransform(tx);
return ido;
}
public static ImageDrawObject forGraphicsDrawRenderedImage(PaintSettings ps, RenderedImage image, AffineTransform tx) {
int width = image.getWidth();
int height = image.getHeight();
BufferedImage i = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D ig = i.createGraphics();
ig.drawRenderedImage(image, null);
ig.dispose();
ImageDrawObject ido = new ImageDrawObject(ps, i, 0, 0, width, height);
ido.setTransform(tx);
return ido;
}
private static Dimension prepareImage(Image image) {
long startTime = System.currentTimeMillis();
for (;;) {
int width = image.getWidth(null);
int height = image.getHeight(null);
if (width >= 0 && height >= 0) return new Dimension(width, height);
long endTime = System.currentTimeMillis();
if ((endTime - startTime) > 1000) return null;
}
}
}