(AffineTransform.TYPE_FLIP |
AffineTransform.TYPE_MASK_ROTATION |
AffineTransform.TYPE_GENERAL_TRANSFORM)) == 0)))
{
// Must be a simple scale - we can handle this
SurfaceData sData =
SurfaceData.getSurfaceDataFromImage(img, sg.surfaceData,
sg.imageComp, bgColor, true);
if (!isBgOperation(sData, bgColor)) {
SurfaceType src = sData.getSurfaceType();
SurfaceType dst = sg.surfaceData.getSurfaceType();
int dstX = x;
int dstY = y;
int dstW = img.getWidth(null);
int dstH = img.getHeight(null);
double coords[] = null;
if (xf != null) {
coords = new double[] {
dstX, dstY, dstX+dstW, dstY+dstH,
};
xf.transform(coords, 0, coords, 0, 2);
// Round to integer coordinates first,
// then subtract to get w/h
dstX = (int)(coords[0] + 0.5);
dstY = (int)(coords[1] + 0.5);
dstW = (int)(coords[2] + 0.5);
dstH = (int)(coords[3] + 0.5);
dstW -= dstX;
dstH -= dstY;
}
if (scaleSurfaceData(sg, sData, sg.surfaceData, src, dst,
dstX, dstY, 0, 0,
dstW, dstH,
img.getWidth(null),
img.getHeight(null), coords))
{
return;
}
}
}
}
// Must not have been acceleratable as a simple scale - do this
// as a general transform
BufferedImage bImg = getBufferedImage(img);
AffineTransform opXform = null;
if (op != null) {
if (op instanceof AffineTransformOp) {
AffineTransformOp atop = (AffineTransformOp) op;
opXform = atop.getTransform();
interpolationType = atop.getInterpolationType();
}
else {
bImg = op.filter(bImg, null);
}
}
int bImgWidth = bImg.getWidth();
int bImgHeight = bImg.getHeight();
// Begin Transform
AffineTransform tx = new AffineTransform(sg.transform);
tx.translate(x, y);
if (xf != null && !xf.isIdentity()) {
tx.concatenate(xf);
}
if (opXform != null && !opXform.isIdentity()) {
tx.concatenate(opXform);
}
double mat[] = new double[6];
tx.getMatrix(mat);
// Only a translation
if (mat[0] == 1. && mat[1] == 0. && mat[2] == 0. && mat[3] == 1.) {
x = (int) Math.round(mat[4]);
y = (int) Math.round(mat[5]);
Region bounds = Region.getInstanceXYWH(x, y, bImgWidth, bImgHeight);
clip = clip.getBoundsIntersection(bounds);
if (clip.isEmpty()) {
return;
}
if (!clip.encompasses(bounds)) {
bImgWidth = clip.getWidth();
bImgHeight = clip.getHeight();
bImg = bImg.getSubimage(clip.getLoX() - x, clip.getLoY() - y,
bImgWidth, bImgHeight);
}
} else {
int hint = interpolationType;
if (interpolationType == -1) {
hint = (sg.renderHint == SunHints.INTVAL_RENDER_QUALITY
? AffineTransformOp.TYPE_BILINEAR
: AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
}
// MediaLib/AffineTransformOp handle indexed images poorly in
// the bilinear case, so we will convert the source image into
// an INT_ARGB_PRE image (MediaLib produces better results with
// premultiplied alpha)
// REMIND: this and other similar special case hacks should go
// away in the future...
if ((hint != AffineTransformOp.TYPE_NEAREST_NEIGHBOR) &&
(bImg.getColorModel() instanceof IndexColorModel))
{
BufferedImage tmpBI =
new BufferedImage(bImg.getWidth(), bImg.getHeight(),
BufferedImage.TYPE_INT_ARGB_PRE);
Graphics2D g2d = tmpBI.createGraphics();
try {
g2d.setComposite(AlphaComposite.Src);
g2d.drawImage(bImg, 0, 0, null);
} finally {
g2d.dispose();
}
bImg = tmpBI;
}
ColorModel dstCM = getTransformColorModel(sg, bImg, tx);
AffineTransformOp affOp = new AffineTransformOp(tx, hint);
// Transform the bounding box of the image in order to
// extract the translation and to figure out the destination
// width and height
Rectangle bounds = affOp.getBounds2D(bImg).getBounds();
clip = clip.getBoundsIntersection(bounds);
if (clip.isEmpty()) {
return;
}
x = clip.getLoX();
y = clip.getLoY();
bImgWidth = clip.getWidth();
bImgHeight = clip.getHeight();
if (x != 0 || y != 0) {
tx.preConcatenate(new AffineTransform(1.,0.,0.,1., -x, -y));
affOp = new AffineTransformOp(tx, hint);
}
// Create a new dst image.
BufferedImage dst;
if (dstCM == bImg.getColorModel()) {
// It is better to use Raster.createCompatibleWritableRaster
// because the equivalent call in ColorModel cannot
// figure out if the image is, for example, RGB vs BGR.
// This is the fix for bug 4245031.
dst = new BufferedImage(dstCM,
bImg.getRaster().createCompatibleWritableRaster(bImgWidth,
bImgHeight),
dstCM.isAlphaPremultiplied(), null);
}
else {
dst = new BufferedImage(dstCM,
dstCM.createCompatibleWritableRaster(bImgWidth,
bImgHeight),
dstCM.isAlphaPremultiplied(), null);
}
// Now transform the image by the new transform.
bImg = affOp.filter(bImg, dst);
if (bImg == null) {
return;
}
}
// End Transform
SurfaceData sData;
if (bImg instanceof OffScreenImage) {
// If bImg is an OffScreenImage, then there may be a hardware-
// accelerated sd to use. The image that contains sData will
// return the best surface data object to use in this situation.