From 4b5e77961d1c660f3537f4041fc1a3ce47ef105c Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Sat, 7 Sep 2013 12:52:19 +0200
Subject: AWT/GL Printing WIP: Abstract AWT tile painting code out to
 AWTTilePainter, reused w/ GLCanvas and GLJPanel

---
 .../classes/javax/media/opengl/awt/GLCanvas.java   | 186 ++++--------------
 .../classes/javax/media/opengl/awt/GLJPanel.java   | 198 ++++---------------
 .../classes/jogamp/opengl/awt/AWTTilePainter.java  | 217 +++++++++++++++++++++
 3 files changed, 300 insertions(+), 301 deletions(-)
 create mode 100644 src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java

diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index 4ff25d0e6..5ada2d80f 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -53,13 +53,9 @@ import java.awt.Graphics;
 import java.awt.Graphics2D;
 import java.awt.GraphicsConfiguration;
 import java.awt.GraphicsDevice;
-import java.awt.Rectangle;
 import java.awt.RenderingHints;
-import java.awt.Shape;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
-import java.awt.image.DataBufferInt;
 
 import java.awt.EventQueue;
 import java.lang.reflect.InvocationTargetException;
@@ -107,16 +103,13 @@ import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
 import com.jogamp.nativewindow.awt.JAWTWindow;
 import com.jogamp.opengl.JoglVersion;
 import com.jogamp.opengl.util.GLDrawableUtil;
-import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
 import com.jogamp.opengl.util.TileRenderer;
-import com.jogamp.opengl.util.TileRendererBase;
-import com.jogamp.opengl.util.awt.AWTGLPixelBuffer;
-import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.AWTGLPixelBufferProvider;
 
 import jogamp.opengl.Debug;
 import jogamp.opengl.GLContextImpl;
 import jogamp.opengl.GLDrawableHelper;
 import jogamp.opengl.GLDrawableImpl;
+import jogamp.opengl.awt.AWTTilePainter;
 
 // FIXME: Subclasses need to call resetGLFunctionAvailability() on their
 // context whenever the displayChanged() function is called on our
@@ -738,12 +731,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
 
   private static final int PRINT_TILE_SIZE = 512;
   private volatile boolean printActive = false;
-  private GLOffscreenAutoDrawable printGLAD = null;
-  private TileRenderer printRenderer = null;
   private GLAnimatorControl printAnimator = null; 
