From 7015d8617bb20d33d2e1c3afc5ed92c483798683 Mon Sep 17 00:00:00 2001 From: Billy Olsen Date: Wed, 23 Dec 2020 18:30:53 -0700 Subject: [PATCH] Fix scaling on high dpi monitors GLJPanel handles display scaling better than the GLCanvas does natively. Change to use the GLJPanel always when rendering in 3D mode. FBO (offscreen rendering) will be set on the GLJPanel via the GLCapabilities. Also, ensure when creating a Graphics2D object from a GLOverlay to set the current transform to the default transform for the component. The default transform of the swing components will take into account the scaling of the screen that it is rendered on. By setting the transform of the overlay, we can be sure that it gets the scaling information as well. Fixes #854 Signed-off-by: Billy Olsen --- .../gui/figure3d/RocketFigure3d.java | 66 ++++++++++++------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/figure3d/RocketFigure3d.java b/swing/src/net/sf/openrocket/gui/figure3d/RocketFigure3d.java index 372e18867..26518c290 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/RocketFigure3d.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/RocketFigure3d.java @@ -4,6 +4,7 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; import java.awt.Point; import java.awt.Rectangle; import java.awt.RenderingHints; @@ -157,12 +158,14 @@ public class RocketFigure3d extends JPanel implements GLEventListener { } if (Application.getPreferences().getBoolean(Preferences.OPENGL_USE_FBO, false)) { - log.trace("GL - Creating GLJPanel"); - canvas = new GLJPanel(caps); + log.trace("GL - enabling FBO"); + caps.setFBO(true); } else { - log.trace("GL - Creating GLCanvas"); - canvas = new GLCanvas(caps); + log.trace("GL - disabling FBO"); + caps.setFBO(false); } + log.trace("GL - Creating GLJPanel"); + canvas = new GLJPanel(caps); log.trace("GL - Registering as GLEventListener on canvas"); ((GLAutoDrawable) canvas).addGLEventListener(this); @@ -330,10 +333,27 @@ public class RocketFigure3d extends JPanel implements GLEventListener { } + /** + * Creates a Graphics2D object for the overlay. The resultant Graphics2D + * object has the rendering hints set and the transform to match the + * current GraphicsConfiguration this component is rendered on. This takes + * into account things such as DPI Scaling. + * + * @param overlay the overlay to use when creating the Graphics2D object. + * @return Graphics2D a Graphics2D object for the overlay + */ + private Graphics2D createOverlayGraphics(final Overlay overlay) { + final Graphics2D og2d = overlay.createGraphics(); + setRenderingHints(og2d); + GraphicsConfiguration gconf = getGraphicsConfiguration(); + if (gconf != null) { + og2d.setTransform(gconf.getDefaultTransform()); + } + return og2d; + } private void drawCarets(final GL2 gl, final GLU glu) { - final Graphics2D og2d = caretOverlay.createGraphics(); - setRenderingHints(og2d); + final Graphics2D og2d = createOverlayGraphics(caretOverlay); og2d.setBackground(new Color(0, 0, 0, 0)); og2d.clearRect(0, 0, canvas.getWidth(), canvas.getHeight()); @@ -344,28 +364,27 @@ public class RocketFigure3d extends JPanel implements GLEventListener { Coordinate pCG = project(cg, gl, glu); final int d = CARET_SIZE / 2; + double height = canvas.getHeight(); + + /* Need to take the displayScaling into account. If the scaling is not + * taken into account here, the CG and CP carets are placed in the wrong + * location. I *think* that's because the Coordinates returned by project(...) + * are already appropriately scaled - but not 100% certain on that. The + * following does work though. + */ + double displayScale = getGraphicsConfiguration().getDefaultTransform().getScaleX(); + AffineTransform cgTransform = AffineTransform.getTranslateInstance(((pCG.x / displayScale) - d), height - ((pCG.y / displayScale) + d)); + AffineTransform cpTransform = AffineTransform.getTranslateInstance(((pCP.x / displayScale) - d), height - ((pCP.y / displayScale) + d)); //z order the carets if (pCG.z < pCP.z) { //Subtract half of the caret size, so they are centered ( The +/- d in each translate) //Flip the sense of the Y coordinate from GL to normal (Y+ up/down) - og2d.drawRenderedImage( - cpCaretRaster, - AffineTransform.getTranslateInstance((pCP.x - d), - canvas.getHeight() - (pCP.y + d))); - og2d.drawRenderedImage( - cgCaretRaster, - AffineTransform.getTranslateInstance((pCG.x - d), - canvas.getHeight() - (pCG.y + d))); + og2d.drawRenderedImage(cpCaretRaster, cpTransform); + og2d.drawRenderedImage(cgCaretRaster, cgTransform); } else { - og2d.drawRenderedImage( - cgCaretRaster, - AffineTransform.getTranslateInstance((pCG.x - d), - canvas.getHeight() - (pCG.y + d))); - og2d.drawRenderedImage( - cpCaretRaster, - AffineTransform.getTranslateInstance((pCP.x - d), - canvas.getHeight() - (pCP.y + d))); + og2d.drawRenderedImage(cgCaretRaster, cgTransform); + og2d.drawRenderedImage(cpCaretRaster, cpTransform); } og2d.dispose(); @@ -388,8 +407,7 @@ public class RocketFigure3d extends JPanel implements GLEventListener { if (redrawExtras || extrasOverlay.contentsLost()) { log.debug("Redrawing Overlay"); - final Graphics2D og2d = extrasOverlay.createGraphics(); - setRenderingHints(og2d); + final Graphics2D og2d = createOverlayGraphics(extrasOverlay); og2d.setBackground(new Color(0, 0, 0, 0)); og2d.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());