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.