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

Print this page

        

*** 63,72 **** --- 63,74 ---- import java.awt.Font; import java.awt.image.ImageObserver; 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; import sun.java2d.pipe.PixelFillPipe; import sun.java2d.pipe.ShapeDrawPipe;
*** 80,97 **** import sun.java2d.loops.RenderLoops; import sun.java2d.loops.CompositeType; 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; /** * This is a the master Graphics2D superclass for all of the Sun * Graphics implementations. This class relies on subclasses to --- 82,97 ----
*** 201,217 **** public int interpolationType; // algorithm choice based on // interpolation and render Hints public RenderingHints hints; ! public Region constrainClip; // lightweight bounds public int constrainX; public int constrainY; public Region clipRegion; public Shape usrClip; ! protected Region devClip; // Actual physical drawable // cached state for text rendering private boolean validFontInfo; private FontInfo fontInfo; private FontInfo glyphVectorFontInfo; --- 201,219 ---- public int interpolationType; // algorithm choice based on // interpolation and render Hints public RenderingHints hints; ! 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 in pixels ! ! private final int devScale; // Actual physical scale factor // cached state for text rendering private boolean validFontInfo; private FontInfo fontInfo; private FontInfo glyphVectorFontInfo;
*** 250,259 **** --- 252,267 ---- interpolationType = AffineTransformOp.TYPE_NEAREST_NEIGHBOR; validateColor(); + devScale = sd.getDefaultScale(); + if (devScale != 1) { + transform.setToScale(devScale, devScale); + invalidateTransform(); + } + font = f; if (font == null) { font = defaultFont; }
*** 314,362 **** setDevClip(r.x, r.y, r.width, r.height); } /** * 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) { translate(x, y); } ! 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); 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; } ! } constrainClip = c; if (!devClip.isInsideQuickCheck(c)) { devClip = devClip.getIntersection(c); validateCompClip(); } } protected static ValidatePipe invalidpipe = new ValidatePipe(); /* * Invalidate the pipeline */ --- 322,389 ---- setDevClip(r.x, r.y, r.width, r.height); } /** * Constrain rendering for lightweight objects. */ ! public void constrain(int x, int y, int w, int h, Region region) { ! if ((x | y) != 0) { translate(x, y); } ! if (transformState > TRANSFORM_TRANSLATESCALE) { clipRect(0, 0, w, h); return; } ! // 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 (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); validateCompClip(); } } + /** + * 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(); /* * Invalidate the pipeline */
*** 1534,1548 **** * @param Tx The Transform object to be used in the rendering process. * @see #transform * @see TransformChain * @see AffineTransform */ public void setTransform(AffineTransform Tx) { ! if ((constrainX|constrainY) == 0) { transform.setTransform(Tx); } else { ! transform.setToTranslation(constrainX, constrainY); transform.concatenate(Tx); } invalidateTransform(); } --- 1561,1577 ---- * @param Tx The Transform object to be used in the rendering process. * @see #transform * @see TransformChain * @see AffineTransform */ + @Override public void setTransform(AffineTransform Tx) { ! if ((constrainX | constrainY) == 0 && devScale == 1) { transform.setTransform(Tx); } else { ! transform.setTransform(devScale, 0, 0, devScale, constrainX, ! constrainY); transform.concatenate(Tx); } invalidateTransform(); }
*** 1596,1611 **** /** * Returns the current Transform in the Graphics2D state. * @see #transform * @see #setTransform */ public AffineTransform getTransform() { ! if ((constrainX|constrainY) == 0) { return new AffineTransform(transform); } ! AffineTransform tx = ! AffineTransform.getTranslateInstance(-constrainX, -constrainY); tx.concatenate(transform); return tx; } /** --- 1625,1643 ---- /** * Returns the current Transform in the Graphics2D state. * @see #transform * @see #setTransform */ + @Override public AffineTransform getTransform() { ! if ((constrainX | constrainY) == 0 && devScale == 1) { return new AffineTransform(transform); } ! final double invScale = 1.0 / devScale; ! AffineTransform tx = new AffineTransform(invScale, 0, 0, invScale, ! -constrainX * invScale, ! -constrainY * invScale); tx.concatenate(transform); return tx; } /**
*** 2985,2994 **** --- 3017,3057 ---- surfaceData.markDirty(); } } // 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. */ public boolean drawImage(Image img, int x, int y, int width, int height,
*** 2998,3009 **** /** * 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). */ public boolean copyImage(Image img, int dx, int dy, int sx, int sy, int width, int height, Color bgcolor, ImageObserver observer) { try { --- 3061,3073 ---- /** * 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 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, ImageObserver observer) { try {
*** 3037,3047 **** } if ((width == 0) || (height == 0)) { return true; } ! if (width == img.getWidth(null) && height == img.getHeight(null)) { return copyImage(img, x, y, 0, 0, width, height, bg, observer); } try { return imagepipe.scaleImage(this, img, x, y, width, height, --- 3101,3119 ---- } if ((width == 0) || (height == 0)) { return true; } ! ! 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); } try { return imagepipe.scaleImage(this, img, x, y, width, height,
*** 3078,3087 **** --- 3150,3166 ---- if (img == null) { 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) { try { revalidateAll();
*** 3126,3135 **** --- 3205,3219 ---- sx1 == sx2 || sy1 == sy2) { 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))) { // Not a scale - forward it to a copy routine int srcX, srcY, dstX, dstY, width, height;
*** 3204,3213 **** --- 3288,3309 ---- if (xform == null || xform.isIdentity()) { 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) { try { revalidateAll();