Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Large SVG(1000x1000) does not load on Software Layer #245

Closed
DavidCorrado opened this issue Dec 21, 2021 · 11 comments
Closed

Large SVG(1000x1000) does not load on Software Layer #245

DavidCorrado opened this issue Dec 21, 2021 · 11 comments

Comments

@DavidCorrado
Copy link

Glide Version:
4.12.0

Integration libraries:
https://github.com/BigBadaboom/androidsvg

Device/Android Version:
Pixel 4 API 30 emulator and misc android physical devices

Issue details / Repro steps / Use case background:
If you run on a Pixel 4 API 30 emulator in portrait the android image displays. In landscape it does not show the image but instead just the background.

Actual:
Landscape with the sample project with aspect ratio 3:2 does not display image

Expected:
Landscape with sample project with aspect ratio 3:2 does display android icon

Important Note:
If you choose aspect ratio 3:1 it works

Glide load line / GlideModule (if any) / list Adapter code (if any):
https://github.com/DavidCorrado/GlideSVGBug

        val requestBuilder = GlideApp.with(this)
            .`as`(PictureDrawable::class.java)
            .transition(withCrossFade())
            .listener(SvgSoftwareLayerSetter())
        requestBuilder.load(Uri.parse("https://upload.wikimedia.org/wikipedia/commons/d/d7/Android_robot.svg")).into(findViewById(R.id.articleHeaderImage))

All code copied from
https://github.com/bumptech/glide/tree/master/samples/svg

Layout XML:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">

<ImageView
    android:id="@+id/articleHeaderImage"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:contentDescription="@null"
    app:layout_constraintDimensionRatio="3:2"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    tools:background="#0289A0" />

</androidx.constraintlayout.widget.ConstraintLayout>

Stack trace / LogCat:
N/A

@BigBadaboom
Copy link
Owner

Also posted on the Glide issue tracker here: bumptech/glide#4710

@BigBadaboom
Copy link
Owner

Thanks for reporting this issue.

At first glance, it's hard to see how it could be AndroidSVG or Glide at fault here. Glide is just fetching an SVG and calling AndroidsSVG to parse it to a PictureDrawable. That behaviour will be identical for both portrait and landscape orientations. Those operations are both independent of the layout and the device dimensions. I don't see how the device orientation could affect the behaviour of either of our two libraries.

I am more inclined to suspect that the cause is a quirk, or perhaps bug, related to ConstraintLayout.

@DavidCorrado When you say that all that is displayed is "just the background", do you mean the app background? Your layout has no background colour. So I assume that is what you mean.

Are you sure that the ImageView is not just collapsing to zero size, because the constraints can't be met in landscape mode? Have you tried checking if that is the problem? You could, for instance:

  • read the ImageView bounds at runtime, or
  • add a background colour to the ImageView to see if that is displayed.

Or perhaps try testing on an emulator device that would support a 3:2 aspect ratio. Such as a tablet.

@DavidCorrado
Copy link
Author

Thanks for the reply.

Some things I have tried is I swapped out the svg with a png and it worked via glide. Also I tried the background color and it does appear on landscape when loading the svg in landscape the background color disappears. But interestingly enough if I remove the SVG loading code from glide it works. So something with running the glide svg loading code causes the imageview to goto 0 height or something.

I will continue exploring here and post what I find. So some interesting things to explore:

  1. Do aspect ratio without constraint layout
  2. Try landscape without aspect ratio
  3. See why in landscape the image gets collapsed

@DavidCorrado
Copy link
Author

Found out something interesting
Tested with Pixel 4 emulator, Pixel 5, Samsung20+ all with same results as above.

Pixel C tablet emulator works.

Also found an warning in the logs related to landscape
W/View: AppCompatImageView not displayed because it is too large to fit into a software layer (or drawing cache), needs 10422744 bytes, only 9849600 available

So I commented
.listener(SvgSoftwareLayerSetter())

It worked. Still not sure root cause but it does appear something with the landscape image that gets generated is over the maximum of the software layer.

So the image gets computed to be 10MB it seems. I am not sure what is expected here or the root cause but something to dig into.

@DavidCorrado
Copy link
Author

Also I am able to replicate with portrait if I change the imageview to 1000x1000. So I removed the constraintlayout and pushed out to my repo. So it definitely has to do with software layer not supporting larger sizes.

@BigBadaboom
Copy link
Owner

Ah interesting.

I haven't ever come across that software layer memory restriction before. For a long time setting a layer to be software was necesary due to the fact that many Canvas methods were not supported in hardware accelerated layers. That is no longer the case for more recent versions of Android.

I have no idea if that limit was always there or not. We may just be hitting it now due to how high screen resolutions are getting. The Pixel4 screen is 1080x2280. So in landscape, at 3:2, the ImageView could potentially end up at something like:

2200 x 1466 x 4 = 12,900,800 bytes

If that 10422744 is right, that would make your ImageView 1977 x 1318 - if my algebra is correct.

In any case, you found the right solution. You would only need to worry if you need to support old versions of Android.
If you do, you may want to consider switching from the ImageView/PictureDrawable solution that the Glide demo users. The alternative is to render directly to the Canvas.

Thanks for the doing the follow-up work.

Paul

@DavidCorrado DavidCorrado changed the title Aspect Ratio 3:2 in landscape with SVG does not load Large SVG(1000x1000) does not load on Software Layer Dec 22, 2021
@DavidCorrado
Copy link
Author

Cool so it seems according to
https://developer.android.com/guide/topics/graphics/hardware-accel#unsupported
If you set your min sdk to 23 you should be ok to remove it right?

Thanks. Appreciate your support in helping point me in a good direction

@DavidCorrado
Copy link
Author

Actually can you clarify what the min sdk is to remove the software layer. Not sure what exactly canvas APIs you are using. Seems like some things are 28

@DavidCorrado
Copy link
Author

Is this something where it works or doesnt work? So I can test. Or depending on the SVG it might hit a different code path where some SVGs fail

@BigBadaboom
Copy link
Owner

BigBadaboom commented Dec 22, 2021

I think 23 should be fine - to support drawPicture().

AndroidSVG uses Paint.setPathEffect() for dashed lines. That's listed as SDK 28. But I think that just means that the path effects are calculated on the GPU. The dashes should still render on SDK 23-27 devices, via software on the CPU side.

@DavidCorrado
Copy link
Author

Thanks so much. I appreciate your time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants