You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-users@xmlgraphics.apache.org by Michael Jurke <ju...@zedat.fu-berlin.de> on 2010/04/27 12:27:11 UTC

resizing SWT embedded JSVGCanvas

Hi,

still pending is the problem of resizing a JSVGCanvas. I attached the 
code for a very simple whiteboard to draw lines.
After resizing, batik rendering get's strange behavior. Sometimes, on 
smaller window, parts get rendered doubled on the downside or cheesy 
background stays somehow. Sometimes rendering stucks completely although 
the UpdateManager works. Making the window big again, somehow magically 
repairs the rendering.
Please, help me! I tried thousends of ugly workarrounds, some do work 
like changing and resetting the SVGDocument but lead to bad performance 
and flickering.

System.setProperty("sun.awt.noerasebackground", "true"), 
SWT.NO_REDRAW_RESIZE, SWT.NO_BACKGROUND are not connected to the problem.

Regards
Michael

Here see the attached code:

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Point;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;

import org.apache.batik.dom.svg.SVGDOMImplementation;
import org.apache.batik.svggen.SVGGraphics2D;
import org.apache.batik.swing.JSVGCanvas;
import org.apache.batik.swing.svg.AbstractJSVGComponent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.svg.SVGDocument;

public class SimpleWhiteboard extends Composite {

     static {
         System.setProperty("sun.awt.noerasebackground", "true");
     }

     public SimpleWhiteboard(Composite parent, int mode) {
         super(parent, mode);

         this.setLayout(new FillLayout());
         new SimpleSVGSurface(this);

     }

     public static void main(String[] args) {
         Display display = new Display();
         Shell shell = new Shell(display);
         shell.setText("Whiteboard");
         shell.setLayout(new FillLayout());
         SimpleWhiteboard instance = new SimpleWhiteboard(shell,
             SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND);
         shell.open();
         while (!shell.isDisposed()) {
             if (!display.readAndDispatch())
                 display.sleep();
         }
         instance.dispose();
     }

     public static class SimpleSVGSurface extends Composite {

         private JSVGCanvas svgCanvas = null;
         private Frame frame = null;

         private Document svgDocument = null;

         public SimpleSVGSurface(Composite parent) {
             this(parent, SWT.NONE);
         }

         public SimpleSVGSurface(Composite parent, int mode) {
             super(parent, mode | SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE
                 | SWT.EMBEDDED);

             init();
             initXMLGraphics();
             initListeners();

         }

         protected void init() {

             svgCanvas = new JSVGCanvas();

             
svgCanvas.setDocumentState(AbstractJSVGComponent.ALWAYS_DYNAMIC);
             svgCanvas.setLayout(new BorderLayout());
             svgCanvas.setDoubleBuffered(true);
             svgCanvas.setDoubleBufferedRendering(true);

             frame = SWT_AWT.new_Frame(this);
             frame.setLayout(new BorderLayout());
             frame.add(BorderLayout.CENTER, svgCanvas);
             frame.setEnabled(true);

             frame.pack();
             frame.setVisible(true);
         }

         protected void initXMLGraphics() {
             DOMImplementation impl = SVGDOMImplementation
                 .getDOMImplementation();
             String svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI;

             svgDocument = impl.createDocument(svgNS, "svg", null);

             SVGGraphics2D svgGraphics = new SVGGraphics2D(svgDocument);
             // fill the SVG Document with the Defaults
             Element root = svgGraphics
                 .getRoot(svgDocument.getDocumentElement());

             root.setAttributeNS(null, "overflow", "visible");

             svgCanvas.setDocument(svgDocument);
         }

         private static Point lastPoint = null;

