8153522: Update JLightweightFrame to allow non-integer (and X/Y) scales

Reviewed-by: alexsch
This commit is contained in:
Semyon Sadetsky 2016-11-07 10:36:52 +03:00
parent 6dc331a5e3
commit 57dc20d541
4 changed files with 155 additions and 45 deletions

View File

@ -196,7 +196,8 @@ public class CPlatformLWWindow extends CPlatformWindow {
getLocalGraphicsEnvironment();
LWLightweightFramePeer peer = (LWLightweightFramePeer)getPeer();
int scale = ((LightweightFrame)peer.getTarget()).getScaleFactor();
int scale =(int) Math.round(((LightweightFrame)peer.getTarget())
.getScaleFactorX());
Rectangle bounds = ((LightweightFrame)peer.getTarget()).getHostBounds();
for (GraphicsDevice d : ge.getScreenDevices()) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -141,16 +141,51 @@ public abstract class LightweightFrame extends Frame {
*
* @return the scale factor
* @see #notifyDisplayChanged(int)
* @Depricated replaced by {@link #getScaleFactorX()} and
* {@link #getScaleFactorY}
*/
@Deprecated(since = "9")
public abstract int getScaleFactor();
/**
* Returns the scale factor of this frame along x coordinate. The default
* value is 1.
*
* @return the x coordinate scale factor
* @see #notifyDisplayChanged(double, double)
* @since 9
*/
public abstract double getScaleFactorX();
/**
* Returns the scale factor of this frame along y coordinate. The default
* value is 1.
*
* @return the y coordinate scale factor
* @see #notifyDisplayChanged(double, double)
* @since 9
*/
public abstract double getScaleFactorY();
/**
* Called when display of the hosted frame is changed.
*
* @param scaleFactor the scale factor
* @Depricated replaced by {@link #notifyDisplayChanged(double, double)}
*/
@Deprecated(since = "9")
public abstract void notifyDisplayChanged(int scaleFactor);
/**
* Called when display of the hosted frame is changed.
*
* @param scaleFactorX the scale factor
* @param scaleFactorY the scale factor
* @since 9
*/
public abstract void notifyDisplayChanged(double scaleFactorX,
double scaleFactorY);
/**
* Host window absolute bounds.
*/
@ -202,4 +237,5 @@ public abstract class LightweightFrame extends Frame {
* Removes a drop target from the lightweight frame.
*/
public abstract void removeDropTarget(DropTarget dt);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,18 +25,7 @@
package sun.swing;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.*;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragGestureRecognizer;
@ -46,6 +35,7 @@ import java.awt.dnd.InvalidDnDOperationException;
import java.awt.dnd.peer.DragSourceContextPeer;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.beans.PropertyChangeEvent;
@ -89,7 +79,8 @@ public final class JLightweightFrame extends LightweightFrame implements RootPan
private BufferedImage bbImage;
private volatile int scaleFactor = 1;
private volatile double scaleFactorX;
private volatile double scaleFactorY;
/**
* {@code copyBufferEnabled}, true by default, defines the following strategy.
@ -124,6 +115,10 @@ public final class JLightweightFrame extends LightweightFrame implements RootPan
*/
public JLightweightFrame() {
super();
AffineTransform defaultTransform =
getGraphicsConfiguration().getDefaultTransform();
scaleFactorX = defaultTransform.getScaleX();
scaleFactorY = defaultTransform.getScaleY();
copyBufferEnabled = "true".equals(AccessController.
doPrivileged(new GetPropertyAction("swing.jlf.copyBufferEnabled", "true")));
@ -157,8 +152,9 @@ public final class JLightweightFrame extends LightweightFrame implements RootPan
}
Point p = SwingUtilities.convertPoint(c, x, y, jlf);
Rectangle r = new Rectangle(p.x, p.y, w, h).intersection(
new Rectangle(0, 0, bbImage.getWidth() / scaleFactor,
bbImage.getHeight() / scaleFactor));
new Rectangle(0, 0,
(int)Math.round(bbImage.getWidth() / scaleFactorX),
(int)Math.round(bbImage.getHeight() / scaleFactorY)));
if (!r.isEmpty()) {
notifyImageUpdated(r.x, r.y, r.width, r.height);
@ -212,7 +208,7 @@ public final class JLightweightFrame extends LightweightFrame implements RootPan
g.setBackground(getBackground());
g.setColor(getForeground());
g.setFont(getFont());
g.scale(scaleFactor, scaleFactor);
g.scale(scaleFactorX, scaleFactorY);
return g;
}
@ -237,28 +233,52 @@ public final class JLightweightFrame extends LightweightFrame implements RootPan
}
@Override
@SuppressWarnings("deprecation")
public int getScaleFactor() {
return scaleFactor;
return (int)scaleFactorX;
}
@Override
public double getScaleFactorX() {
return scaleFactorX;
}
@Override
public double getScaleFactorY() {
return scaleFactorY;
}
@Override
public void notifyDisplayChanged(final int scaleFactor) {
if (scaleFactor != this.scaleFactor) {
notifyDisplayChanged(scaleFactor, scaleFactor);
}
@Override
public void notifyDisplayChanged(final double scaleFactorX,
final double scaleFactorY) {
if (Double.compare(scaleFactorX, this.scaleFactorX) != 0 ||
Double.compare(scaleFactorY, this.scaleFactorY) != 0) {
if (!copyBufferEnabled) content.paintLock();
try {
if (bbImage != null) {
resizeBuffer(getWidth(), getHeight(), scaleFactor);
resizeBuffer(getWidth(), getHeight(), scaleFactorX,
scaleFactorY);
}
} finally {
if (!copyBufferEnabled) content.paintUnlock();
}
this.scaleFactor = scaleFactor;
this.scaleFactorX = scaleFactorX;
this.scaleFactorY = scaleFactorY;
if(isVisible()) {
final Object peer =
AWTAccessor.getComponentAccessor().getPeer(this);
if (peer instanceof DisplayChangedListener) {
((DisplayChangedListener) peer).displayChanged();
}
repaint();
}
}
final Object peer = AWTAccessor.getComponentAccessor().getPeer(this);
if (peer instanceof DisplayChangedListener) {
((DisplayChangedListener) peer).displayChanged();
}
repaint();
}
@Override
@ -270,7 +290,8 @@ public final class JLightweightFrame extends LightweightFrame implements RootPan
}
}
private void syncCopyBuffer(boolean reset, int x, int y, int w, int h, int scale) {
private void syncCopyBuffer(boolean reset, int x, int y, int w, int h,
double scaleX, double scaleY) {
content.paintLock();
try {
int[] srcBuffer = ((DataBufferInt)bbImage.getRaster().getDataBuffer()).getData();
@ -279,14 +300,14 @@ public final class JLightweightFrame extends LightweightFrame implements RootPan
}
int linestride = bbImage.getWidth();
x *= scale;
y *= scale;
w *= scale;
h *= scale;
int startX = (int)Math.floor(x * scaleX);
int startY = (int)Math.floor(y * scaleY);
int width = (int)Math.ceil((x + w) * scaleX) - startX;
int height = (int)Math.ceil((y + h) * scaleY) - startY;
for (int i=0; i<h; i++) {
int from = (y + i) * linestride + x;
System.arraycopy(srcBuffer, from, copyBuffer, from, w);
for (int i = 0; i < height; i++) {
int from = (startY + i) * linestride + startX;
System.arraycopy(srcBuffer, from, copyBuffer, from, width);
}
} finally {
content.paintUnlock();
@ -295,7 +316,8 @@ public final class JLightweightFrame extends LightweightFrame implements RootPan
private void notifyImageUpdated(int x, int y, int width, int height) {
if (copyBufferEnabled) {
syncCopyBuffer(false, x, y, width, height, scaleFactor);
syncCopyBuffer(false, x, y, width, height, scaleFactorX,
scaleFactorY);
}
content.imageUpdated(x, y, width, height);
}
@ -382,8 +404,10 @@ public final class JLightweightFrame extends LightweightFrame implements RootPan
int newW = width;
int newH = height;
if (bbImage != null) {
int imgWidth = bbImage.getWidth() / scaleFactor;
int imgHeight = bbImage.getHeight() / scaleFactor;
int imgWidth = (int)Math.round(bbImage.getWidth() /
scaleFactorX);
int imgHeight = (int)Math.round(bbImage.getHeight() /
scaleFactorY);
if (width != imgWidth || height != imgHeight) {
createBB = true;
if (bbImage != null) {
@ -407,7 +431,7 @@ public final class JLightweightFrame extends LightweightFrame implements RootPan
}
}
if (createBB) {
resizeBuffer(newW, newH, scaleFactor);
resizeBuffer(newW, newH, scaleFactorX, scaleFactorY);
return;
}
content.imageReshaped(0, 0, width, height);
@ -419,16 +443,19 @@ public final class JLightweightFrame extends LightweightFrame implements RootPan
}
}
private void resizeBuffer(int width, int height, int newScaleFactor) {
bbImage = new BufferedImage(width*newScaleFactor,height*newScaleFactor,
private void resizeBuffer(int width, int height, double newScaleFactorX,
double newScaleFactorY) {
bbImage = new BufferedImage((int)Math.round(width * newScaleFactorX),
(int)Math.round(height * newScaleFactorY),
BufferedImage.TYPE_INT_ARGB_PRE);
int[] pixels= ((DataBufferInt)bbImage.getRaster().getDataBuffer()).getData();
if (copyBufferEnabled) {
syncCopyBuffer(true, 0, 0, width, height, newScaleFactor);
syncCopyBuffer(true, 0, 0, width, height, newScaleFactorX,
newScaleFactorY);
pixels = copyBuffer;
}
content.imageBufferReset(pixels, 0, 0, width, height,
width * newScaleFactor, newScaleFactor);
bbImage.getWidth(), newScaleFactorX, newScaleFactorY);
}
@Override

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2016 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -117,7 +117,10 @@ public interface LightweightContent {
* @param height the logical height of the image
* @param linestride the line stride of the pixel buffer
* @param scale the scale factor of the pixel buffer
* @Depricated replaced by
* {@link #imageBufferReset(int[],int,int,int,int,int,double,double)}
*/
@Deprecated(since = "9")
default public void imageBufferReset(int[] data,
int x, int y,
int width, int height,
@ -127,12 +130,55 @@ public interface LightweightContent {
imageBufferReset(data, x, y, width, height, linestride);
}
/**
* {@code JLightweightFrame} calls this method to notify the client
* application that a new data buffer has been set as a content pixel
* buffer. Typically this occurs when a buffer of a larger size is
* created in response to a content resize event.
* <p>
* The method reports a reference to the pixel data buffer, the content
* image bounds within the buffer and the line stride of the buffer.
* These values have the following correlation.
* The {@code width} and {@code height} matches the layout size of the
* content (the component returned from the {@link #getComponent} method).
* The {@code x} and {@code y} is the origin of the content, {@code (0, 0)}
* in the layout coordinate space of the content, appearing at
* {@code data[y * scaleY * linestride + x * scaleX]} in the buffer.
* A pixel with indices {@code (i, j)}, where {@code (0 <= i < width)} and
* {@code (0 <= j < height)}, in the layout coordinate space of the content
* is represented by a {@code scaleX * scaleY} square of pixels in the
* physical coordinate space of the buffer. The top-left corner of the
* square has the following physical coordinate in the buffer:
* {@code data[(y + j) * scaleY * linestride + (x + i) * scaleX]}.
*
* @param data the content pixel data buffer of INT_ARGB_PRE type
* @param x the logical x coordinate of the image
* @param y the logical y coordinate of the image
* @param width the logical width of the image
* @param height the logical height of the image
* @param linestride the line stride of the pixel buffer
* @param scaleX the x coordinate scale factor of the pixel buffer
* @param scaleY the y coordinate scale factor of the pixel buffer
* @since 9
*/
@SuppressWarnings("deprecation")
default public void imageBufferReset(int[] data,
int x, int y,
int width, int height,
int linestride,
double scaleX, double scaleY)
{
imageBufferReset(data, x, y, width, height, linestride,
(int)Math.round(scaleX));
}
/**
* The default implementation for #imageBufferReset uses a hard-coded value
* of 1 for the scale factor. Both the old and the new methods provide
* default implementations in order to allow a client application to run
* with any JDK version without breaking backward compatibility.
*/
@SuppressWarnings("deprecation")
default public void imageBufferReset(int[] data,
int x, int y,
int width, int height,