-  private AWTGLPixelBuffer printBuffer = null;
-  private BufferedImage printVFlipImage = null;
-  private Graphics2D printGraphics = null;
+  private GLOffscreenAutoDrawable printGLAD = null;
+  private AWTTilePainter printAWTTiles = null;
   
   @Override
   public void setupPrint() {
@@ -777,95 +767,15 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
           printGLAD = factory.createOffscreenAutoDrawable(null, caps, null, PRINT_TILE_SIZE, PRINT_TILE_SIZE, null);
           GLDrawableUtil.swapGLContextAndAllGLEventListener(GLCanvas.this, printGLAD);
           destroyOnEDTAction.run();
-          printRenderer = new TileRenderer();
-          printRenderer.setRowOrder(TileRenderer.TR_TOP_TO_BOTTOM);
+          
+          final int componentCount = isOpaque() ? 3 : 4;
+          final TileRenderer printRenderer = new TileRenderer();
           printRenderer.setTileSize(printGLAD.getWidth(), printGLAD.getHeight(), 0);
           printRenderer.attachToAutoDrawable(printGLAD);
-
-          final GLEventListener preTileGLEL = new GLEventListener() {
-              @Override
-              public void init(GLAutoDrawable drawable) {
-              }
-              @Override
-              public void dispose(GLAutoDrawable drawable) {}
-              @Override
-              public void display(GLAutoDrawable drawable) {
-                  final GL gl = drawable.getGL();
-                  if( null == printBuffer ) {
-                      final int componentCount = isOpaque() ? 3 : 4;
-                      final AWTGLPixelBufferProvider printBufferProvider = new AWTGLPixelBufferProvider( true /* allowRowStride */ );      
-                      final GLPixelAttributes pixelAttribs = printBufferProvider.getAttributes(gl, componentCount);
-                      printBuffer = printBufferProvider.allocate(gl, pixelAttribs, printGLAD.getWidth(), printGLAD.getHeight(), 1, true, 0);
-                      printRenderer.setTileBuffer(printBuffer);
-                      printVFlipImage = new BufferedImage(printBuffer.width, printBuffer.height, printBuffer.image.getType());
-                  }
-                  System.err.println("XXX tile-pre "+printRenderer); // FIXME
-              }
-              @Override
-              public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {}
-          };
-          final GLEventListener postTileGLEL = new GLEventListener() {
-              int tTopRowHeight = 0;
-              @Override
-              public void init(GLAutoDrawable drawable) {
-                  tTopRowHeight = 0;
-              }
-              @Override
-              public void dispose(GLAutoDrawable drawable) {}
-              @Override
-              public void display(GLAutoDrawable drawable) {              
-                  // Copy temporary data into raster of BufferedImage for faster
-                  // blitting Note that we could avoid this copy in the cases
-                  // where !offscreenDrawable.isGLOriented(),
-                  // but that's the software rendering path which is very slow anyway.
-                  final int tHeight = printRenderer.getParam(TileRendererBase.TR_CURRENT_TILE_HEIGHT);
-                  final int tWidth = printRenderer.getParam(TileRendererBase.TR_CURRENT_TILE_WIDTH);
-                  // final BufferedImage dstImage = printBuffer.image;
-                  final BufferedImage srcImage = printBuffer.image;
-                  final BufferedImage dstImage = printVFlipImage;
-                  final int[] src = ((DataBufferInt) srcImage.getRaster().getDataBuffer()).getData();
-                  final int[] dst = ((DataBufferInt) dstImage.getRaster().getDataBuffer()).getData();
-                  final int incr = printBuffer.width;
-                  int srcPos = 0;
-                  int destPos = (tHeight - 1) * printBuffer.width;
-                  for (; destPos >= 0; srcPos += incr, destPos -= incr) {
-                      System.arraycopy(src, srcPos, dst, destPos, incr);
-                  }
-                  // Draw resulting image in one shot
-                  final int tRows = printRenderer.getParam(TileRenderer.TR_ROWS);
-                  final int tRow = printRenderer.getParam(TileRenderer.TR_CURRENT_ROW);
-                  final int pX = printRenderer.getParam(TileRendererBase.TR_CURRENT_TILE_X_POS); 
-                  final int pYf;
-                  if( tRow == tRows - 1 ) {
-                      tTopRowHeight = tHeight;
-                      pYf = 0;
-                  } else if( tRow == tRows - 2 ){
-                      pYf = tTopRowHeight;
-                  } else {
-                      pYf = ( tRows - 2 - tRow ) * tHeight + tTopRowHeight;
-                  }
-                  final Shape oClip = printGraphics.getClip();
-                  printGraphics.clipRect(pX, pYf, tWidth, tHeight);
-                  final Shape clip = printGraphics.getClip();
-                  printGraphics.drawImage(dstImage, pX, pYf, dstImage.getWidth(), dstImage.getHeight(), null); // Null ImageObserver since image data is ready.
-                  printGraphics.setColor(Color.BLACK);
-                  printGraphics.drawRect(pX, pYf, tWidth, tHeight);
-                  {
-                      final Rectangle r = oClip.getBounds();
-                      printGraphics.setColor(Color.YELLOW);
-                      printGraphics.drawRect(r.x, r.y, r.width, r.height);
-                  }
-                  printGraphics.setClip(oClip);
-                  System.err.println("XXX tile-post.X clip "+oClip+" -> "+clip);
-                  System.err.println("XXX tile-post.X "+printRenderer);
-                  System.err.println("XXX tile-post.X dst-img "+dstImage.getWidth()+"x"+dstImage.getHeight()+" -> "+pX+"/"+pYf); // +", "+dstImage); // FIXME
-              }
-              @Override
-              public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {}
-          };      
-          printRenderer.setGLEventListener(preTileGLEL, postTileGLEL);
-
-          System.err.println("AWT print.setup "+printRenderer); // FIXME
+          printAWTTiles = new AWTTilePainter(printRenderer, componentCount, DEBUG);
+          if( DEBUG ) {
+              System.err.println("AWT print.setup "+printAWTTiles);
+          }
       }
   };
   