         protected void initListeners() {
             svgCanvas.addMouseListener(new java.awt.event.MouseListener() {

                 public void mouseClicked(java.awt.event.MouseEvent e) {
                     //
                 }

                 public void mouseEntered(java.awt.event.MouseEvent e) {
                     // TODO Auto-generated method stub

                 }

                 public void mouseExited(java.awt.event.MouseEvent e) {
                     //

                 }

                 public void mousePressed(java.awt.event.MouseEvent e) {
                     System.out.print("MouseDown ");
                     if (lastPoint == null)
                         lastPoint = e.getPoint();

                     appendLine(lastPoint, e.getPoint());
                     lastPoint = e.getPoint();
                 }

                 public void mouseReleased(java.awt.event.MouseEvent e) {
                     //
                 }

             });

             svgCanvas
                 .addMouseMotionListener(new 
java.awt.event.MouseMotionListener() {

                     public void mouseDragged(java.awt.event.MouseEvent e) {
                         System.out.print("MouseDragged ");

                         appendLine(lastPoint, e.getPoint());
                         lastPoint = e.getPoint();

                     }

                     public void mouseMoved(java.awt.event.MouseEvent e) {
                         // System.out.println("MouseMoved");

                     }

                 });

             initDebugListener();
         }

         private void appendLine(final Point start, final Point end) {

             
svgCanvas.getUpdateManager().getUpdateRunnableQueue().invokeLater(
                 new Runnable() {

                     public void run() {
                         System.out.println("WM works");

                         SVGDocument doc = svgCanvas.getSVGDocument();
                         String SVGNS = 
SVGDOMImplementation.SVG_NAMESPACE_URI;

                         Element g = doc.createElementNS(SVGNS, "g");

                         Element e = doc.createElementNS(SVGNS, "line");

                         e.setAttributeNS(null, "fill", "none");
                         e.setAttributeNS(null, "x1", String.valueOf(start
                             .getX()));
                         e.setAttributeNS(null, "y1", String.valueOf(start
                             .getY()));
                         e
                             .setAttributeNS(null, "x2", String.valueOf(end
                                 .getX()));
                         e
                             .setAttributeNS(null, "y2", String.valueOf(end
                                 .getY()));

                         g.appendChild(e);

                         doc.getRootElement().appendChild(g);
                     }
                 });
         }

         @Override
         public void dispose() {
             // should be disposed by the AWT thread to avoid deadlocks
             EventQueue.invokeLater(new Runnable() {
                 public void run() {
                     svgCanvas.dispose();
                     frame.dispose();
                 }
             });
             super.dispose();
         }

         private void initDebugListener() {
             svgCanvas.addComponentListener(new ComponentListener() {

                 public void componentHidden(ComponentEvent arg0) {
                     // TODO Auto-generated method stub

                 }

                 public void componentMoved(ComponentEvent arg0) {
                     // TODO Auto-generated method stub

                 }

                 public void componentResized(ComponentEvent arg0) {

                     System.out.println("Resize: " + svgCanvas.getSize());

                 }

                 public void componentShown(ComponentEvent arg0) {
                     // TODO Auto-generated method stub

                 }

             });

         }
     }

}

---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: batik-users-help@xmlgraphics.apache.org


Re: resizing SWT embedded JSVGCanvas

Posted by dao <da...@gmail.com>.
hello,

I have embeded a svg canvas into a composite using SWT_AWT too.

