BigBadaboom / androidsvg

SVG rendering library for Android
http://bigbadaboom.github.io/androidsvg/
Apache License 2.0
1.19k stars 226 forks source link

Scale to fit code removes embedded images #236

Closed AndreKR closed 2 years ago

AndreKR commented 2 years ago

I'm trying to render this SVG into an ImageView so that it fills the whole ImageView while keeping the aspect ratio.

The SVG has width and height but no viewBox, so I added the recommended code (essentially the same case as "Dealing with Inkscape files"):

svg.setDocumentViewBox(0f, 0f, svg.documentWidth, svg.documentHeight);
svg.setDocumentHeight("100%")
svg.setDocumentWidth("100%")

Without the extra settings it renders like this:

image

With the extra settings the scaling is as desired, but all the embedded images are missing:

image

Here is the complete code ```kotlin val locationNumber = "2-2192362" val imageView = root.findViewById(R.id.weatherGraph) val resp: HttpResponse = ktorHttpClient.request { method = HttpMethod.Get url.takeFrom("https://www.yr.no/en/content/$locationNumber/meteogram.svg") header("User-Agent", "[email address redacted]") } val svg = SVG.getFromString(resp.readText()) val b = Bitmap.createBitmap(imageView.width, imageView.height, Bitmap.Config.ARGB_8888) val c = Canvas(b) c.drawRGB(255, 255, 255) svg.setDocumentViewBox(0f, 0f, svg.documentWidth, svg.documentHeight); svg.setDocumentHeight("100%") svg.setDocumentWidth("100%") svg.renderToCanvas(c) imageView.setImageBitmap(b) ```
BigBadaboom commented 2 years ago

Thanks for the report.

Interesting. It looks like there might be a bug with either child <svg> elements, or <use> elements when a viewBox is involved. I'll have to investigate and see what is happening.

Issue236_meteogram.zip

AndreKR commented 2 years ago

I looked into this a bit and I noticed something...

So, svg.setDocumentViewBox(0f, 0f, svg.documentWidth, svg.documentHeight); is enough to trigger the issue.

Those little icons look like this in the source: image

These three function are involved:

https://github.com/BigBadaboom/androidsvg/blob/dbe1a8b44339daea2b8bb9b8abed219db6ed4563/androidsvg/src/main/java/com/caverock/androidsvg/utils/SVGAndroidRenderer.java#L639-L645

https://github.com/BigBadaboom/androidsvg/blob/dbe1a8b44339daea2b8bb9b8abed219db6ed4563/androidsvg/src/main/java/com/caverock/androidsvg/utils/SVGAndroidRenderer.java#L703-L714

https://github.com/BigBadaboom/androidsvg/blob/dbe1a8b44339daea2b8bb9b8abed219db6ed4563/androidsvg/src/main/java/com/caverock/androidsvg/utils/SVGAndroidRenderer.java#L291-L297

When I didn't call setDocumentViewBox() then the call to render() in line 644 would have the viewPort parameter set to [0.0 0.0 24.0 24.0]. (This seems to make sense because the icon is to be rendered into a space 24x24 in size?)

But when I called setDocumentViewBox() then the call to render() would have viewPort set to [0.0 0.0 782.0 391.0]. (That seems to be the full size of the document.) This is because in the error case, state.viewBox in getCurrentViewPortInUserUnits() is not null, unlike in the working case where it is null.

Unfortunately this is where I'm a bit stuck because I don't know which state exactly state is supposed to represent and why the document viewbox might "leak" down into the viewport of sub SVG elements.

BigBadaboom commented 2 years ago

Thanks for the new clues. I can reproduce this in a simple test case now. I'm looking into the cause.

BigBadaboom commented 2 years ago

This now fixed. The fix will be in the 1.5 release.