@@ -882,26 +792,19 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
   private final Runnable releasePrintOnEDT = new Runnable() {
       @Override
       public void run() {
-          printRenderer.detachFromAutoDrawable(); // tile-renderer -> printGLAD
+          if( DEBUG ) {
+              System.err.println("AWT print.release "+printAWTTiles);
+          }
+          printAWTTiles.dispose();
+          printAWTTiles= null;
           createDrawableAndContext( false );
           GLDrawableUtil.swapGLContextAndAllGLEventListener(printGLAD, GLCanvas.this);
           printGLAD.destroy();
+          printGLAD = null;
           if( null != printAnimator ) {
               printAnimator.add(GLCanvas.this);
+              printAnimator = null;
           }
-          System.err.println("AWT print.release "+printRenderer); // FIXME
-          printGLAD = null;
-          printRenderer = null;
-          printAnimator = null;
-          if( null != printBuffer ) {
-              printBuffer.dispose();
-              printBuffer = null;
-          }
-          if( null != printVFlipImage ) {
-              printVFlipImage.flush();
-              printVFlipImage = null;
-          }
-          printGraphics = null;
           printActive = false;
       }
   };
@@ -916,40 +819,33 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
           // we cannot dispatch print on AWT-EDT due to printing internal locking ..
       }
       sendReshape = false; // clear reshape flag
-      printGraphics = (Graphics2D)graphics;
-      System.err.println("AWT print.0: canvasSize "+getWidth()+"x"+getWidth()+", printAnimator "+printAnimator);
-      {
-          final RenderingHints rHints = printGraphics.getRenderingHints();
-          final Set<Entry<Object, Object>> rEntries = rHints.entrySet();
-          int count = 0;
-          for(Iterator<Entry<Object, Object>> rEntryIter = rEntries.iterator(); rEntryIter.hasNext(); count++) {
-              final Entry<Object, Object> rEntry = rEntryIter.next();
-              System.err.println("Hint["+count+"]: "+rEntry.getKey()+" -> "+rEntry.getValue());
+      final Graphics2D printGraphics = (Graphics2D)graphics;
+      if( DEBUG ) {
+          System.err.println("AWT print.0: canvasSize "+getWidth()+"x"+getWidth()+", printAnimator "+printAnimator);
+          {
+              final RenderingHints rHints = printGraphics.getRenderingHints();
+              final Set<Entry<Object, Object>> rEntries = rHints.entrySet();
+              int count = 0;
+              for(Iterator<Entry<Object, Object>> rEntryIter = rEntries.iterator(); rEntryIter.hasNext(); count++) {
+                  final Entry<Object, Object> rEntry = rEntryIter.next();
+                  System.err.println("Hint["+count+"]: "+rEntry.getKey()+" -> "+rEntry.getValue());
+              }
           }
+          final AffineTransform aTrans = printGraphics.getTransform();
+          System.err.println(" scale "+aTrans.getScaleX()+" x "+aTrans.getScaleY());
+          System.err.println(" move "+aTrans.getTranslateX()+" x "+aTrans.getTranslateY());
+      }      
+      printAWTTiles.updateGraphics2DAndClipBounds(printGraphics);
+      final TileRenderer tileRenderer = printAWTTiles.getTileRenderer(); 
+      if( DEBUG ) {
+          System.err.println("AWT print.0: "+tileRenderer);
       }
-      // final GraphicsConfiguration gc = printGraphics.getDeviceConfiguration();
-      final AffineTransform aTrans = printGraphics.getTransform();
-      System.err.println(" scale "+aTrans.getScaleX()+" x "+aTrans.getScaleY());
-      System.err.println(" move "+aTrans.getTranslateX()+" x "+aTrans.getTranslateY());
-      
-      final Rectangle gClipOrig = printGraphics.getClipBounds();
-      final Rectangle gClip = new Rectangle(gClipOrig);
-      if( 0 > gClip.x ) {
-          gClip.width += gClip.x;
-          gClip.x = 0;
-      }
-      if( 0 > gClip.y ) {
-          gClip.height += gClip.y;
-          gClip.y = 0;
-      }
-      printRenderer.setImageSize(gClip.width, gClip.height);      
-      printRenderer.setTileOffset(gClip.x, gClip.y);
-      System.err.println("AWT print.0: "+gClipOrig+" -> "+gClip);
-      System.err.println("AWT print.0: "+printRenderer);
       do {
-          printRenderer.display();
-      } while ( !printRenderer.eot() );
-      System.err.println("AWT print.X: "+printRenderer);
+          tileRenderer.display();
+      } while ( !tileRenderer.eot() );
+      if( DEBUG ) {
+          System.err.println("AWT print.X: "+tileRenderer);
+      }
   }
     
   @Override
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index 84663cb3a..1f9e65a7d 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -49,7 +49,6 @@ import java.awt.GraphicsConfiguration;
 import java.awt.GraphicsEnvironment;
 import java.awt.Rectangle;
 import java.awt.RenderingHints;