It works fine for me except for the keyboard interactors (ctrl+T and zoom in
and out does not work properly, I don't know why)

here is the code (if you have the solution for the keyboard interactors, by
the way). Note the super(parent, SWT.EMBEDDED); the MaskedSvgCanvas is just
a canvas with additional layers for selection/edition (the canvas is
ALWAYS_DYNAMIC)


/*
 * Created on 09.03.2005
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package com.moow.svg.editor;

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Panel;

import javax.swing.JRootPane;
import javax.swing.JScrollPane;

import org.eclipse.jface.util.LocalSelectionTransfer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.w3c.dom.svg.SVGDocument;

import com.moow.svg.domain.symbol.GraphicalComponentBean;
import com.moow.svg.toolkit.ui.MaskedSvgCanvas;
import com.moow.svg.toolkit.ui.SvgComponent;


public class SVGComposite extends Composite  {

private final MaskedSvgCanvas svgCanvas;

private Frame frame;

private DropTarget dropTarget;




public SVGComposite(Composite parent, int style, boolean showScrollbars,
MaskedSvgCanvas canvas) {
super(parent, SWT.EMBEDDED);
this.svgCanvas = canvas;
parent.setLayout(new FillLayout());

/*
 * Set a Windows specific AWT property that prevents heavyweight
 * components from erasing their background. Note that this is a global
 * property and cannot be scoped. It might not be suitable for your
 * application.
 */
try {
System.setProperty("sun.awt.noerasebackground", "true");
} catch (NoSuchMethodError error) {
error.printStackTrace();
}

try {
svgCanvas.setLayout(new BorderLayout());
 frame = SWT_AWT.new_Frame(this);

Panel panel = new Panel(new BorderLayout())
{
public void update(java.awt.Graphics g) {
super.update(g);
/* Do not erase the background */
paint(g);
}
};

JRootPane root = new JRootPane();
panel.add(root);
java.awt.Container contentPane = root.getContentPane();
contentPane.setLayout(new BorderLayout());

if (showScrollbars) {
contentPane
.add(BorderLayout.CENTER, new JScrollPane(svgCanvas));
} else {
contentPane.add(BorderLayout.CENTER, svgCanvas);
}
frame.setLayout(new BorderLayout());
frame.add(BorderLayout.CENTER, panel);
frame.setEnabled(true);

 } catch (Throwable t) {
t.printStackTrace();
}
}


public void dispose() {

EventQueue.invokeLater(new Runnable() {

public void run() {
try {
frame.dispose();
svgCanvas.dispose();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
super.dispose();
}


public SVGDocument getSVGDocument() {
SVGDocument svgDocument = svgCanvas.getSVGDocument();
if (svgDocument==null)
System.err.println("attention, on a enlevé le svgCanvas.waitIsUsable() et ca
fout la merde!!!");
return svgDocument;
}




public MaskedSvgCanvas getSvgCanvas() {
return svgCanvas;
}


public SvgComponent insertSvgComponent(int x, int y,
GraphicalComponentBean graphicalComponentBean) {
// TODO Auto-generated method stub
return null;
}


public void removeGraphicalComponent(String id) {
// TODO Auto-generated method stub
 }


public void makeRegistrations(final SVGCompositeDropListener dropListener) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
if (dropTarget!=null)
dropTarget.dispose();
int operations = DND.DROP_COPY| DND.DROP_MOVE;
dropTarget = new DropTarget(SVGComposite.this, operations);
dropTarget.setTransfer(new Transfer[]
{LocalSelectionTransfer.getTransfer()});
dropTarget.addDropListener(dropListener);
}
});
}


public void unmakeRegistrations() {
if (dropTarget!=null) {
Display.getDefault().asyncExec(new Runnable() {

@Override
public void run() {
dropTarget.dispose();
dropTarget=null;
}
});
}
}



}


On Thu, Apr 29, 2010 at 12:10 PM, <th...@kodak.com> wrote:

