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 André Ávila <as...@nextech.com.br> on 2006/05/09 23:34:41 UTC

JSVGCanvas resizing transform

Hello,

I'm still struggling with this issue, so I would like some suggestions on how to approach it.

I have a JSVGCanvas in an applet. That canvas holds an overlay that paints Java2D shapes. Everytime a rendering transform is applied to the canvas, I have my overlay apply the same transform to all Java2D shapes, so they all keep the same relative position, regardless of the zooming/panning/rotation.

Now, my problem is that, when the JSVGCanvas gets resized, the document is transformed to fit in the entire new area. This means that, if the canvas' size is reduced, the document is scaled down, and so on. This is the default Batik behavior.

I would like to use the same approach I described above to keep my overlay's shapes in synch with the canvas when it is resized. However, I was not able to determine which AffineTransform is applied to the canvas. 

I got to a very close effect by messing with the viewBox transform, but the synch is not perfect (the shapes always get a little displaced) and the amount of code for doing that is really disturbing. If I could just grab the AffineTransform applied to the canvas in a resize operation, that could be accomplished with 2 lines of code. 

Any ideas will be most welcome.

Re: JSVGCanvas resizing transform

Posted by th...@kodak.com.
Hi André,

André Ávila <as...@nextech.com.br> wrote on 05/10/2006 10:16:52 AM:

> > André Ávila <as...@nextech.com.br> wrote on 05/09/2006 05:34:41 PM:
> >
> > > Now, my problem is that, when the JSVGCanvas gets resized, the 
document
> > > is transformed to fit in the entire new area. This means that, if 
the
> > > canvas' size is reduced, the document is scaled down, and so on. 
This is the
> > > default Batik behavior.
> >
> >    Ok, now I understand the issue.  You need to use the 'viewing 
transform'
> > (JSVGComponent.getViewingTransform()) the problem is that I'm not sure 
you
> > can hold the data in 'screen space' like you more or less currently 
are.
> > You will have to transform the drawing in screen space to the viewBox
> > (aka the SVG element's user space) in order for the drawing to stay
> > consistent (likely the cause of the 'drift' you mention below).
> 
> Here's what I'm doing. Everytime a shape is created, the current canvas'
> viewing transform is stored for future reference (let's call it the
> 'original viewing transform'). When the canvas is resized, I try to 
create a
> new transform that maps from the original viewing transform to the new 
one,
> and apply that transform to the Java2D objects.

   What you need to do in concatenate the inverse of the old viewing 
transform
and the new viewing transform, something like:

        AffineTransform oldVT, newVT; // come from somewhere.
        AffineTransform ptTrans = new AffineTransfomr(newVT);
        ptTrans.concatenate(oldVT.createInverse());   // catch 
non-invertable exception...

      // transform your shapes by ptTrans.

> >    This sort of underscores for me anyway that your overlay data 
should
> > probably just be made part of the SVG document

> You are most likely right, but I have some requirements that are much 
easier
> to accomplish by keeping the Java2D objects in memory, specially because 
I
> deal with very large, complex documents, and will not be using the DOM 
in
> the future (I still have plans to use the JGVTComponent to render the
> documents, completely disposing of the DOM afterwards). After creating 
the
> shapes, the user should be able to manipulate them (move, resize, etc), 
and
> I don't think I could do that with an SVG without manipulating the DOM. 
Am I
> right?

   In theory you can manipulate the GVT tree just the way the Bridge does
in response to DOM mutation events.  However, the main problem is that for
historical reasons all of the update support for the Canvas lives in the
JSVGComponent - meaning that while there isn't any large technical hurdle 
to having a Dynamic JGVTComponent currently you can't have the GVT 
component
automatically repaint (just modified regions) like the JSVGComponent does.


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


Re: JSVGCanvas resizing transform

Posted by André Ávila <as...@nextech.com.br>.
Hi Thomas,

> André Ávila <as...@nextech.com.br> wrote on 05/09/2006 05:34:41 PM:
>
> > Now, my problem is that, when the JSVGCanvas gets resized, the document
> is
> > transformed to fit in the entire new area. This means that, if the
> canvas'
> > size is reduced, the document is scaled down, and so on. This is the
> default
> > Batik behavior.
>
>    Ok, now I understand the issue.  You need to use the 'viewing
> transform'
> (JSVGComponent.getViewingTransform()) the problem is that I'm not sure you
> can hold the data in 'screen space' like you more or less currently are.
> You will have to transform the drawing in screen space to the viewBox
> (aka the SVG element's user space) in order for the drawing to stay
> consistent
> (likely the cause of the 'drift' you mention below).

Here's what I'm doing. Everytime a shape is created, the current canvas'
viewing transform is stored for future reference (let's call it the
'original viewing transform'). When the canvas is resized, I try to create a
new transform that maps from the original viewing transform to the new one,
and apply that transform to the Java2D objects.

This works fine for translation. Some of the documents I display are
vertically oriented, so there's no rescaling when the canvas is resized, and
applying a translation solves the problem. Basically this comes down to:

double tx = originalTransform.getTranslateX() -
currentTransform.getTranslateX();
double ty = originalTransform.getTranslateX() -
currentTransform.getTranslateX();

AffineTransform mappingTransform = AffineTransform.getTranslateInstance(tx,
ty);

Shape s = mappingTransform.createTransformedShape(originalShape);

However, most documents are horizontally oriented, and get rescaled.
Probably because of my lack of intimacy with the AffineTransform, I was not
able to find the correct scale mapping. I tried the same approach above but
could not obtain the correct scaling factor. I've tried applying some
corrections, but I still get a small displacement no matter what.

I know I crossed the Batik line here, but I was hoping you could maybe tell
me what's wrong with this approach.

>    This sort of underscores for me anyway that your overlay data should
> probably just be made part of the SVG document (at least once the
> interactive
> drawing part is done) that way you wouldn't have to worry about _any_ of
> this
> nonsense.

You are most likely right, but I have some requirements that are much easier
to accomplish by keeping the Java2D objects in memory, specially beacuse I
deal with very large, complex documents, and will not be using the DOM in
the future (I still have plans to use the JGVTComponent to render the
documents, completely disposing of the DOM afterwards). After creating the
shapes, the user should be able to manipulate them (move, resize, etc), and
I don't think I could do that with an SVG without manipulating the DOM. Am I
right?

Again, many thanks for your help,

André


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


Re: JSVGCanvas resizing transform

Posted by th...@kodak.com.
Hi André,

André Ávila <as...@nextech.com.br> wrote on 05/09/2006 05:34:41 PM:

> Now, my problem is that, when the JSVGCanvas gets resized, the document 
is 
> transformed to fit in the entire new area. This means that, if the 
canvas' 
> size is reduced, the document is scaled down, and so on. This is the 
default 
> Batik behavior.

   Ok, now I understand the issue.  You need to use the 'viewing 
transform'
(JSVGComponent.getViewingTransform()) the problem is that I'm not sure you
can hold the data in 'screen space' like you more or less currently are.
You will have to transform the drawing in screen space to the viewBox 
(aka the SVG element's user space) in order for the drawing to stay 
consistent
(likely the cause of the 'drift' you mention below).

   This sort of underscores for me anyway that your overlay data should 
probably just be made part of the SVG document (at least once the 
interactive
drawing part is done) that way you wouldn't have to worry about _any_ of 
this
nonsense.

> I would like to use the same approach I described above to keep my 
overlay's 
> shapes in synch with the canvas when it is resized. However, I was not 
able to
> determine which AffineTransform is applied to the canvas. 
> 
> I got to a very close effect by messing with the viewBox transform, but 
the 
> synch is not perfect (the shapes always get a little displaced) and the 
amount
> of code for doing that is really disturbing. If I could just grab the 
> AffineTransform applied to the canvas in a resize operation, that could 
be 
> accomplished with 2 lines of code. 
> 
> Any ideas will be most welcome.

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