-import java.awt.Shape;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Rectangle2D;
 import java.awt.image.BufferedImage;
@@ -90,6 +89,7 @@ import jogamp.opengl.GLContextImpl;
 import jogamp.opengl.GLDrawableFactoryImpl;
 import jogamp.opengl.GLDrawableHelper;
 import jogamp.opengl.GLDrawableImpl;
+import jogamp.opengl.awt.AWTTilePainter;
 import jogamp.opengl.awt.Java2D;
 import jogamp.opengl.util.glsl.GLSLTextureRaster;
 
@@ -100,7 +100,6 @@ import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
 import com.jogamp.opengl.util.GLPixelBuffer.SingletonGLPixelBufferProvider;
 import com.jogamp.opengl.util.GLPixelStorageModes;
 import com.jogamp.opengl.util.TileRenderer;
-import com.jogamp.opengl.util.TileRendererBase;
 import com.jogamp.opengl.util.awt.AWTGLPixelBuffer;
 import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.AWTGLPixelBufferProvider;
 import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.SingleAWTGLPixelBufferProvider;
@@ -502,11 +501,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
   }
 
   private volatile boolean printActive = false;
-  private TileRenderer printRenderer = null;
   private GLAnimatorControl printAnimator = null; 
-  private AWTGLPixelBuffer printBuffer = null;
-  private BufferedImage printVFlipImage = null;
-  private Graphics2D printGraphics = null;
+  private AWTTilePainter printAWTTiles = null;
   
   @Override
   public void setupPrint() {
@@ -535,102 +531,15 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
           printAnimator =  helper.getAnimator();
           if( null != printAnimator ) {
               printAnimator.remove(GLJPanel.this);
-          }
-          final int tileWidth = getWidth();
-          final int tileHeight = getHeight();
-          
-          // FIXME final OffscreenBackend offscrBacken = (OffscreenBackend)backend;
-          final GLCapabilities caps = (GLCapabilities)getChosenGLCapabilities().cloneMutable();
-          caps.setOnscreen(false);
-          printRenderer = new TileRenderer();
-          printRenderer.setRowOrder(TileRenderer.TR_TOP_TO_BOTTOM);
-          printRenderer.setTileSize(tileWidth, tileHeight, 0);
+          }          
+          final int componentCount = isOpaque() ? 3 : 4;
+          final TileRenderer printRenderer = new TileRenderer();
+          printRenderer.setTileSize(getWidth(), getHeight(), 0);
           printRenderer.attachToAutoDrawable(GLJPanel.this);