> Hi Michael,
>
> Michael Jurke <ju...@zedat.fu-berlin.de> wrote on 04/27/2010 11:04:34 AM:
>
>
> > I found out there are different problems when using Direct3D or openGL
> > (vm argument -Dsun.java2d.opengl=true) for rendering. Doubled rendering
> > of parts of the image appears with D3D only, with openGL I get some
> > vertical shaking when resizing (not horizontal, strange). Furthermore,
> > moving the shell doesn't update the openGL image - on move yes, but
> > after drawing a line again the image is still where it used to be before
> > the shell's position got changed (can be fixed by an extra listener).
> > It's okay for me to use openGL only, maybe anyone has an idea how to
> > correct the shaking or there might be a better solution when moving the
> > shell?
>
>
>     What is "the shell"?
>
> > Finally, still the batik rendering get's stucked, so hopefully
> > anybody has an idea how can I revive it without having to use strange
> > workarounds?
>
>    In the updateCompleted method it calls invokeAndWait to update the
> canvas.  This is the sort of thing that given potential differences
> between Swing and SWT could lead to a dead lock.
>
>
> > About the code, going throw line by line in different threads, first I
> > found a reason for flickering:
> > AbstractJGVTComponent.paintComponent() calls g2d.fillRect with the
> > background color before painting the image. Why? Wouldn't it be much
> > better to paint on the image first - isn't this meant by double
> > buffering? It seems to be an error.
>
>    The Image we draw is often mostly transparent.  So we need to draw
> the background color so it can show through the transparent parts of
> the SVG image.
>
>    And in any case if this causes flickering then the binding between
> swing and SWT is really badly broken.  You shouldn't be able to see
> the 'intermediate' drawing results, I would think you should only see
> the drawing when it's done with the paint method.
>
> > With D3D getRenderRect() sometimes seems to return some wrong values,
> > also the image is not updated properly (results in painting the same
> > image on different locations on small windows). However, as openGL is
> > preferable for us anyway I now have to search the reason for shaking
> > vertically.
>
>     I don't see these sorts of problem using just swing so the problem
> must be somewhere in the swing<->SWT translator.
>
> > On 27.04.2010 12:46, thomas.deweese@kodak.com wrote:
> > > Hi Michael,
> > >
> > > Michael Jurke<ju...@zedat.fu-berlin.de>  wrote on 04/27/2010 06:27:11
> AM:
> > >
> > >
> > >> After resizing, batik rendering get's strange behavior. Sometimes, on
> > >> smaller window, parts get rendered doubled on the downside or cheesy
> > >> background stays somehow. Sometimes rendering stucks completely
> although
> > >>
> > >
> > >> the UpdateManager works. Making the window big again, somehow
> magically
> > >> repairs the rendering.
> > >>
> > >     If I had to guess something goes bad in the SWT<->Swing connection
> > > on resize.  My best guess would be the problem is related to our update
> > > handling.  In particular you might look at JSVGComponent in particular
> > > the 'updateCompleted' method (~line 1971).  I could imagine that the
> > > 'repaint' and/or paintImmediately could have problems, especially given
> > > the use of invokeAndWait.
> > >
> > >     You might see if doing a simple repaint of everything avoids the
> > > issues (this would be less efficient but much more efficient than
> > > setting the whole document).
> > >
> > >
> > >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: batik-users-unsubscribe@xmlgraphics.apache.org
> > For additional commands, e-mail: batik-users-help@xmlgraphics.apache.org
> >
>
>


-- 
Dao Hodac

Re: resizing SWT embedded JSVGCanvas

Posted by th...@kodak.com.
Hi Michael,

Michael Jurke <ju...@zedat.fu-berlin.de> wrote on 04/27/2010 11:04:34 AM:

> I found out there are different problems when using Direct3D or openGL 
> (vm argument -Dsun.java2d.opengl=true) for rendering. Doubled rendering 
> of parts of the image appears with D3D only, with openGL I get some 
> vertical shaking when resizing (not horizontal, strange). Furthermore, 
> moving the shell doesn't update the openGL image - on move yes, but 
> after drawing a line again the image is still where it used to be before 

> the shell's position got changed (can be fixed by an extra listener).
> It's okay for me to use openGL only, maybe anyone has an idea how to 
> correct the shaking or there might be a better solution when moving the 
> shell?

    What is "the shell"?

> Finally, still the batik rendering get's stucked, so hopefully 
> anybody has an idea how can I revive it without having to use strange 
> workarounds?

   In the updateCompleted method it calls invokeAndWait to update the
