I’d not deal with the scales of Java2D. When I used to do it, I used to do it with triple buffering. One is the on screen image, and two BufferedImage instances for off screen. I kept the screen image (window) completely resizable. Off screen buffers are in game resolution.
When presenting, I used to calculate the aspect, and find the scales. Then draw the image on the screen with the drawImage method.
// new_(width|height) is the dimension of the scaled image
// bound_(width|height) is the dimension of the window
// original_(width|height) is the dimension of the game resolution
// first check if we need to scale width
if (original_width > bound_width)
{
//scale width to fit
new_width = bound_width;
//scale height to maintain aspect ratio
new_height = (new_width * original_height) / original_width;
}
// then check if we need to scale even with the new height
if (new_height > bound_height)
{
//scale height to fit instead
new_height = bound_height;
//scale width to maintain aspect ratio
new_width = (new_height * original_width) / original_height;
}
// Now clear the screen
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, bound_width, bound_height);
// Calculate the offset x and offset y
int offsetX = Math.abs((new_width - bound_width) / 2);
int offsetY = Math.abs((new_height - bound_height) / 2);
// Draw the image onto the screen
g2d.drawImage(offScreenImage, offsetX, offsetY, new_width, new_height, this /* window */);
This is what I used to do, and it worked for me perfectly.