-
-          final GLEventListener preTileGLEL = new GLEventListener() {
-              @Override
-              public void init(GLAutoDrawable drawable) {
-              }
-              @Override
-              public void dispose(GLAutoDrawable drawable) {}
-              @Override
-              public void display(GLAutoDrawable drawable) {
-                  final GL gl = drawable.getGL();
-                  if( null == printBuffer ) {
-                      final int componentCount = isOpaque() ? 3 : 4;
-                      final AWTGLPixelBufferProvider printBufferProvider = new AWTGLPixelBufferProvider( true /* allowRowStride */ );      
-                      final GLPixelAttributes pixelAttribs = printBufferProvider.getAttributes(gl, componentCount);
-                      printBuffer = printBufferProvider.allocate(gl, pixelAttribs, tileWidth, tileHeight, 1, true, 0);
-                      printRenderer.setTileBuffer(printBuffer);
-                      printVFlipImage = new BufferedImage(printBuffer.width, printBuffer.height, printBuffer.image.getType());
-                  }
-                  System.err.println("XXX tile-pre "+printRenderer); // FIXME
-              }
-              @Override
-              public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {}
-          };
-          final GLEventListener postTileGLEL = new GLEventListener() {
-              int tTopRowHeight = 0;
-              @Override
-              public void init(GLAutoDrawable drawable) {
-                  tTopRowHeight = 0;
-              }
-              @Override
-              public void dispose(GLAutoDrawable drawable) {}
-              @Override
-              public void display(GLAutoDrawable drawable) {              
-                  // Copy temporary data into raster of BufferedImage for faster
-                  // blitting Note that we could avoid this copy in the cases
-                  // where !offscreenDrawable.isGLOriented(),
-                  // but that's the software rendering path which is very slow anyway.
-                  final int tHeight = printRenderer.getParam(TileRendererBase.TR_CURRENT_TILE_HEIGHT);
-                  final int tWidth = printRenderer.getParam(TileRendererBase.TR_CURRENT_TILE_WIDTH);
-                  // final BufferedImage dstImage = printBuffer.image;
-                  final BufferedImage srcImage = printBuffer.image;
-                  final BufferedImage dstImage = printVFlipImage;
-                  final int[] src = ((DataBufferInt) srcImage.getRaster().getDataBuffer()).getData();
-                  final int[] dst = ((DataBufferInt) dstImage.getRaster().getDataBuffer()).getData();
-                  final int incr = printBuffer.width;
-                  int srcPos = 0;
-                  int destPos = (tHeight - 1) * printBuffer.width;
-                  for (; destPos >= 0; srcPos += incr, destPos -= incr) {
-                      System.arraycopy(src, srcPos, dst, destPos, incr);
-                  }
-                  // Draw resulting image in one shot
-                  final int tRows = printRenderer.getParam(TileRenderer.TR_ROWS);
-                  final int tRow = printRenderer.getParam(TileRenderer.TR_CURRENT_ROW);
-                  final int pX = printRenderer.getParam(TileRendererBase.TR_CURRENT_TILE_X_POS); 
-                  final int pYf;
-                  if( tRow == tRows - 1 ) {
-                      tTopRowHeight = tHeight;
-                      pYf = 0;
-                  } else if( tRow == tRows - 2 ){
-                      pYf = tTopRowHeight;
-                  } else {
-                      pYf = ( tRows - 2 - tRow ) * tHeight + tTopRowHeight;
-                  }
-                  final Shape oClip = printGraphics.getClip();
-                  printGraphics.clipRect(pX, pYf, tWidth, tHeight);
-                  final Shape clip = printGraphics.getClip();
-                  printGraphics.drawImage(dstImage, pX, pYf, dstImage.getWidth(), dstImage.getHeight(), null); // Null ImageObserver since image data is ready.
-                  printGraphics.setColor(Color.BLACK);
-                  printGraphics.drawRect(pX, pYf, tWidth, tHeight);
-                  {
-                      final Rectangle r = oClip.getBounds();
-                      printGraphics.setColor(Color.YELLOW);
-                      printGraphics.drawRect(r.x, r.y, r.width, r.height);
-                  }
-                  printGraphics.setClip(oClip);
-                  System.err.println("XXX tile-post.X clip "+oClip+" -> "+clip);
-                  System.err.println("XXX tile-post.X "+printRenderer);
-                  System.err.println("XXX tile-post.X dst-img "+dstImage.getWidth()+"x"+dstImage.getHeight()+" -> "+pX+"/"+pYf); // +", "+dstImage); // FIXME
-              }
-              @Override
-              public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {}
-          };      
-          printRenderer.setGLEventListener(preTileGLEL, postTileGLEL);
-
-          System.err.println("AWT print.setup "+printRenderer); // FIXME
+          printAWTTiles = new AWTTilePainter(printRenderer, componentCount, DEBUG);
+          if( DEBUG ) {
+              System.err.println("AWT print.setup "+printAWTTiles);
+          }
       }
   };
   
@@ -649,22 +558,15 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
   private final Runnable releasePrintOnEDT = new Runnable() {
       @Override
       public void run() {
-          printRenderer.detachFromAutoDrawable(); // tile-renderer -> printGLAD
+          if( DEBUG ) {
+              System.err.println("AWT print.release "+printAWTTiles);
+          }
+          printAWTTiles.dispose();
+          printAWTTiles= null;
           if( null != printAnimator ) {
               printAnimator.add(GLJPanel.this);
+              printAnimator = null;
           }
-          System.err.println("AWT print.release "+printRenderer); // FIXME
-          printRenderer = null;
-          printAnimator = null;
-          if( null != printBuffer ) {
-              printBuffer.dispose();
-              printBuffer = null;
-          }
-          if( null != printVFlipImage ) {
-              printVFlipImage.flush();
-              printVFlipImage = null;
-          }
-          printGraphics = null;
           printActive = false;
       }
   };
@@ -680,45 +582,40 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
       }
       sendReshape = false; // clear reshape flag
       handleReshape = false; // ditto