canvas.  This is the sort of thing that given potential differences 
between Swing and SWT could lead to a dead lock.


> About the code, going throw line by line in different threads, first I 
> found a reason for flickering:
> AbstractJGVTComponent.paintComponent() calls g2d.fillRect with the 
> background color before painting the image. Why? Wouldn't it be much 
> better to paint on the image first - isn't this meant by double 
> buffering? It seems to be an error.

   The Image we draw is often mostly transparent.  So we need to draw
the background color so it can show through the transparent parts of
the SVG image.

   And in any case if this causes flickering then the binding between
swing and SWT is really badly broken.  You shouldn't be able to see
the 'intermediate' drawing results, I would think you should only see 
the drawing when it's done with the paint method.

> With D3D getRenderRect() sometimes seems to return some wrong values, 
> also the image is not updated properly (results in painting the same 
> image on different locations on small windows). However, as openGL is 
> preferable for us anyway I now have to search the reason for shaking 
> vertically.

    I don't see these sorts of problem using just swing so the problem
must be somewhere in the swing<->SWT translator.

> On 27.04.2010 12:46, thomas.deweese@kodak.com wrote:
> > Hi Michael,
> >
> > Michael Jurke<ju...@zedat.fu-berlin.de>  wrote on 04/27/2010 06:27:11 
AM:
> >
> > 
> >> After resizing, batik rendering get's strange behavior. Sometimes, on
> >> smaller window, parts get rendered doubled on the downside or cheesy
> >> background stays somehow. Sometimes rendering stucks completely 
although
> >> 
> > 
> >> the UpdateManager works. Making the window big again, somehow 
magically
> >> repairs the rendering.
> >> 
> >     If I had to guess something goes bad in the SWT<->Swing connection
> > on resize.  My best guess would be the problem is related to our 
update
> > handling.  In particular you might look at JSVGComponent in particular
> > the 'updateCompleted' method (~line 1971).  I could imagine that the
> > 'repaint' and/or paintImmediately could have problems, especially 
given
> > the use of invokeAndWait.
> >
> >     You might see if doing a simple repaint of everything avoids the
> > issues (this would be less efficient but much more efficient than
> > setting the whole document).
> >
> >
> > 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: batik-users-unsubscribe@xmlgraphics.apache.org
> For additional commands, e-mail: batik-users-help@xmlgraphics.apache.org
> 


Re: resizing SWT embedded JSVGCanvas

Posted by Michael Jurke <ju...@zedat.fu-berlin.de>.
Hi again,

I found out there are different problems when using Direct3D or openGL 
(vm argument -Dsun.java2d.opengl=true) for rendering. Doubled rendering 
of parts of the image appears with D3D only, with openGL I get some 
vertical shaking when resizing (not horizontal, strange). Furthermore, 
moving the shell doesn't update the openGL image - on move yes, but 
after drawing a line again the image is still where it used to be before 
the shell's position got changed (can be fixed by an extra listener).
It's okay for me to use openGL only, maybe anyone has an idea how to 
correct the shaking or there might be a better solution when moving the 
shell? Finally, still the batik rendering get's stucked, so hopefully 
anybody has an idea how can I revive it without having to use strange 
workarounds?
Or already a solution for me - if anybody has an idea - where how to 
know whether rendering got stucked, it would be very, very great!!! So I 
could check and call setDocument only when there is a problem.

About the code, going throw line by line in different threads, first I 
found a reason for flickering:
AbstractJGVTComponent.paintComponent() calls g2d.fillRect with the 
background color before painting the image. Why? Wouldn't it be much 
better to paint on the image first - isn't this meant by double 
buffering? It seems to be an error.

With D3D getRenderRect() sometimes seems to return some wrong values, 
also the image is not updated properly (results in painting the same 
image on different locations on small windows). However, as openGL is 
preferable for us anyway I now have to search the reason for shaking 
vertically.

