SVG and its boundaries

Hi and Hello

is there a way to let [Drawable] consider svg’s viewport/boundaries context while processing its drawing?

In this topic im facing particular scenario.

What do you mean by “consider”? If you have something specific in mind, could you suggest a code change?

to optionally let [Drawable] use svg’s viewport/size attributes in order to display it within its original context (with offsets/position)

With [DrawableShape] call to pathChanged(), path’s bounds (actuall visible shape bounds) are passed to setBoundsToEnclose() in order to calculate delta for originRelativeToComponent which is used to alter the transform at the drawn stage. That is totally fine for most of the cases but it doesnt give us an option to respect original boundaries of a given path container that comes with xml/svg .
Would you be so keen to add adequate flag/option to ommit offset substraction while parent is a nullptr ?

ive been looking further into the parser + co, and i found that altering [DrawableComposite]'s getDrawableBounds() method could provide an option for using bounding box values as a unity for drawing and transformation of a given paths. This way shapes are drawn within its original viewbox boundaries that comes as an attribute specified inside their document file.

As such relation might be only related to svg parsing, an appropriate flag could be specified by the user while passing desired svg document to the Drawable’s parser i guess.
However, a more adorable way would be respecting svg’s enable-background attribute. It could be used as a indicator for the parser, but obviously it would introduce visual side effects across ale the legacy projects.

Maybe I’ve misunderstood what you’re asking, but isn’t this what DrawableComposite::resetBoundingBoxToContentArea() is for?

i havent seen the implementation, just checked the method on the fly.
could not aquire what its name stands here for.
does it work in relation with setTransformToFit() ?

I guess so, I think setTransformToFit uses the bounds that this would set up.

wait ,bounding box consist of content boundary already.
this is how i retrieve them to calculate scale myself later on against custom size

viewBox = image->getBoundingBox().getBounds(nullptr);

otherwise, no luck

as a usecase, i want to resize SVG to match desired bounds while preserving ratio and respecting its viewbox/content area.

and this is how i achieve proper placement and scale, where the scale “float s” is sort of a magnify level

AffineTransform getTransformWith(int w, int h, float s, RectanglePlacement::Flags p = RectanglePlacement::fillDestination) {
	if(viewBox.getWidth() == 0 || viewBox.getHeight() == 0) return AffineTransform();
	float newX = 0.f;
	float newY = 0.f;
	float scaleX = w / viewBox.getWidth();
	float scaleY = (h > 0.f ? h : w) / viewBox.getHeight();
	scaleX *= s;
	scaleY *= s;

	if(p != RectanglePlacement::stretchToFit) {
		scaleX = (p == RectanglePlacement::Flags::centred) ? 1.f : jmax(jmin(scaleX, scaleY), 0.0f);
		scaleY = scaleX;
		newX += (w - viewBox.getWidth() * scaleX) / 2.0f;    // centre
		newY += ((h > 0.f ? h : w) - viewBox.getHeight() * scaleX) / 2.0f;    // centre
	auto at = AffineTransform::scale(scaleX, scaleY).translated(newX, newY);
	return at.isSingularity() ? AffineTransform() : at;

Get struggling with this too…
I have an non-symmetric sized svg (see picture), which is perfectly centred in its current svg document bounds.

How can use I drawWithin to draw it centred, and respect its svg bounds, so i can rotate it, so that the circle stays at the position, and does not rotate around the wrong center.


im not sure if i could do this with the drawWithin() if your SVG itslef doesnt have helping container within.
Perhaps you would have to translate whole path in your drawing procedure, similarry to what i did with getTransformWith() above .
If you dont mind, you could provide invisible container inside your SVG document that has the desired boundaries and then the parser will work around its bounds relatively.

1 Like

Thank you very much, using invisible box is seems to be the easiest workaround to solve this problem. :slight_smile:

unfortunatelly :confused:
have fun !

You can also name objects and groups with ids in the SVG (e.g., in Illustrator) and it’s reasonably trivial to filter out specific objects or groups of objects based on the ids at the XML level. Then you could have multiple items laid out in the same page with bounding boxes as the reference bounds for those objects.

ive done it too, its too much hassle for displaying scenarios, unless you are building svg editor :slight_smile:

you can as well strip down DrawableComposite into the paths and do the same without editing XML id’s.

I’m late to the party, but I think the problem with setTransformToFit() is that it uses
getDrawableBounds(). In cases where there is intentional space between svg elements and the viewbox, the drawable bounds won’t be the same as the content bounds. You can call resetBoundingBoxToContentArea(), but that won’t change the drawable bounds, right?

The only way I’ve found so far to accomplish what is desired is to do something like this when drawing:

        Rectangle<float> svgstate_default_rect(0,0,512,512);
        auto transform = placement.getTransformToFit(svgstate_default_rect, dest_bounds);
        drawable->draw( graphics, 1.0f, transform );

But I’m sure this is a brittle hack.

1 Like