-      printGraphics = (Graphics2D)graphics;
-      System.err.println("AWT print.0: canvasSize "+getWidth()+"x"+getWidth()+", printAnimator "+printAnimator);
-      {
-          final RenderingHints rHints = printGraphics.getRenderingHints();
-          final Set<Entry<Object, Object>> rEntries = rHints.entrySet();
-          int count = 0;
-          for(Iterator<Entry<Object, Object>> rEntryIter = rEntries.iterator(); rEntryIter.hasNext(); count++) {
-              final Entry<Object, Object> rEntry = rEntryIter.next();
-              System.err.println("Hint["+count+"]: "+rEntry.getKey()+" -> "+rEntry.getValue());
+      final Graphics2D printGraphics = (Graphics2D)graphics;
+      if( DEBUG ) {
+          System.err.println("AWT print.0: canvasSize "+getWidth()+"x"+getWidth()+", printAnimator "+printAnimator);
+          {
+              final RenderingHints rHints = printGraphics.getRenderingHints();
+              final Set<Entry<Object, Object>> rEntries = rHints.entrySet();
+              int count = 0;
+              for(Iterator<Entry<Object, Object>> rEntryIter = rEntries.iterator(); rEntryIter.hasNext(); count++) {
+                  final Entry<Object, Object> rEntry = rEntryIter.next();
+                  System.err.println("Hint["+count+"]: "+rEntry.getKey()+" -> "+rEntry.getValue());
+              }
           }
+          final AffineTransform aTrans = printGraphics.getTransform();
+          System.err.println(" scale "+aTrans.getScaleX()+" x "+aTrans.getScaleY());
+          System.err.println(" move "+aTrans.getTranslateX()+" x "+aTrans.getTranslateY());
+      }      
+      printAWTTiles.updateGraphics2DAndClipBounds(printGraphics);
+      final TileRenderer tileRenderer = printAWTTiles.getTileRenderer(); 
+      if( DEBUG ) {
+          System.err.println("AWT print.0: "+tileRenderer);
       }
-      // final GraphicsConfiguration gc = printGraphics.getDeviceConfiguration();
-      final AffineTransform aTrans = printGraphics.getTransform();
-      System.err.println(" scale "+aTrans.getScaleX()+" x "+aTrans.getScaleY());
-      System.err.println(" move "+aTrans.getTranslateX()+" x "+aTrans.getTranslateY());
-      
-      final Rectangle gClipOrig = printGraphics.getClipBounds();
-      final Rectangle gClip = new Rectangle(gClipOrig);
-      if( 0 > gClip.x ) {
-          gClip.width += gClip.x;
-          gClip.x = 0;
-      }
-      if( 0 > gClip.y ) {
-          gClip.height += gClip.y;
-          gClip.y = 0;
-      }
-      printRenderer.setImageSize(gClip.width, gClip.height);      
-      printRenderer.setTileOffset(gClip.x, gClip.y);
-      System.err.println("AWT print.0: "+gClipOrig+" -> "+gClip);
-      System.err.println("AWT print.0: "+printRenderer);
       do {
           // printRenderer.display();
           backend.doPlainPaint();
-      } while ( !printRenderer.eot() );
-      System.err.println("AWT print.X: "+printRenderer);
+      } while ( !tileRenderer.eot() );
+      if( DEBUG ) {
+          System.err.println("AWT print.X: "+tileRenderer);
+      }
   }
   @Override
   protected void printComponent(Graphics g) {
-      System.err.println("AWT printComponent.X: "+printRenderer);
+      if( DEBUG ) {
+          System.err.println("AWT printComponent.X: "+printAWTTiles);
+      }
       print(g);
   }
       
