--- old/src/share/classes/sun/java2d/SunGraphics2D.java 2013-04-08 16:14:40.720572500 +0400 +++ new/src/share/classes/sun/java2d/SunGraphics2D.java 2013-04-08 16:14:40.537562100 +0400 @@ -65,6 +65,8 @@ import java.awt.Transparency; import java.awt.font.GlyphVector; import java.awt.font.TextLayout; + +import sun.awt.image.SurfaceManager; import sun.font.FontDesignMetrics; import sun.font.FontUtilities; import sun.java2d.pipe.PixelDrawPipe; @@ -82,14 +84,12 @@ import sun.java2d.loops.SurfaceType; import sun.java2d.loops.Blit; import sun.java2d.loops.MaskFill; -import sun.font.FontManager; import java.awt.font.FontRenderContext; import sun.java2d.loops.XORComposite; import sun.awt.ConstrainableGraphics; import sun.awt.SunHints; import java.util.Map; import java.util.Iterator; -import sun.java2d.DestSurfaceProvider; import sun.misc.PerformanceLogger; import javax.tools.annotation.GenerateNativeHeader; @@ -207,13 +207,15 @@ public RenderingHints hints; - public Region constrainClip; // lightweight bounds + public Region constrainClip; // lightweight bounds in pixels public int constrainX; public int constrainY; public Region clipRegion; public Shape usrClip; - protected Region devClip; // Actual physical drawable + protected Region devClip; // Actual physical drawable in pixels + + private final int devScale; // Actual physical scale factor // cached state for text rendering private boolean validFontInfo; @@ -256,6 +258,12 @@ validateColor(); + devScale = sd.getDefaultScale(); + if (devScale != 1) { + transform.setToScale(devScale, devScale); + invalidateTransform(); + } + font = f; if (font == null) { font = defaultFont; @@ -320,38 +328,40 @@ /** * Constrain rendering for lightweight objects. - * - * REMIND: This method will back off to the "workaround" - * of using translate and clipRect if the Graphics - * to be constrained has a complex transform. The - * drawback of the workaround is that the resulting - * clip and device origin cannot be "enforced". - * - * @exception IllegalStateException If the Graphics - * to be constrained has a complex transform. */ - public void constrain(int x, int y, int w, int h) { - if ((x|y) != 0) { + public void constrain(int x, int y, int w, int h, Region region) { + if ((x | y) != 0) { translate(x, y); } - if (transformState >= TRANSFORM_TRANSLATESCALE) { + if (transformState > TRANSFORM_TRANSLATESCALE) { clipRect(0, 0, w, h); return; } - x = constrainX = transX; - y = constrainY = transY; - w = Region.dimAdd(x, w); - h = Region.dimAdd(y, h); + // changes parameters according to the current scale and translate. + final double scaleX = transform.getScaleX(); + final double scaleY = transform.getScaleY(); + x = constrainX = (int) transform.getTranslateX(); + y = constrainY = (int) transform.getTranslateY(); + w = Region.dimAdd(x, Region.clipScale(w, scaleX)); + h = Region.dimAdd(y, Region.clipScale(h, scaleY)); + Region c = constrainClip; if (c == null) { c = Region.getInstanceXYXY(x, y, w, h); } else { c = c.getIntersectionXYXY(x, y, w, h); - if (c == constrainClip) { - // Common case to ignore - return; - } } + if (region != null) { + region = region.getScaledRegion(scaleX, scaleY); + region = region.getTranslatedRegion(x, y); + c = c.getIntersection(region); + } + + if (c == constrainClip) { + // Common case to ignore + return; + } + constrainClip = c; if (!devClip.isInsideQuickCheck(c)) { devClip = devClip.getIntersection(c); @@ -359,6 +369,23 @@ } } + /** + * Constrain rendering for lightweight objects. + * + * REMIND: This method will back off to the "workaround" + * of using translate and clipRect if the Graphics + * to be constrained has a complex transform. The + * drawback of the workaround is that the resulting + * clip and device origin cannot be "enforced". + * + * @exception IllegalStateException If the Graphics + * to be constrained has a complex transform. + */ + @Override + public void constrain(int x, int y, int w, int h) { + constrain(x, y, w, h, null); + } + protected static ValidatePipe invalidpipe = new ValidatePipe(); /* @@ -1540,11 +1567,13 @@ * @see TransformChain * @see AffineTransform */ + @Override public void setTransform(AffineTransform Tx) { - if ((constrainX|constrainY) == 0) { + if ((constrainX | constrainY) == 0 && devScale == 1) { transform.setTransform(Tx); } else { - transform.setToTranslation(constrainX, constrainY); + transform.setTransform(devScale, 0, 0, devScale, constrainX, + constrainY); transform.concatenate(Tx); } invalidateTransform(); @@ -1602,12 +1631,15 @@ * @see #transform * @see #setTransform */ + @Override public AffineTransform getTransform() { - if ((constrainX|constrainY) == 0) { + if ((constrainX | constrainY) == 0 && devScale == 1) { return new AffineTransform(transform); } - AffineTransform tx = - AffineTransform.getTranslateInstance(-constrainX, -constrainY); + final double invScale = 1.0 / devScale; + AffineTransform tx = new AffineTransform(invScale, 0, 0, invScale, + -constrainX * invScale, + -constrainY * invScale); tx.concatenate(transform); return tx; } @@ -2991,6 +3023,37 @@ } // end of text rendering methods + private static boolean isHiDPIImage(final Image img) { + return SurfaceManager.getImageScale(img) != 1; + } + + private boolean drawHiDPIImage(Image img, int dx1, int dy1, int dx2, + int dy2, int sx1, int sy1, int sx2, int sy2, + Color bgcolor, ImageObserver observer) { + final int scale = SurfaceManager.getImageScale(img); + sx1 = Region.clipScale(sx1, scale); + sx2 = Region.clipScale(sx2, scale); + sy1 = Region.clipScale(sy1, scale); + sy2 = Region.clipScale(sy2, scale); + try { + return imagepipe.scaleImage(this, img, dx1, dy1, dx2, dy2, sx1, sy1, + sx2, sy2, bgcolor, observer); + } catch (InvalidPipeException e) { + try { + revalidateAll(); + return imagepipe.scaleImage(this, img, dx1, dy1, dx2, dy2, sx1, + sy1, sx2, sy2, bgcolor, observer); + } catch (InvalidPipeException e2) { + // Still catching the exception; we are not yet ready to + // validate the surfaceData correctly. Fail for now and + // try again next time around. + return false; + } + } finally { + surfaceData.markDirty(); + } + } + /** * Draws an image scaled to x,y,w,h in nonblocking mode with a * callback object. @@ -3004,8 +3067,9 @@ * Not part of the advertised API but a useful utility method * to call internally. This is for the case where we are * drawing to/from given coordinates using a given width/height, - * but we guarantee that the weidth/height of the src and dest - * areas are equal (no scale needed). + * but we guarantee that the surfaceData's width/height of the src and dest + * areas are equal (no scale needed). Note that this method intentionally + * ignore scale factor of the source image, and copy it as is. */ public boolean copyImage(Image img, int dx, int dy, int sx, int sy, int width, int height, Color bgcolor, @@ -3043,7 +3107,15 @@ if ((width == 0) || (height == 0)) { return true; } - if (width == img.getWidth(null) && height == img.getHeight(null)) { + + final int imgW = img.getWidth(null); + final int imgH = img.getHeight(null); + if (isHiDPIImage(img)) { + return drawHiDPIImage(img, x, y, x + width, y + height, 0, 0, imgW, + imgH, bg, observer); + } + + if (width == imgW && height == imgH) { return copyImage(img, x, y, 0, 0, width, height, bg, observer); } @@ -3084,6 +3156,13 @@ return true; } + if (isHiDPIImage(img)) { + final int imgW = img.getWidth(null); + final int imgH = img.getHeight(null); + return drawHiDPIImage(img, x, y, x + imgW, y + imgH, 0, 0, imgW, + imgH, bg, observer); + } + try { return imagepipe.copyImage(this, img, x, y, bg, observer); } catch (InvalidPipeException e) { @@ -3132,6 +3211,11 @@ return true; } + if (isHiDPIImage(img)) { + return drawHiDPIImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, + bgcolor, observer); + } + if (((sx2 - sx1) == (dx2 - dx1)) && ((sy2 - sy1) == (dy2 - dy1))) { @@ -3210,6 +3294,18 @@ return drawImage(img, 0, 0, null, observer); } + if (isHiDPIImage(img)) { + final int w = img.getWidth(null); + final int h = img.getHeight(null); + final AffineTransform tx = new AffineTransform(transform); + transform(xform); + boolean result = drawHiDPIImage(img, 0, 0, w, h, 0, 0, w, h, null, + observer); + transform.setTransform(tx); + invalidateTransform(); + return result; + } + try { return imagepipe.transformImage(this, img, xform, observer); } catch (InvalidPipeException e) {