diff --git a/README.md b/README.md
index 52ce99861..a68c9e2fa 100644
--- a/README.md
+++ b/README.md
@@ -26,6 +26,17 @@ The library is licensed under the terms of the GNU Lesser General Public
License (LGPL) version 2.1 or later.
+Using JFreeChart
+----------------
+To use JFreeChart in your projects, add the following dependency to your build tool:
+
+
+ org.jfree
+ jfreechart
+ 1.5.1
+
+
+
Building JFreeChart
-------------------
You can build JFreeChart using Maven. The build requires JDK 8 or later.
@@ -49,6 +60,7 @@ History
-------
##### Version 1.5.1 (not yet released)
+- modify buffer in ChartPanel to handle high DPI displays (bug #170);
- added Catalan translations (PR #117);
- fix for LayeredBarRenderer (bug #169);
- migrated to JUnit 5.
diff --git a/src/main/java/org/jfree/chart/ChartPanel.java b/src/main/java/org/jfree/chart/ChartPanel.java
index e560a3d8a..88ba68b26 100644
--- a/src/main/java/org/jfree/chart/ChartPanel.java
+++ b/src/main/java/org/jfree/chart/ChartPanel.java
@@ -2,7 +2,7 @@
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
- * (C) Copyright 2000-2017, by Object Refinery Limited and Contributors.
+ * (C) Copyright 2000-2020, by Object Refinery Limited and Contributors.
*
* Project Info: http://www.jfree.org/jfreechart/index.html
*
@@ -218,8 +218,8 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.util.ArrayList;
import java.util.EventListener;
-import java.util.Iterator;
import java.util.List;
import java.util.ResourceBundle;
@@ -747,7 +747,7 @@ public ChartPanel(JFreeChart chart, int width, int height,
this.panMask = InputEvent.ALT_MASK;
}
- this.overlays = new java.util.ArrayList();
+ this.overlays = new ArrayList();
}
/**
@@ -1566,12 +1566,21 @@ else if (drawHeight > this.maximumDrawHeight) {
// are we using the chart buffer?
if (this.useBuffer) {
+ // for better rendering on the HiDPI monitors upscaling the buffer to the "native" resoution
+ // instead of using logical one provided by Swing
+ final AffineTransform globalTransform = ((Graphics2D) g).getTransform();
+ final double globalScaleX = globalTransform.getScaleX();
+ final double globalScaleY = globalTransform.getScaleY();
+
+ final int scaledWidth = (int) (available.getWidth() * globalScaleX);
+ final int scaledHeight = (int) (available.getHeight() * globalScaleY);
+
// do we need to resize the buffer?
if ((this.chartBuffer == null)
- || (this.chartBufferWidth != available.getWidth())
- || (this.chartBufferHeight != available.getHeight())) {
- this.chartBufferWidth = (int) available.getWidth();
- this.chartBufferHeight = (int) available.getHeight();
+ || (this.chartBufferWidth != scaledWidth)
+ || (this.chartBufferHeight != scaledHeight)) {
+ this.chartBufferWidth = scaledWidth;
+ this.chartBufferHeight = scaledHeight;
GraphicsConfiguration gc = g2.getDeviceConfiguration();
this.chartBuffer = gc.createCompatibleImage(
this.chartBufferWidth, this.chartBufferHeight,
@@ -1584,17 +1593,19 @@ else if (drawHeight > this.maximumDrawHeight) {
this.refreshBuffer = false; // clear the flag
+ // scale graphics of the buffer to the same value as global
+ // Swing graphics - this allow to paint all elements as usual
+ // but applies all necessary smoothing
+ Graphics2D bufferG2 = (Graphics2D) this.chartBuffer.getGraphics();
+ bufferG2.scale(globalScaleX, globalScaleY);
+
Rectangle2D bufferArea = new Rectangle2D.Double(
- 0, 0, this.chartBufferWidth, this.chartBufferHeight);
+ 0, 0, available.getWidth(), available.getHeight());
// make the background of the buffer clear and transparent
- Graphics2D bufferG2 = (Graphics2D)
- this.chartBuffer.getGraphics();
Composite savedComposite = bufferG2.getComposite();
- bufferG2.setComposite(AlphaComposite.getInstance(
- AlphaComposite.CLEAR, 0.0f));
- Rectangle r = new Rectangle(0, 0, this.chartBufferWidth,
- this.chartBufferHeight);
+ bufferG2.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f));
+ Rectangle r = new Rectangle(0, 0, (int) available.getWidth(), (int) available.getHeight());
bufferG2.fill(r);
bufferG2.setComposite(savedComposite);
@@ -1614,7 +1625,7 @@ else if (drawHeight > this.maximumDrawHeight) {
}
// zap the buffer onto the panel...
- g2.drawImage(this.chartBuffer, insets.left, insets.top, this);
+ g2.drawImage(this.chartBuffer, insets.left, insets.top, (int) available.getWidth(), (int) available.getHeight(), this);
} else { // redrawing the chart every time...
AffineTransform saved = g2.getTransform();