/*
* $Id$
*
* Copyright (c) 2007 by Joel Uckelman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License (LGPL) as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, copies are available
* at http://www.opensource.org.
*/
package VASSAL.tools.imageop;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang.builder.HashCodeBuilder;
import VASSAL.tools.image.ImageUtils;
/**
* An {@link ImageOp} which rotates and scales its source. Rotation
* is about the center of the source image, and scaling ranges from
* <code>(0,Double.MAX_VALUE)</code>. If a source is to be both rotated
* and scaled, using one <code>RotateScaleOp</code> will produce better
* results than doing the rotation and scaling separately with
* one {@link RotateOp} and one {@link ScaleOp}.
*
* @since 3.1.0
* @author Joel Uckelman
*/
public class RotateScaleOpBitmapImpl extends AbstractTileOpImpl
implements RotateScaleOp {
private final ImageOp sop;
private final double scale;
private final double angle;
private final RenderingHints hints;
private final int hash;
/**
* Constructs an <code>ImageOp</code> which will rotate and scale
* the image produced by its source <code>ImageOp</code>.
*
* @param sop the source operation
* @param angle the angle of rotation, in degrees
* @param scale the scale factor
*/
public RotateScaleOpBitmapImpl(ImageOp sop, double angle, double scale) {
this(sop, angle, scale, ImageUtils.getDefaultHints());
}
/**
* Constructs an <code>ImageOp</code> which will rotate and scale
* the image produced by its source <code>ImageOp</code>.
*
* @param sop the source operation
* @param angle the angle of rotation, in degrees
* @param scale the scale factor
* @param hints rendering hints
* @throws IllegalArgumentException if <code>sop == null</code>.
*/
public RotateScaleOpBitmapImpl(ImageOp sop, double angle, double scale,
RenderingHints hints) {
if (sop == null) throw new IllegalArgumentException();
if (scale <= 0) throw new IllegalArgumentException("scale = " + scale);
this.sop = sop;
this.angle = angle;
this.scale = scale;
this.hints = hints;
hash = new HashCodeBuilder().append(sop)
.append(scale)
.append(angle)
.append(hints)
.toHashCode();
}
public List<VASSAL.tools.opcache.Op<?>> getSources() {
return Collections.<VASSAL.tools.opcache.Op<?>>singletonList(sop);
}
/**
* {@inheritDoc}
*
* @throws Exception passed up from the source <code>ImageOp</code>.
*/
public BufferedImage eval() throws Exception {
return ImageUtils.transform(sop.getImage(null), scale, angle, hints);
}
/** {@inheritDoc} */
protected void fixSize() {
if ((size = getSizeFromCache()) == null) {
size = ImageUtils.transform(
new Rectangle(sop.getSize()), scale, angle).getSize();
}
}
/**
* Returns the angle of rotation.
*
* @return the angle of rotation, in degrees.
*/
public double getAngle() {
return angle;
}
/**
* Returns the scale factor.
*
* @return the scale factor, in the range <code>(0,Double.MAX_VALUE]</code>.
*/
public double getScale() {
return scale;
}
public RenderingHints getHints() {
return hints;
}
/** {@inheritDoc} */
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || o.getClass() != this.getClass()) return false;
final RotateScaleOpBitmapImpl op = (RotateScaleOpBitmapImpl) o;
return scale == op.getScale() &&
angle == op.getAngle() &&
hints.equals(op.getHints()) &&
sop.equals(op.sop);
}
/** {@inheritDoc} */
@Override
public int hashCode() {
return hash;
}
}