weisJ / jsvg

Java SVG renderer
MIT License
133 stars 7 forks source link

If present, expose ViewBox of SVG on the SVGDocument API #69

Closed Gleethos closed 8 months ago

Gleethos commented 8 months ago

First up thank you, for this wonderful SVG renderer! It has helped us alot in doing modern Swing development. I immensely appreciate all the good work that is put into this.

Problem

So the problem here is relatively straight forward. Most of the SVGs in our application have a view box which defines the size of the SVG in pixels.

And one important use case for us is the ability to specify one (scaled) dimension of an SVG image in the frontend and have the other dimension be computed based on the aspect ratio of the SVG icon. But for this we need a way to access the formerly mentioned view box bounds from a loaded SVGDocument object (if the view box is present).

Looking inside the SVGDocument and the SVG it references, there is already a ViewBox onbject there which models this.

Correct me if I am wrong but it looks like there is no way to access this information from the public API, correct?

Solution

So the proposal the introduction of the following method on the SVGDocument:

public Optional<ViewBox> viewBox() {...}

This would allow us to scale our SVGs with their aspect ratios preserved.


If there is currently not enough time for this I am also happy to open a pull request with the desired changes.

weisJ commented 8 months ago

thank you for the kind words. Glad JSVG is helpful for you :)

If you don’t have any explicit width and height set then SVGDocument.size() should return the viewport dimensions. If this doesn’t fulfill your needs I am open to expose the viewbox, though probably not as an optional value as semantically every svg has one, even if not specified directly.

Gleethos commented 8 months ago

If you don’t have any explicit width and height set then SVGDocument.size() should return the viewport dimensions.

The problem is that this is not the case when the width and height was specified in the % unit. I am not intimately familiar with the exact specifications of the SVG format, but it seems to us that a percentage is a sort of multiplier either based on the size of any given parent component or on top of the view box dimensions.

I think it is best to give you an example.

Here an example SVG where the true dimensions of the image are lost when trying to scale it using the FloatSize based aspect ratio:

<?xml version="1.0" encoding="iso-8859-1"?>
<svg fill="#000000" version="1.1" 
     width="100%" height="100%" viewBox="150 0 300 600"
     xml:space="preserve">
<g>
    <g>
        <path d="M370.882,44.88c-0.176,0-0.348,0.024-0.526,0.028c-2.93-18.507-18.907-32.668-38.234-32.668
            c-5.116,0-9.987,1.016-14.459,2.815c-5.974-1.449-12.146-2.379-18.486-2.689C292.448,4.798,282.668,0,271.746,0
            c-18.503,0-33.766,13.696-36.308,31.498c-3.362,2.472-6.548,5.157-9.567,8.021c-25.827,7.956-44.599,32.004-44.599,60.441
            c0,17.482,7.173,33.228,18.642,44.672c-1.914,5.157-3.007,10.706-3.007,16.528c0,21.922,14.839,40.335,35.006,45.863
            c6.479,27.605,20.021,52.489,45.223,72.379L274.59,410.86c-5.394-6.268-13.439-9.303-21.318-4.688
            c-6.985,4.093-11.245,15.223-5.855,22.33c8.719,11.501,17.442,23.003,26.161,34.505l-2.514,121.787h46.239l-4.773-238.39
            c12.681-13.713,25.361-27.426,38.042-41.139c14.264-15.427-8.76-38.564-23.081-23.081c-5.291,5.72-10.583,11.444-15.871,17.165
            l-1.738-89.805c15.41-2.448,29.601-8.49,41.788-17.165c28.29-0.277,51.143-23.272,51.143-51.628
            c0-11.021-3.477-21.208-9.355-29.597c-0.013-3.26-0.176-6.479-0.494-9.657c6.476-5.965,10.56-14.488,10.56-23.986
            C403.522,59.494,388.908,44.88,370.882,44.88z M278.013,234.09c-6.022-8.564-10.281-17.883-13.211-27.715
            c4.435,1.371,9.009,2.432,13.685,3.178L278.013,234.09z"/>
    </g>
</g>
</svg>

The problem here is that there is no way for us to compute the aspect ratio of the image due to the size() method of the SVGDocumentreturning a FloatSize of width 100.0 and height 100.0. This may be an edge case, but it would be very useful for us to account for the view box here as well.

It would also be helpful to know the units of both the width and the height. Then we could scale the image even more accurately according to how it was designed.


... though probably not as an optional value as semantically every svg has one, even if not specified directly.

Ah ok, If a view box is always present then that would be even better! I just assumed that it may not be set as I encountered some null checks while reading through the source code.

weisJ commented 8 months ago

I see your problem now. Notably percentage values have an effect on svg documents if they are either embedded in a different svg/html document. JSVG simply treats them as pixel values for the purpose of determining the size of the document.

Ah ok, If a view box is always present then that would be even better! I just assumed that it may not be set as I encountered some null checks while reading through the source code.

You are correct in that the viewBox field of SVG may be null. Nonetheless it is possible to assign a meaningful view box to all documents. If they don't have an explicitly specified view box it implicitly is given by 0 0 <width> <height>.

I'll add a method to expose the view box on SVGDocument.

weisJ commented 8 months ago

API is available in the snapshot version. I'll publish a new release soon.