diff options
author | Sven Gothel <sgothel@jausoft.com> | 2013-09-19 03:21:15 +0200 |
---|---|---|
committer | Sven Gothel <sgothel@jausoft.com> | 2013-09-19 03:21:15 +0200 |
commit | 8a4a64e1a3e9beb09580ba95fe85026abf2ff106 (patch) | |
tree | aab4881100a2b55c3068cb591caf44414ed2a352 /src | |
parent | 94117c091a253903d164a2934ea8ab1d70e9003e (diff) |
AWTTilePainter.setupGraphics2DAndClipBounds(): Use 'Shape getClip()'; Use double precicion clip bounds 'all the way'; Explicitly scale image and clip w/ current scaled transform.
- Use 'Shape getClip()'
Don't assume Rectangle2D, but use Shape's getBounds2D()
- Use double precicion clip bounds 'all the way'
Remove rounding error on clip bounds w/ start value, which was _not_ using doubles.
- Explicitly scale image and clip w/ current scaled transform.
Instead of abusing Graphics2D's clip shape to scale image size and clip-area,
explicitly use transform both bounding boxes into transformed space,
scale space and transform out (inversion).
A possible NoninvertibleTransformException will be thrown while Graphics2D has not been modified.
Diffstat (limited to 'src')
4 files changed, 93 insertions, 64 deletions
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index c43f218df..1ab30547a 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -53,6 +53,7 @@ import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; +import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.Rectangle2D; import java.awt.EventQueue; @@ -835,21 +836,26 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing sendReshape = false; // clear reshape flag final Graphics2D g2d = (Graphics2D)graphics; - printAWTTiles.setupGraphics2DAndClipBounds(g2d, getWidth(), getHeight()); try { - final TileRenderer tileRenderer = printAWTTiles.renderer; - if( DEBUG ) { - System.err.println("AWT print.0: "+tileRenderer); - } - do { - if( printGLAD != GLCanvas.this ) { - tileRenderer.display(); - } else { - Threading.invoke(true, displayOnEDTAction, getTreeLock()); + printAWTTiles.setupGraphics2DAndClipBounds(g2d, getWidth(), getHeight()); + try { + final TileRenderer tileRenderer = printAWTTiles.renderer; + if( DEBUG ) { + System.err.println("AWT print.0: "+tileRenderer); } - } while ( !tileRenderer.eot() ); - } finally { - printAWTTiles.resetGraphics2D(); + do { + if( printGLAD != GLCanvas.this ) { + tileRenderer.display(); + } else { + Threading.invoke(true, displayOnEDTAction, getTreeLock()); + } + } while ( !tileRenderer.eot() ); + } finally { + printAWTTiles.resetGraphics2D(); + } + } catch (NoninvertibleTransformException nte) { + System.err.println("Catched: Inversion failed of: "+g2d.getTransform()); + nte.printStackTrace(); } if( DEBUG ) { System.err.println("AWT print.X: "+printAWTTiles); diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index c66fba70b..e9d1b38d2 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -48,6 +48,7 @@ import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.GraphicsEnvironment; import java.awt.Rectangle; +import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.DataBufferInt; @@ -612,18 +613,23 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing handleReshape = false; // ditto final Graphics2D g2d = (Graphics2D)graphics; - printAWTTiles.setupGraphics2DAndClipBounds(g2d, getWidth(), getHeight()); try { - final TileRenderer tileRenderer = printAWTTiles.renderer; - do { - if( printGLAD != GLJPanel.this ) { - tileRenderer.display(); - } else { - backend.doPlainPaint(); - } - } while ( !tileRenderer.eot() ); - } finally { - printAWTTiles.resetGraphics2D(); + printAWTTiles.setupGraphics2DAndClipBounds(g2d, getWidth(), getHeight()); + try { + final TileRenderer tileRenderer = printAWTTiles.renderer; + do { + if( printGLAD != GLJPanel.this ) { + tileRenderer.display(); + } else { + backend.doPlainPaint(); + } + } while ( !tileRenderer.eot() ); + } finally { + printAWTTiles.resetGraphics2D(); + } + } catch (NoninvertibleTransformException nte) { + System.err.println("Catched: Inversion failed of: "+g2d.getTransform()); + nte.printStackTrace(); } if( DEBUG ) { System.err.println("AWT print.X: "+printAWTTiles); diff --git a/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java b/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java index f3aba3902..0b24fadae 100644 --- a/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java +++ b/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java @@ -33,6 +33,7 @@ import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.geom.AffineTransform; +import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.DataBufferInt; @@ -148,18 +149,22 @@ public class AWTTilePainter { return new Rectangle((int)Math.round(r.getX()), (int)Math.round(r.getY()), (int)Math.round(r.getWidth()), (int)Math.round(r.getHeight())); } - private static Rectangle clipNegative(Rectangle in) { + private static Rectangle2D getClipBounds2D(Graphics2D g) { + final Shape shape = g.getClip(); + return null != shape ? shape.getBounds2D() : null; + } + private static Rectangle2D clipNegative(Rectangle2D in) { if( null == in ) { return null; } - final Rectangle out = new Rectangle(in); - if( 0 > out.x ) { - out.width += out.x; - out.x = 0; + double x=in.getX(), y=in.getY(), width=in.getWidth(), height=in.getHeight(); + if( 0 > x ) { + width += x; + x = 0; } - if( 0 > out.y ) { - out.height += out.y; - out.y = 0; + if( 0 > y ) { + height += y; + y = 0; } - return out; + return new Rectangle2D.Double(x, y, width, height); } /** @@ -177,35 +182,37 @@ public class AWTTilePainter { * @param g2d Graphics2D instance used for transform and clipping * @param width width of the AWT component in case clipping is null * @param height height of the AWT component in case clipping is null + * @throws NoninvertibleTransformException if the {@link Graphics2D}'s {@link AffineTransform} {@link AffineTransform#invert() inversion} fails. + * Since inversion is tested before scaling the given {@link Graphics2D}, caller shall ignore the whole <i>term</i>. */ - public void setupGraphics2DAndClipBounds(Graphics2D g2d, int width, int height) { + public void setupGraphics2DAndClipBounds(Graphics2D g2d, int width, int height) throws NoninvertibleTransformException { this.g2d = g2d; saveAT = g2d.getTransform(); - final Rectangle gClipOrigR; - final Rectangle2D dClipOrig, dImageSizeOrig; // double precision for scaling - // setup original rectangles - { - gClipOrigR = g2d.getClipBounds(); - final Rectangle gClipOrig = clipNegative(gClipOrigR); - dClipOrig = null != gClipOrig ? new Rectangle2D.Double(gClipOrig.getX(), gClipOrig.getY(), gClipOrig.getWidth(), gClipOrig.getHeight()) : null; - dImageSizeOrig = new Rectangle2D.Double(0, 0, width, height); - } - final Rectangle2D dClipScaled, dImageSizeScaled; // double precision for scaling - // retrieve scaled image-size and clip-bounds + // We use double precision for scaling + // + // Setup original rectangles + final Rectangle2D dClipOrigR = getClipBounds2D(g2d); + final Rectangle2D dClipOrig = clipNegative(dClipOrigR); + final Rectangle2D dImageSizeOrig = new Rectangle2D.Double(0, 0, width, height); + + // Retrieve scaled image-size and clip-bounds + final Rectangle2D dImageSizeScaled, dClipScaled; { - g2d.setClip(dImageSizeOrig); - g2d.scale(scaleMatX, scaleMatY); - dImageSizeScaled = (Rectangle2D) g2d.getClip(); + final AffineTransform scaledATI; + { + final AffineTransform scaledAT = g2d.getTransform(); + scaledAT.scale(scaleMatX, scaleMatY); + scaledATI = scaledAT.createInverse(); // -> NoninvertibleTransformException + } + Shape s0 = saveAT.createTransformedShape(dImageSizeOrig); // user in + dImageSizeScaled = scaledATI.createTransformedShape(s0).getBounds2D(); // scaled out if( null == dClipOrig ) { - g2d.setClip(null); dClipScaled = (Rectangle2D) dImageSizeScaled.clone(); } else { - g2d.setTransform(saveAT); // reset - g2d.setClip(dClipOrig); - g2d.scale(scaleMatX, scaleMatY); - dClipScaled = (Rectangle2D) g2d.getClip(); + s0 = saveAT.createTransformedShape(dClipOrig); // user in + dClipScaled = scaledATI.createTransformedShape(s0).getBounds2D(); // scaled out } - } + } final Rectangle iClipScaled = getRoundedRect(dClipScaled); final Rectangle iImageSizeScaled = getRoundedRect(dImageSizeScaled); scaledYOffset = iClipScaled.y; @@ -213,9 +220,13 @@ public class AWTTilePainter { renderer.clipImageSize(iClipScaled.width, iClipScaled.height); final int clipH = Math.min(iImageSizeScaled.height, iClipScaled.height); renderer.setTileOffset(iClipScaled.x, iImageSizeScaled.height - ( iClipScaled.y + clipH )); + + // Scale actual Grahics2D matrix + g2d.scale(scaleMatX, scaleMatY); + if( verbose ) { System.err.println("AWT print.0: image "+dImageSizeOrig + " -> " + dImageSizeScaled + " -> " + iImageSizeScaled); - System.err.println("AWT print.0: clip "+gClipOrigR + " -> " + dClipOrig + " -> " + dClipScaled + " -> " + iClipScaled); + System.err.println("AWT print.0: clip "+dClipOrigR + " -> " + dClipOrig + " -> " + dClipScaled + " -> " + iClipScaled); System.err.println("AWT print.0: "+renderer); } } diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index 64e9bb0f6..374a80325 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -37,6 +37,7 @@ import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.KeyboardFocusManager; +import java.awt.geom.NoninvertibleTransformException; import java.beans.Beans; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -577,17 +578,22 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto } final Graphics2D g2d = (Graphics2D)graphics; - printAWTTiles.setupGraphics2DAndClipBounds(g2d, getWidth(), getHeight()); try { - final TileRenderer tileRenderer = printAWTTiles.renderer; - if( DEBUG ) { - System.err.println("AWT print.0: "+tileRenderer); + printAWTTiles.setupGraphics2DAndClipBounds(g2d, getWidth(), getHeight()); + try { + final TileRenderer tileRenderer = printAWTTiles.renderer; + if( DEBUG ) { + System.err.println("AWT print.0: "+tileRenderer); + } + do { + tileRenderer.display(); + } while ( !tileRenderer.eot() ); + } finally { + printAWTTiles.resetGraphics2D(); } - do { - tileRenderer.display(); - } while ( !tileRenderer.eot() ); - } finally { - printAWTTiles.resetGraphics2D(); + } catch (NoninvertibleTransformException nte) { + System.err.println("Catched: Inversion failed of: "+g2d.getTransform()); + nte.printStackTrace(); } if( DEBUG ) { System.err.println("AWT print.X: "+printAWTTiles); |