@@ -1578,17 +1475,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
 
     @Override
     public boolean handleReshape() {
-        /** FIXME: Shall we utilize such resize optimization (snippet kept alive from removed pbuffer backend) ?
-        // Use factor larger than 2 during shrinks for some hysteresis
-        float shrinkFactor = 2.5f;
-        if ( (panelWidth > readBackWidthInPixels)                  || (panelHeight > readBackHeightInPixels) ||
-             (panelWidth < (readBackWidthInPixels / shrinkFactor)) || (panelHeight < (readBackHeightInPixels / shrinkFactor))) {
-            if (DEBUG) {
-                System.err.println(getThreadName()+": Resizing offscreen from (" + readBackWidthInPixels + ", " + readBackHeightInPixels + ") " +
-                        " to fit (" + panelWidth + ", " + panelHeight + ")");
-            }
-        } */
-        
         GLDrawableImpl _drawable = offscreenDrawable;
         {
             final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, offscreenContext, panelWidth, panelHeight);
diff --git a/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java b/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java
new file mode 100644
index 000000000..7493a19c5
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java
@@ -0,0 +1,217 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ * 
+ *    1. Redistributions of source code must retain the above copyright notice, this list of
+ *       conditions and the following disclaimer.
+ * 
+ *    2. Redistributions in binary form must reproduce the above copyright notice, this list
+ *       of conditions and the following disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl.awt;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+
+import com.jogamp.opengl.util.TileRenderer;
+import com.jogamp.opengl.util.TileRendererBase;
+import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
+import com.jogamp.opengl.util.awt.AWTGLPixelBuffer;
+import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.AWTGLPixelBufferProvider;
+
+/**
+ * Implementing AWT {@link Graphics2D} based {@link TileRenderer} <i>painter</i>.
+ * <p>
+ * Maybe utilized for AWT printing.
+ * </p>
+ */
+public class AWTTilePainter {
+    final private TileRenderer renderer;
+    final private int componentCount;
+    final private boolean verbose;
+    
+    private AWTGLPixelBuffer tBuffer = null;
+    private BufferedImage vFlipImage = null;
+    private Graphics2D g2d = null;
+    
+    /** 
+     * Assumes a configured {@link TileRenderer}, i.e.
+     * an {@link TileRenderer#attachToAutoDrawable(GLAutoDrawable) attached}
+     * {@link GLAutoDrawable} with {@link TileRenderer#setTileSize(int, int, int) set tile size}.
+     * <p> 
+     * Sets the renderer to {@link TileRenderer#TR_TOP_TO_BOTTOM} row order.
+     * </p>
+     * <p>
+     * <code>componentCount</code> reflects opaque, i.e. 4 if non opaque.
+     * </p>
+     */
+    public AWTTilePainter(TileRenderer renderer, int componentCount, boolean verbose) {
+        this.renderer = renderer;
+        this.renderer.setGLEventListener(preTileGLEL, postTileGLEL);
+        this.componentCount = componentCount;
+        this.verbose = verbose;
+        this.renderer.setRowOrder(TileRenderer.TR_TOP_TO_BOTTOM);
+    }
+    
+    public String toString() { return renderer.toString(); }
+    
+    public TileRenderer getTileRenderer() { return renderer; }
+    
+    /**
+     * Caches the {@link Graphics2D} instance for rendering.
+     * <p>
+     * Sets the {@link TileRenderer}'s {@link TileRenderer#setImageSize(int, int) image size}
+     * and {@link TileRenderer#setTileOffset(int, int) tile offset} according the
+     * the {@link Graphics2D#getClipBounds() graphics clip bounds}.
+     * </p>
+     * @param g2d
+     */
+    public void updateGraphics2DAndClipBounds(Graphics2D g2d) {
+        this.g2d = g2d;
+        final Rectangle gClipOrig = g2d.getClipBounds();
+        final Rectangle gClip = new Rectangle(gClipOrig);
+        if( 0 > gClip.x ) {
+            gClip.width += gClip.x;
+            gClip.x = 0;
+        }
+        if( 0 > gClip.y ) {
+            gClip.height += gClip.y;
+            gClip.y = 0;
+        }
+        if( verbose ) {
+            System.err.println("AWT print.0: "+gClipOrig+" -> "+gClip);
+        }
+        renderer.setImageSize(gClip.width, gClip.height);      
+        renderer.setTileOffset(gClip.x, gClip.y);
+    }
+    
+    /**
+     * Disposes resources and {@link TileRenderer#detachFromAutoDrawable() detaches}
+     * the {@link TileRenderer}'s {@link GLAutoDrawable}.
+     */
+    public void dispose() {
+        renderer.detachFromAutoDrawable(); // tile-renderer -> printGLAD
+        g2d = null;
+        if( null != tBuffer ) {
+            tBuffer.dispose();
+            tBuffer = null;
+        }
+        if( null != vFlipImage ) {
+            vFlipImage.flush();
+            vFlipImage = null;
+        }
+    }
+    
+    final GLEventListener preTileGLEL = new GLEventListener() {
+        @Override
+        public void init(GLAutoDrawable drawable) {
+        }
+        @Override
+        public void dispose(GLAutoDrawable drawable) {}
+        @Override
+        public void display(GLAutoDrawable drawable) {
+            final GL gl = drawable.getGL();
+            if( null == tBuffer ) {
+                final int tWidth = renderer.getParam(TileRenderer.TR_TILE_WIDTH);
+                final int tHeight = renderer.getParam(TileRenderer.TR_TILE_HEIGHT);
+                final AWTGLPixelBufferProvider printBufferProvider = new AWTGLPixelBufferProvider( true /* allowRowStride */ );      
+                final GLPixelAttributes pixelAttribs = printBufferProvider.getAttributes(gl, componentCount);
+                tBuffer = printBufferProvider.allocate(gl, pixelAttribs, tWidth, tHeight, 1, true, 0);
+                renderer.setTileBuffer(tBuffer);
+                vFlipImage = new BufferedImage(tBuffer.width, tBuffer.height, tBuffer.image.getType());
+            }
+            if( verbose ) {
+                System.err.println("XXX tile-pre "+renderer);
+            }
+        }
+        @Override
+        public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {}
+    };
+    final GLEventListener postTileGLEL = new GLEventListener() {
+        int tTopRowHeight = 0;
+        @Override
+        public void init(GLAutoDrawable drawable) {
+            tTopRowHeight = 0;
+        }
+        @Override
+        public void dispose(GLAutoDrawable drawable) {}
+        @Override
+        public void display(GLAutoDrawable drawable) {              
+            // Copy temporary data into raster of BufferedImage for faster
+            // blitting Note that we could avoid this copy in the cases
+            // where !offscreenDrawable.isGLOriented(),
+            // but that's the software rendering path which is very slow anyway.
+            final int tWidth = renderer.getParam(TileRendererBase.TR_CURRENT_TILE_WIDTH);
+            final int tHeight = renderer.getParam(TileRendererBase.TR_CURRENT_TILE_HEIGHT);
+            // final BufferedImage dstImage = printBuffer.image;
+            final BufferedImage srcImage = tBuffer.image;
+            final BufferedImage dstImage = vFlipImage;
+            final int[] src = ((DataBufferInt) srcImage.getRaster().getDataBuffer()).getData();
+            final int[] dst = ((DataBufferInt) dstImage.getRaster().getDataBuffer()).getData();
+            final int incr = tBuffer.width;
+            int srcPos = 0;
+            int destPos = (tHeight - 1) * tBuffer.width;
+            for (; destPos >= 0; srcPos += incr, destPos -= incr) {
+                System.arraycopy(src, srcPos, dst, destPos, incr);
+            }
+            // Draw resulting image in one shot
+            final int tRows = renderer.getParam(TileRenderer.TR_ROWS);
+            final int tRow = renderer.getParam(TileRenderer.TR_CURRENT_ROW);
+            final int pX = renderer.getParam(TileRendererBase.TR_CURRENT_TILE_X_POS); 
+            final int pYf;
+            if( tRow == tRows - 1 ) {
+                tTopRowHeight = tHeight;
+                pYf = 0;
+            } else if( tRow == tRows - 2 ){
+                pYf = tTopRowHeight;
+            } else {
+                pYf = ( tRows - 2 - tRow ) * tHeight + tTopRowHeight;
+            }
+            final Shape oClip = g2d.getClip();
+            g2d.clipRect(pX, pYf, tWidth, tHeight);
+            final Shape clip = g2d.getClip();
+            g2d.drawImage(dstImage, pX, pYf, dstImage.getWidth(), dstImage.getHeight(), null); // Null ImageObserver since image data is ready.
+            g2d.setColor(Color.BLACK);
+            g2d.drawRect(pX, pYf, tWidth, tHeight);
+            {
+                final Rectangle r = oClip.getBounds();
+                g2d.setColor(Color.YELLOW);
+                g2d.drawRect(r.x, r.y, r.width, r.height);
+            }
+            g2d.setClip(oClip);
+            if( verbose ) {
+                System.err.println("XXX tile-post.X clip "+oClip+" -> "+clip);
+                System.err.println("XXX tile-post.X "+renderer);
+                System.err.println("XXX tile-post.X dst-img "+dstImage.getWidth()+"x"+dstImage.getHeight()+" -> "+pX+"/"+pYf);
+            }
+        }
+        @Override
+        public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {}
+    };      
+
+}
-- 
cgit v1.2.3