Thanks a lot for any help!
Regards
Michael


On 27.04.2010 12:46, thomas.deweese@kodak.com wrote:
> Hi Michael,
>
> Michael Jurke<ju...@zedat.fu-berlin.de>  wrote on 04/27/2010 06:27:11 AM:
>
>    
>> After resizing, batik rendering get's strange behavior. Sometimes, on
>> smaller window, parts get rendered doubled on the downside or cheesy
>> background stays somehow. Sometimes rendering stucks completely although
>>      
>    
>> the UpdateManager works. Making the window big again, somehow magically
>> repairs the rendering.
>>      
>     If I had to guess something goes bad in the SWT<->Swing connection
> on resize.  My best guess would be the problem is related to our update
> handling.  In particular you might look at JSVGComponent in particular
> the 'updateCompleted' method (~line 1971).  I could imagine that the
> 'repaint' and/or paintImmediately could have problems, especially given
> the use of invokeAndWait.
>
>     You might see if doing a simple repaint of everything avoids the
> issues (this would be less efficient but much more efficient than
> setting the whole document).
>
>
>    


---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: batik-users-help@xmlgraphics.apache.org


Re: resizing SWT embedded JSVGCanvas

Posted by Michael Jurke <ju...@zedat.fu-berlin.de>.
On 27.04.2010 12:46, thomas.deweese@kodak.com wrote:
> Hi Michael,
>
> Michael Jurke<ju...@zedat.fu-berlin.de>  wrote on 04/27/2010 06:27:11 AM:
>
>    
>> After resizing, batik rendering get's strange behavior. Sometimes, on smaller window, parts get rendered doubled on the downside or cheesy background stays somehow. Sometimes rendering stucks completely although the UpdateManager works. Making the window big again, somehow magically repairs the rendering.
>>      
>     If I had to guess something goes bad in the SWT<->Swing connection
> on resize.  My best guess would be the problem is related to our update
> handling.  In particular you might look at JSVGComponent in particular
> the 'updateCompleted' method (~line 1971).  I could imagine that the
> 'repaint' and/or paintImmediately could have problems, especially given
> the use of invokeAndWait.
>    
Ok, I try to search for it.

>     You might see if doing a simple repaint of everything avoids the
> issues (this would be less efficient but much more efficient than
> setting the whole document).
>    
Unfortunately repaint doesn't help. Actually the behavior is little 
deterministic. In some composite constallations the problem of wrong 
rendering of some parts somewhere gets solved, but still batik dynamic 
rendering gets stucked.

So if anyone has an idea just how to revive it, would be great and solve 
my main problem! What worked out for example was to set deactivate the 
layout manager, set the JSVGCanvas size to 0 and back, reactivate and to 
call repaint or to change and set the document again. ;)

Regards,
Michael

---------------------------------------------------------------------
To unsubscribe, e-mail: batik-users-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: batik-users-help@xmlgraphics.apache.org


Re: resizing SWT embedded JSVGCanvas

Posted by th...@kodak.com.
Hi Michael,

Michael Jurke <ju...@zedat.fu-berlin.de> wrote on 04/27/2010 06:27:11 AM:

> After resizing, batik rendering get's strange behavior. Sometimes, on 
> smaller window, parts get rendered doubled on the downside or cheesy 
> background stays somehow. Sometimes rendering stucks completely although 

> the UpdateManager works. Making the window big again, somehow magically 
> repairs the rendering.

   If I had to guess something goes bad in the SWT<->Swing connection
on resize.  My best guess would be the problem is related to our update
handling.  In particular you might look at JSVGComponent in particular
the 'updateCompleted' method (~line 1971).  I could imagine that the 
'repaint' and/or paintImmediately could have problems, especially given 
the use of invokeAndWait.

   You might see if doing a simple repaint of everything avoids the
issues (this would be less efficient but much more efficient than 
setting the whole document).