Skip to content

Commit 2b7594b

Browse files
committed
java2d: implement drawImage as a copy if src & dst have the same scale
This is required for fractional scaling since the generic code rounds too much to perform pixel-perfect copies at all scales. Signed-off-by: Julian Orth <[email protected]>
1 parent 220e267 commit 2b7594b

File tree

1 file changed

+53
-0
lines changed

1 file changed

+53
-0
lines changed

src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3469,6 +3469,13 @@ public boolean drawImage(Image img,
34693469
return true;
34703470
}
34713471

3472+
boolean blitImageDrawn = drawImageBlit(img, dx1, dy1, dx2, dy2,
3473+
sx1, sy1, sx2, sy2,
3474+
bgcolor, observer);
3475+
if (blitImageDrawn) {
3476+
return true;
3477+
}
3478+
34723479
Boolean hidpiImageDrawn = drawHiDPIImage(img, dx1, dy1, dx2, dy2,
34733480
sx1, sy1, sx2, sy2,
34743481
bgcolor, observer, null);
@@ -3525,6 +3532,52 @@ public boolean drawImage(Image img,
35253532
}
35263533
}
35273534

3535+
/**
3536+
* Tries to draw the image via copyImage if the image is compatible with
3537+
* the current transformation. That is, the scaling of the image is the
3538+
* same as the scaling of the transformation and the transformation does
3539+
* not contain any rotation. This leads to better results when the scaling
3540+
* is fractional.
3541+
*/
3542+
private boolean drawImageBlit(Image img,
3543+
int dx1, int dy1, int dx2, int dy2,
3544+
int sx1, int sy1, int sx2, int sy2,
3545+
Color bgcolor, ImageObserver observer) {
3546+
if (dx2 - dx1 == sx2 - sx1 &&
3547+
dy2 - dy1 == sy2 - sy1 &&
3548+
sx1 <= sx2 &&
3549+
sy1 <= sy2 &&
3550+
dx1 <= dx2 &&
3551+
dy1 <= dy2 &&
3552+
transformState <= TRANSFORM_TRANSLATESCALE
3553+
) {
3554+
final SurfaceData sd;
3555+
try {
3556+
sd = SurfaceManager.getManager(img).getPrimarySurfaceData();
3557+
} catch (InvalidPipeException e) {
3558+
return false;
3559+
}
3560+
if (sd.getDefaultScaleX() == transform.getScaleX() && sd.getDefaultScaleY() == transform.getScaleY()) {
3561+
dx1 = Region.clipRound(transform.getScaleX() * dx1);
3562+
dx2 = Region.clipRound(transform.getScaleX() * dx2);
3563+
dy1 = Region.clipRound(transform.getScaleY() * dy1);
3564+
dy2 = Region.clipRound(transform.getScaleY() * dy2);
3565+
sx1 = Region.clipRound(transform.getScaleX() * sx1);
3566+
sy1 = Region.clipRound(transform.getScaleY() * sy1);
3567+
int width = dx2 - dx1;
3568+
int height = dy2 - dy1;
3569+
AffineTransform old = new AffineTransform(transform);
3570+
setTransform(AffineTransform.getTranslateInstance(transform.getTranslateX(), transform.getTranslateY()));
3571+
try {
3572+
return copyImage(img, dx1, dy1, sx1, sy1, width, height, bgcolor, observer);
3573+
} finally {
3574+
setTransform(old);
3575+
}
3576+
}
3577+
}
3578+
return false;
3579+
}
3580+
35283581
/**
35293582
* Draw an image, applying a transform from image space into user space
35303583
* before drawing.

0 commit comments

Comments
 (0)