Hi Thomas,

    thanks a lot for your help. I changed and tested my class
using your proposed getBBox() method. Works great for
all SVG files I have on my hard drive.
Looks more robust now, yes feels like 98%.  :-)

    The class below can be used instead of it's base class,
extends it's base class so that - if setAutoFitToCanvas(true) -
it will automatically center/resize the svg on the canvas.
It still supports
    * canvas size changes (with automatically resizing the svg)
    * the keyboard actions
    * as well as svg's with animation.
         (changes of the documents size by a script
            may result in strange results, but that's
           true for JSVGCanvas as well)

   Right now fragIdent != null IS NOT SUPPORTED !!!
Mainly because I don't understand this parameter AND I didn't
found a single test case to understand and test it.

Greetings Heinz



public class SvgCanvasXx extends JSVGCanvas {
   
    protected int xBorder= 8;
    protected int yBorder= 8;
    protected boolean autoFitToCanvas;
    protected boolean stopProcessingOnDispose;
   

    public SvgCanvasXx() {
    }

    public SvgCanvasXx(SVGUserAgent ua, boolean eventsEnabled, boolean
selectableText) {
        super(ua, eventsEnabled, selectableText);
    }
   
    public boolean isAutoFitToCanvas() {
        return autoFitToCanvas;
    }

    public void setAutoFitToCanvas(boolean autoFit) {
        this.autoFitToCanvas= autoFit;
        if (autoFit)
            setRecenterOnResize(true);
    }
   
    public boolean isStopProcessingOnDispose() {
        return stopProcessingOnDispose;
    }

    public void setStopProcessingOnDispose(boolean
stopProcessingOnDispose) {
        this.stopProcessingOnDispose= stopProcessingOnDispose;
    }

    /** note the border will be ignored if canvas width/height <= 4 *
borderX/Y **/
    public void setInnerBorderWidth(int borderX, int borderY) {
        this.xBorder= borderX;
        this.yBorder= borderY;
    }
   
    @Override
    public void dispose() {
        if (stopProcessingOnDispose)
            stopProcessing();
        super.dispose();
    }
   
    @Override
    protected void installKeyboardActions() {
        super.installKeyboardActions();
        InputMap inputMap = getInputMap(JComponent.WHEN_FOCUSED);
        KeyStroke key;
        // .....
    }

    /**
     * overwrites calculateViewingTransform to allow autoFitToCanvas
behaviour,
     * if autoFitToCanvas is not set it will use the base's class method.
     *
     * Right now fragIdent != null IS NOT SUPPORTED !!!
     */
    @Override
    protected AffineTransform calculateViewingTransform(String
fragIdent, SVGSVGElement svgElt) {
        assert fragIdent == null; // don't understand this parameter,
have not found a simple test case yet
        if (!autoFitToCanvas || fragIdent != null)
            return super.calculateViewingTransform(fragIdent, svgElt);
        // canvas size / additional border
        Dimension d = getSize();
        int xb= 0, yb= 0;
        if (d.width  < 1) d.width  = 1;
        if (d.height < 1) d.height = 1;
        if (d.width > 4 * xBorder) // if canvas is large enough add border
            d.width-= 2 * (xb= xBorder);
        if (d.height > 4 * yBorder) // if canvas is large enough add border
            d.height-= 2 * (yb= yBorder);
        //
        AffineTransform tf;
       //
        String viewBox= svgElt.getAttributeNS(null,
ViewBox.SVG_VIEW_BOX_ATTRIBUTE);
        if (viewBox.length() == 0) {
            // no viewbox specified, make an own one
            float[] vb= calculateDefaultViewbox(fragIdent, svgElt);
            tf= ViewBox.getPreserveAspectRatioTransform(
                    vb,
SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMID, true, d.width,
d.height);
        } else {
            String aspectRatio= svgElt.getAttributeNS(null,
ViewBox.SVG_PRESERVE_ASPECT_RATIO_ATTRIBUTE);
            if (aspectRatio.length() > 0)
                tf= ViewBox.getPreserveAspectRatioTransform(svgElt,
viewBox, aspectRatio, d.width, d.height, bridgeContext);
            else {
                float[] vb= ViewBox.parseViewBoxAttribute(svgElt,
viewBox, bridgeContext);
                tf= ViewBox.getPreserveAspectRatioTransform(
                        vb,
SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMAX, true, d.width,
d.height);
            }
        }
        if (xb > 0 || yb > 0) { // center image
            AffineTransform tf2=
AffineTransform.getTranslateInstance(xb, yb);
            tf2.concatenate(tf);
            tf= tf2;
        }
        return tf;
    }
   
    protected float[] calculateDefaultViewbox(String fragIdent,
SVGSVGElement svgElt) {
        float[] vb= new float[4];
         SVGRect rc= svgElt.getBBox();
        vb[0]= rc.getX();
        vb[1]= rc.getY();
        vb[2]= rc.getWidth();
        vb[3]= rc.getHeight();
        return vb;
    }
   
}



[email protected] schrieb:
>
> Hi Heinz,
>
> Heinz Doerr <[email protected]> wrote on 06/09/2009 04:42:49 PM:
>
> > But for a doc w/o a ViewBox specified I need the "size of the
> > document".
>
>
> > But I have a few questions:
> > =====================
> > * Overall, how far away is my "90%" solution from 100% ???
> >     As I stated - I'm not sure what I'm doing here
>
>    You are close.
>
> > * I'm calling svgElt.getWidth() and getHeight(),
> >     Are those values always defined?
> >     Are those values always pixel based?
>
>      No, and no, although the majority are pixels (well
> unitless which is userspace units).
>
> > * to get the origin of the doc I call  svgElt.getX() and getY(),
> >     Is this correct?
> >     Are those values always pixel based?
>
>     No, and no, those are supposed to be ignored on the
> root SVG element.
>
> > With some help I would surely try to contribute a "98%" solution
> > to the community.
>
>    The best way to get the last 8% would be to move to
> using 'getBBox()' on the root SVG Element.  This will
> tell you the actual size of the geometry in the document.
>
> >
> > [email protected] schrieb:
> >
> > Hi Heinz Doerr,
> >
> > Heinz Doerr <[email protected]> wrote on 06/08/2009 06:20:46 AM:
> >
> > > I'm using the JSVGCanvas , very nice, but I need to scale the
> displayed SVG
> > > image to fit the window size of the canvas.
> > > So no scrolling, rotation or panning needed.
> > > This should work for any SVG (with or w/o a ViewBox) - changing
> the svg
> > > file itself it not an option.
> > > The aspect ratio should always be unchanged.
> > > Nice, would be to have an option to either scale down only or to allow
> > > scale up and down.
> >
> >    That is quite a list of requirements.
> >
> > > Because I didn't found any 'scale-to-fit' hints, I was thinking if it
> > > would be better to use
> > > the BufferedImageTranscoder and convert the svg to an image. The
> transcoder
> > > has the scale-to-fit build in (very nice - works with any SVG,
> keeps the
> > > aspect ratio), but then I got problems loading some svg's. I'm not
> sure
> > > how to get javascript, onLoad, references to elements, and
> security under
> > > control. Having animation with the Canvas solution would also be a
> > nice to have.
> >
> >    There are options to run onload scripts before the rendering.
> >
> > > So I think I'm looking for something like an Action AutoFit for the
> > > canvas, and this action automatically triggered (at the right time?).
> >
> >    What I think will work best is for you to override
> > 'JSVGComponent.calculateViewingTransform' to implement your
> > desired scale to fit algorythem.  If you get it working you
> > might consider contributing it back so others could make use
> > of it. 

Reply via email to