--- old/src/share/classes/sun/swing/JLightweightFrame.java 2014-02-03 18:17:13.000000000 +0400 +++ new/src/share/classes/sun/swing/JLightweightFrame.java 2014-02-03 18:17:12.000000000 +0400 @@ -40,6 +40,7 @@ import java.awt.event.ContainerListener; import java.awt.image.BufferedImage; import java.awt.image.DataBufferInt; +import java.awt.peer.FramePeer; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.security.AccessController; @@ -52,6 +53,7 @@ import javax.swing.SwingUtilities; import sun.awt.LightweightFrame; +import sun.awt.image.OffScreenImage; import sun.security.action.GetPropertyAction; /** @@ -73,8 +75,10 @@ private Component component; private JPanel contentPane; - private BufferedImage bbImage; + private OffScreenImage bbImage; + private volatile int scaleFactor = 1; + /** * {@code copyBufferEnabled}, true by default, defines the following strategy. * A duplicating (copy) buffer is created for the original pixel buffer. @@ -85,7 +89,7 @@ * by the lock (managed with the {@link LightweightContent#paintLock()}, * {@link LightweightContent#paintUnlock()} methods). */ - private boolean copyBufferEnabled; + private static boolean copyBufferEnabled; private int[] copyBuffer; private PropertyChangeListener layoutSizeListener; @@ -97,6 +101,8 @@ frame.updateClientCursor(); } }); + copyBufferEnabled = "true".equals(AccessController. + doPrivileged(new GetPropertyAction("swing.jlf.copyBufferEnabled", "true"))); } /** @@ -105,9 +111,7 @@ */ public JLightweightFrame() { super(); - copyBufferEnabled = "true".equals(AccessController. - doPrivileged(new GetPropertyAction("swing.jlf.copyBufferEnabled", "true"))); - + add(rootPane, BorderLayout.CENTER); setFocusTraversalPolicy(new LayoutFocusTraversalPolicy()); if (getGraphicsConfiguration().isTranslucencyCapable()) { @@ -190,19 +194,54 @@ public void ungrabFocus() { if (content != null) content.focusUngrabbed(); } + + @Override + public void setScaleFactor(int scaleFactor) { + if (scaleFactor != this.scaleFactor) { + if (!copyBufferEnabled) content.paintLock(); + try { + if (bbImage != null) { + resizeBuffer(getWidth(), getHeight(), scaleFactor); + } + } finally { + if (!copyBufferEnabled) content.paintUnlock(); + } + this.scaleFactor = scaleFactor; + if (getPeer() != null) { + ((FramePeer)getPeer()).notifyScaleFactorChanged(); + } + repaint(); + } + } + + @Override + public void addNotify() { + super.addNotify(); + ((FramePeer)getPeer()).notifyScaleFactorChanged(); + } + + @Override + public int getScaleFactor() { + return scaleFactor; + } - private void syncCopyBuffer(boolean reset, int x, int y, int w, int h) { + private void syncCopyBuffer(boolean reset, int x, int y, int w, int h, int scale) { content.paintLock(); try { int[] srcBuffer = ((DataBufferInt)bbImage.getRaster().getDataBuffer()).getData(); if (reset) { copyBuffer = new int[srcBuffer.length]; } - int linestride = bbImage.getWidth(); - + int linestride = bbImage.getWidth() * scale; + + x *= scale; + y *= scale; + w *= scale; + h *= scale; + for (int i=0; i= newW) && (oldH >= newH)) { - createBB = false; - } else { - if (oldW >= newW) { - newW = oldW; - } else { - newW = Math.max((int)(oldW * 1.2), width); - } - if (oldH >= newH) { - newH = oldH; + try { + boolean createBB = (bbImage == null); + int newW = width; + int newH = height; + if (bbImage != null) { + int imgWidth = bbImage.getWidth(); + int imgHeight = bbImage.getHeight(); + if (width != imgWidth || height != imgHeight) { + createBB = true; + if (bbImage != null) { + int oldW = imgWidth; + int oldH = imgHeight; + if ((oldW >= newW) && (oldH >= newH)) { + createBB = false; } else { - newH = Math.max((int)(oldH * 1.2), height); - } - } - } - if (createBB) { - BufferedImage oldBB = bbImage; - bbImage = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB_PRE); - if (oldBB != null) { - Graphics g = bbImage.getGraphics(); - try { - g.drawImage(oldBB, 0, 0, newW, newH, null); - } finally { - g.dispose(); - oldBB.flush(); + if (oldW >= newW) { + newW = oldW; + } else { + newW = Math.max((int)(oldW * 1.2), width); + } + if (oldH >= newH) { + newH = oldH; + } else { + newH = Math.max((int)(oldH * 1.2), height); + } } } - int[] pixels = ((DataBufferInt)bbImage.getRaster().getDataBuffer()).getData(); - if (copyBufferEnabled) { - syncCopyBuffer(true, 0, 0, width, height); - pixels = copyBuffer; - } - content.imageBufferReset(pixels, 0, 0, width, height, bbImage.getWidth()); - return; } } + if (createBB) { + resizeBuffer(newW, newH, scaleFactor); + return; + } content.imageReshaped(0, 0, width, height); } finally { @@ -339,6 +369,21 @@ } } } + + private void resizeBuffer(int width, int height, int newScaleFactor) { + bbImage = new OffScreenImage(this, width, height, + BufferedImage.TYPE_INT_ARGB_PRE, + newScaleFactor); + bbImage.setReturnLayoutSize(true); + + int[] pixels = ((DataBufferInt)bbImage.getRaster().getDataBuffer()).getData(); + if (copyBufferEnabled) { + syncCopyBuffer(true, 0, 0, width, height, newScaleFactor); + pixels = copyBuffer; + } + content.imageBufferReset(pixels, 0, 0, width, height, + width * newScaleFactor, newScaleFactor); + } @Override public JRootPane getRootPane() { @@ -375,7 +420,19 @@ return getRootPane().getGlassPane(); } - + /** + * Creates an {@link OffScreenImage} with a scale factor + * matching the {@link #getScaleFactor()} value. + * + * @param width the layout width of the image + * @param height the layout height of the image + * @return the HiDPI image + */ + public OffScreenImage createHiDPIImage(int width, int height) { + if (getPeer() == null) return null; + return ((FramePeer)getPeer()).createHiDPIImage(width, height); + } + /* * Notifies client toolkit that it should change a cursor. *