src/share/classes/sun/swing/JLightweightFrame.java

Print this page

        

@@ -39,10 +39,11 @@
 import java.awt.Window;
 import java.awt.event.ContainerEvent;
 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;
 import javax.swing.JComponent;
 

@@ -53,10 +54,11 @@
 import javax.swing.RepaintManager;
 import javax.swing.RootPaneContainer;
 import javax.swing.SwingUtilities;
 
 import sun.awt.LightweightFrame;
+import sun.awt.image.OffScreenImage;
 import sun.security.action.GetPropertyAction;
 import sun.swing.SwingUtilities2.RepaintListener;
 
 /**
  * The frame serves as a lightweight container which paints its content

@@ -76,11 +78,13 @@
     private LightweightContent content;
 
     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.
      * The copy buffer is synchronized with the original buffer every time the

@@ -88,11 +92,11 @@
      * to the {@link LightweightContent#imageBufferReset} method. The code spot
      * which synchronizes two buffers becomes the only critical section guarded
      * 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;
     private RepaintListener repaintListener;
 

@@ -101,20 +105,20 @@
             @Override
             public void updateCursor(JLightweightFrame frame) {
                 frame.updateClientCursor();
             }
         });
+        copyBufferEnabled = "true".equals(AccessController.
+            doPrivileged(new GetPropertyAction("swing.jlf.copyBufferEnabled", "true")));
     }
 
     /**
      * Constructs a new, initially invisible {@code JLightweightFrame}
      * instance.
      */
     public JLightweightFrame() {
         super();
-        copyBufferEnabled = "true".equals(AccessController.
-            doPrivileged(new GetPropertyAction("swing.jlf.copyBufferEnabled", "true")));
 
         add(rootPane, BorderLayout.CENTER);
         setFocusTraversalPolicy(new LayoutFocusTraversalPolicy());
         if (getGraphicsConfiguration().isTranslucencyCapable()) {
             setBackground(new Color(0, 0, 0, 0));

@@ -219,18 +223,53 @@
     @Override
     public void ungrabFocus() {
         if (content != null) content.focusUngrabbed();
     }
 
-    private void syncCopyBuffer(boolean reset, int x, int y, int w, int h) {
+    @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, 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<h; i++) {
                 int from = (y + i) * linestride + x;
                 System.arraycopy(srcBuffer, from, copyBuffer, from, w);
             }

@@ -239,11 +278,11 @@
         }
     }
 
     private void notifyImageUpdated(int x, int y, int width, int height) {
         if (copyBufferEnabled) {
-            syncCopyBuffer(false, x, y, width, height);
+            syncCopyBuffer(false, x, y, width, height, scaleFactor);
         }
         content.imageUpdated(x, y, width, height);
     }
 
     @SuppressWarnings("serial") // anonymous class inside

@@ -267,11 +306,12 @@
                     clip.height = Math.min(contentPane.getHeight(), clip.height);
 
                     EventQueue.invokeLater(new Runnable() {
                         @Override
                         public void run() {
-                            notifyImageUpdated(clip.x, clip.y, clip.width, clip.height);
+                            Rectangle c = contentPane.getBounds().intersection(clip);
+                            notifyImageUpdated(c.x, c.y, c.width, c.height);
                         }
                     });
                 } finally {
                     if (!copyBufferEnabled) {
                         content.paintUnlock();

@@ -321,17 +361,21 @@
         }
         if (!copyBufferEnabled) {
             content.paintLock();
         }
         try {
-            if ((bbImage == null) || (width != bbImage.getWidth()) || (height != bbImage.getHeight())) {
-                boolean createBB = true;
+            boolean createBB = (bbImage == null);
                 int newW = width;
                 int newH = height;
                 if (bbImage != null) {
-                    int oldW = bbImage.getWidth();
-                    int oldH = bbImage.getHeight();
+                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 {
                         if (oldW >= newW) {
                             newW = oldW;

@@ -343,40 +387,40 @@
                         } 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();
                         }
                     }
-                    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());
+            if (createBB) {
+                resizeBuffer(newW, newH, scaleFactor);
                     return;
                 }
-            }
             content.imageReshaped(0, 0, width, height);
 
         } finally {
             if (!copyBufferEnabled) {
                 content.paintUnlock();
             }
         }
     }
 
+    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() {
         return rootPane;
     }
 

@@ -408,10 +452,22 @@
     @Override
     public Component getGlassPane() {
         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.
      *
      * Called from the peer via SwingAccessor, because the