Revision: 4037
          http://vexi.svn.sourceforge.net/vexi/?rev=4037&view=rev
Author:   clrg
Date:     2011-02-22 00:41:16 +0000 (Tue, 22 Feb 2011)

Log Message:
-----------
Refactor of Surface and AWT prior to Swing-enabled implementation
- split blit implementation from DoubleBufferedSurface
- do not store permanent graphics object for image
- do not dirty from platform implementation

Modified Paths:
--------------
    trunk/org.vexi-core.main/src/main/java/org/vexi/core/Surface.java
    trunk/org.vexi-core.main/src/main/java/org/vexi/plat/AWT.java

Modified: trunk/org.vexi-core.main/src/main/java/org/vexi/core/Surface.java
===================================================================
--- trunk/org.vexi-core.main/src/main/java/org/vexi/core/Surface.java   
2011-02-17 01:34:52 UTC (rev 4036)
+++ trunk/org.vexi-core.main/src/main/java/org/vexi/core/Surface.java   
2011-02-22 00:41:16 UTC (rev 4037)
@@ -400,7 +400,7 @@
     // Frame Management ///////////////////////////////////////////////
     
     // FIXME: handle exceptions etc - better checking of types?
-    /** prepare an image for setting it as the icon of this surface */
+    /** Prepare an image for setting it as the icon of this surface */
     public final void setIcon(JS newicon) throws JSExn {
         icon = newicon == null ? null : Picture.load(newicon, seticon);
         if (icon==null) {
@@ -423,7 +423,7 @@
     public final void setMinimumSize(int minx, int miny) { 
_setMinimumSize(minx, miny); }
     protected void setResizable(boolean resizable) { _setResizable(resizable); 
}
 
-    /** subclasses should invoke this method when the user resizes the window 
*/
+    /** Subclasses should invoke this method when the user resizes the window 
*/
     protected final void SizeChange(int width, int height) {
         if (pendingWidth == width && pendingHeight == height) {
             return;
@@ -435,7 +435,7 @@
         // FEATURE: notify root box of x/y change if align is not topleft 
     }
 
-    /** we enqueue ourselves in the Platform.Scheduler when we have a 
PosChange message to deal with */
+    /** We enqueue ourselves in the Platform.Scheduler when we have a 
PosChange message to deal with */
     private boolean poschangeScheduled = false;
     private final Callable poschanger = new Callable() {
         public Object run(Object o) throws JSExn {
@@ -468,7 +468,7 @@
         }
     };
 
-    /** notify Vexi that the surface (ie frame or window) has moved */
+    /** Notify Vexi that the surface (ie frame or window) has moved */
     protected final void PosChange(int x, int y) {
         if (this.x == x && this.y == y) {
             return;
@@ -551,7 +551,7 @@
         }
     }
 
-    /** only run if scheduled */
+    /** Only run if scheduled */
     public Object run(Object o) {
         if (resizable == Box.testShrink(root)) {
             resizable = !Box.testShrink(root); 
@@ -580,7 +580,7 @@
         return null;
     }
 
-    /** Indicates that the Surface is no longer needed */
+    /** Indicates that the surface is no longer needed */
     public final void dispose(boolean quitIfAllSurfacesGone) {
         //Log.info(this, "disposing " + this);
         allSurfaces.removeElement(this);
@@ -598,16 +598,25 @@
         _dispose();
     }
     
+    /** Calls dirty(0, 0, w, h) where 'w' and 'h' are the dimensions of
+     *  the root box of the surface
+     */
     public void dirty() {
         dirty(0, 0, root.width, root.height);
     }
 
-    public void dirty(int x, int y, int w, int h) {
+    /** Signals that a rendered area is no longer valid.  It is intended
+     *  for use during reflow, identifying which areas on screen need to
+     *  be reconstructed after changes to the underlying model.  Platform
+     *  implementations of Surface should never call dirty outside of
+     *  render() as it is not thread safe.
+     */
+    protected void dirty(int x, int y, int w, int h) {
         dirtyRegions.dirty(x, y, w, h);
         Refresh();
     }
 
-    /** find Surface whose root is Box b */ 
+    /** Find surface whose root is Box b */ 
     public static Surface fromBox(Box b) {
         int numSurfaces = allSurfaces.size();
         for (int i=0; i<numSurfaces; i++) {
@@ -683,7 +692,7 @@
     // unused - private static Affine identity = Affine.identity();
 
     
-    /** when set to true, render() should abort as soon as possible and 
restart the rendering process */
+    /** When set to true, render() should abort as soon as possible and 
restart the rendering process */
     private volatile boolean abort = false;
     private int abortcount;
     public boolean renderAborted() { return abort; }
@@ -694,11 +703,11 @@
         abort = true;
     }
 
-    /** runs the pre-render() and render() pipelines in the root Box to 
regenerate the backbuffer, then blits it to the screen */
-    public synchronized RenderedRegions render() {
+    /** Runs the pre-render() and render() pipelines in the root Box to 
regenerate the backbuffer */
+    public RenderedRegions render() {
         scheduled = false;
-        if (minimized) {
-            abort = false;
+        if (minimized) {
+            abort = false;
             return null;
         }
         // make sure the root is properly sized
@@ -751,7 +760,7 @@
                 continue;
             }
 
-//            System.out.println("render: "+x+","+y+" -> "+w+","+h);
+            //System.out.println("render: "+x+","+y+" -> "+w+","+h);
             root.render(0, 0, x, y, w, h, buf);
             if (scarImage != null) {
                 if (scarImage.width > x && scar_y < h) {
@@ -777,8 +786,8 @@
     }
     
     public static class RenderedRegions {
-        int[] regions;
-        int numregions;
+        public int[] regions;
+        public int numregions;
         RenderedRegions(int[] regions, int numregions) {
             this.regions = regions;
             this.numregions = numregions;
@@ -786,16 +795,18 @@
     }
 
 
-    // Default PixelBuffer implementation 
/////////////////////////////////////////////////////////
+    // Double Buffered PixelBuffer superclass 
/////////////////////////////////////////////////////////
 
-    public static abstract class DoubleBufferedSurface extends Surface 
implements PixelBuffer {
+    /** Basic double buffered surface implementation with no blitting
+     *  i.e. implementations must handle blitting themselves
+     */
+    public static abstract class DoubleBufferedSurfaceNoBlit extends Surface 
implements PixelBuffer {
 
-        public DoubleBufferedSurface(Box root) { super(root); }
+        public DoubleBufferedSurfaceNoBlit(Box root) { super(root); }
         public PixelBuffer getPixelBuffer() { return this; }
         protected PixelBuffer backbuffer = 
Platform.createPixelBuffer(Platform.getScreenBounds().width, 
Platform.getScreenBounds().height, this);
-//        final private DirtyList screenDirtyRegions = new DirtyList();
 
-        /** draw an unscaled image onto the backbuffer where:
+        /** Draw an unscaled image onto the backbuffer where:
          *  (dx,dy) is the offset within the picture from where to start 
sampling
          *  (cx1,cy1) to (cx2,cy2) describe the clipping box on the backbuffer 
which to draw
          */
@@ -803,7 +814,7 @@
             backbuffer.drawPicture(source, dx, dy, cx1, cy1, cx2, cy2);
         }
 
-        /** draw a scaled image onto the backbuffer where:
+        /** Draw a scaled image onto the backbuffer where:
          *  (dx1,dy1) to (dx2,dy2) describe the destination area on the 
backbuffer in which to draw
          *  (sx1,sy1) to (sx2,sy2) describe the source area from which to 
sample from the image
          */
@@ -811,7 +822,7 @@
             backbuffer.drawPicture(source, dx1, dy1, dx2, dy2, sx1, sy1, sx2, 
sy2);
         }
 
-        /** draw an unscaled glyph onto the backbuffer where:
+        /** Draw an unscaled glyph onto the backbuffer where:
          *  (dx1,dy1) is the top-left point of the glyph when placed on the 
backbuffer
          *  (cx1,cy1) to (cx2,cy2) describe the clipping area on the backbuffer
          */
@@ -820,33 +831,36 @@
         }
 
         public void fillTrapezoid(int x1, int x2, int y1, int x3, int x4, int 
y2, int color) {
-//            System.out.println("fillTrapezoid: "+x1+"|"+x2+","+y1+" -> 
"+x3+"|"+x4+","+y2+" - "+Color.colorToString(color));
             backbuffer.fillTrapezoid(x1, x2, y1, x3, x4, y2, color);
         }
 
-        // FIXME: this hack is to cover up a race condition whereby the 
backbuffer
-        // and the window image get somehow out of sync under 
tough-to-reproduce
-        // circumstances i.e. fairly complex applications.  The backbuffer is 
valid,
-        // it is actually correctly (briefly) painted to the window before the
-        // _previous_ state of the backbuffer is then painted back over it (!!)
-        // because asynchronize blits seem to occur first-in last-out - that 
is,
-        // blit from render is called after a refresh, but refresh happens 
last.
-        // To test without the blithack, set disable_blithack to true; it also
-        // adds a 1/4s pause before blitting so you can see the blit 
progression.
-        private boolean blithack = true;
-        private boolean disable_blithack = false;
+        /** This is how subclasses signal a 'shallow dirty', indicating that 
although the backbuffer is valid, the screen is not */
+        public final void refreshFromBackbuffer(int x, int y, int w, int h) {
+            blit(x, y, w, h);
+        }
+
+        // copies a region from the doublebuffer to this surface
+        public abstract void blit(PixelBuffer source, int sx, int sy, int dx, 
int dy, int dx2, int dy2);
+        protected void blit(int x, int y, int w, int h) {
+            blit(backbuffer, x, y, x, y, w + x, h + y);
+        }
+
+    }
+
+
+    // Default PixelBuffer implementation 
/////////////////////////////////////////////////////////
+
+    /** A double buffered surface which blits as part of the render cycle */
+    public static abstract class DoubleBufferedSurface extends 
DoubleBufferedSurfaceNoBlit {
+
+        public DoubleBufferedSurface(Box root) { super(root); }
         
-        /** renders the surface display with changes made to the backbuffer */
-        public synchronized RenderedRegions render() {
+        /** Renders the display with changes made to the backbuffer of the 
surface */
+        public RenderedRegions render() {
             RenderedRegions r = super.render();
             if (r==null) {
-                if (blithack && !disable_blithack) {
-                    blithack = false;
-                    blit(backbuffer, 0, 0, 0, 0, root.width, root.height);
-                }
-                return null;
+                return r;
             }
-            blithack = true;
             
             int numregions = r.numregions;
             int[] regions = r.regions;
@@ -878,37 +892,10 @@
             if (w > rwidth) w = rwidth;
             if (h > rheight) h = rheight;
             if (w > x && h > y) {
-                if (disable_blithack) {
-                    System.out.println("render blit: "+x+","+y+" -> 
"+w+","+h+")");
-                    try {
-                        Thread.sleep(250);
-                    } catch(InterruptedException e) { }
-                }
                 blit(backbuffer, x, y, x, y, w, h);
-//                refreshFromBackbuffer(x, y, w-x, h-y);
             }
             return r;
         }
-
-        /** This is how subclasses signal a 'shallow dirty', indicating that 
although the backbuffer is valid, the screen is not */
-        public final void refreshFromBackbuffer(int x, int y, int w, int h) {
-            blit(backbuffer, x, y, x, y, x + w, y + h);
-        }
-//        public final synchronized void refreshFromBackbuffer(int x, int y, 
int w, int h) {
-//            blit(x, y, w, h);
-//        }
-
-//        public void dirty(int x, int y, int w, int h) {
-//            screenDirtyRegions.dirty(x, y, w, h);
-//            super.dirty(x, y, w, h);
-//        }
-
-        // copies a region from the doublebuffer to this surface
-        public abstract void blit(PixelBuffer source, int sx, int sy, int dx, 
int dy, int dx2, int dy2);
-        protected void blit(int x, int y, int w, int h) {
-            blit(backbuffer, x, y, x, y, w + x, h + y);
-        }
-
     }
     
     static int counter=0;

Modified: trunk/org.vexi-core.main/src/main/java/org/vexi/plat/AWT.java
===================================================================
--- trunk/org.vexi-core.main/src/main/java/org/vexi/plat/AWT.java       
2011-02-17 01:34:52 UTC (rev 4036)
+++ trunk/org.vexi-core.main/src/main/java/org/vexi/plat/AWT.java       
2011-02-22 00:41:16 UTC (rev 4037)
@@ -575,6 +575,15 @@
                 new Color((rootfill >> 16) & 0xff, (rootfill >> 8) & 0xff, 
(rootfill) & 0xff);
             window.setBackground(rootcolor);
         }
+
+        // FIXME: this hack is to cover up a race condition whereby the 
backbuffer
+        // and the window image get somehow out of sync under 
tough-to-reproduce
+        // circumstances i.e. fairly complex applications.  The backbuffer is 
valid,
+        // it is actually correctly (briefly) painted to the window before the
+        // _previous_ state of the backbuffer is then painted back over it (!!)
+        // because asynchronize blits seem to occur first-in last-out - that 
is,
+        // blit from render is called after a refresh, but refresh happens 
last.
+        private boolean blithack = true;
         
         public RenderedRegions render() {
             // useful optimisation;
@@ -592,9 +601,22 @@
                AWTPixelBuffer new_backbuffer = 
(AWTPixelBuffer)Platform.createPixelBuffer(w, h, this);
                new_backbuffer.i.getGraphics().drawImage(buf.i, 0, 0, null);
                backbuffer = new_backbuffer;
-               dirty();
+               // dirty() is implicit due to SizeChange
+               //dirty();
             }
-            return super.render();
+            buf.g = buf.i.getGraphics();
+            RenderedRegions r = super.render();
+            buf.g.dispose();
+            buf.g = null;
+            if (r==null) {
+                if (blithack) {
+                    blithack = false;
+                    blit(backbuffer, 0, 0, 0, 0, root.width, root.height);
+                }
+                return null;
+            }
+            blithack = true;
+            return r;
         }
 
         AWTSurface(Box root, boolean framed) {
@@ -626,8 +648,10 @@
             // REMARK - this is for nicer initial rendering
             setBackgroundColor();
             AWTPixelBuffer buf = (AWTPixelBuffer)backbuffer;
-            buf.g.setColor(rootcolor);
-            buf.g.fillRect(0, 0, pendingWidth, pendingHeight);
+            Graphics g = buf.i.getGraphics();
+            g.setColor(rootcolor);
+            g.fillRect(0, 0, pendingWidth, pendingHeight);
+            g.dispose();
 
             window.addMouseListener(this);
             window.addKeyListener(this);
@@ -689,7 +713,7 @@
         public void windowClosed(WindowEvent e) { }
         public void windowClosing(WindowEvent e) { Close(); }
         public void windowIconified(WindowEvent e) { Minimized(true); }
-        public void windowDeiconified(WindowEvent e) { dirty(0, 0, root.width, 
root.height); Minimized(false); }
+        public void windowDeiconified(WindowEvent e) { window.repaint(0, 0, 
root.width, root.height); Minimized(false); }
         public void windowActivated(WindowEvent e) { Focused(true); }
         public void windowDeactivated(WindowEvent e) { Focused(false); }
         public void componentMoved(ComponentEvent e) { 
PosChange(window.getLocation().x, window.getLocation().y); }
@@ -714,7 +738,8 @@
                 discoverInsets();
                 AWTPixelBuffer buf = (AWTPixelBuffer)backbuffer;
                 //int rootfill = root.getIntFillcolor();
-                buf.g.setColor(new java.awt.Color((rootfill >> 16) & 0xff,
+                Graphics g = buf.i.getGraphics();
+                g.setColor(new java.awt.Color((rootfill >> 16) & 0xff,
                         (rootfill >> 8) & 0xff,
                         (rootfill) & 0xff));
                 if (pendingWidth < newwidth) {
@@ -722,17 +747,16 @@
                     // |    | |
                     // |    | |
                     // '----'-'
-                    buf.g.fillRect(pendingWidth, 0, newwidth, newheight);
-                    dirty(pendingWidth, 0, newwidth, newheight);
+                    g.fillRect(pendingWidth, 0, newwidth, newheight);
                 }
                 if (pendingHeight < newheight) {
                     //  ______
                     // |      |
                     // |______|
                     // '------'
-                    buf.g.fillRect(0, pendingHeight, newwidth, newheight);
-                    dirty(0, pendingHeight, newwidth, newheight);
+                    g.fillRect(0, pendingHeight, newwidth, newheight);
                 }
+                g.dispose();
                 SizeChange(newwidth, newheight);
             }
         }


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
Index, Search & Analyze Logs and other IT data in Real-Time with Splunk 
Collect, index and harness all the fast moving IT data generated by your 
applications, servers and devices whether physical, virtual or in the cloud.
Deliver compliance at lower cost and gain new business insights. 
Free Software Download: http://p.sf.net/sfu/splunk-dev2dev
_______________________________________________
Vexi-svn mailing list
Vexi-svn@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/vexi-svn

Reply via email to