accompanist-drawablepainter: PictureDrawable doesn't scale
theojarrus opened this issue · 4 comments
Describe the bug
PictureDrawable displayed using Compose Image and Accompanist DrawablePainter doesn't scale
To Reproduce
- Create PictureDrawable
val picture = Picture()
val pictureCanvas = picture.beginRecording(100, 100)
pictureCanvas.drawCircle(50f, 50f, 50f, Paint())
picture.endRecording()
val drawable = PictureDrawable(picture)
- Show using Compose Image and Accompanist DrawablePainter
Image(
painter = rememberDrawablePainter(drawable),
contentDescription = null,
contentScale = ContentScale.FillHeight,
modifier = Modifier.height(200.dp).border(2.dp, color = Color.Cyan)
)
- See the image is not scaled
Expected behavior
Image scales depending on available size and scale strategy
Screenshots
Actual | Expected (fixed using canvas#scale) |
---|---|
Environment
- Android OS version: API 34
- Device: Emulator, Google Pixel 4
- Accompanist version: 0.34.0
Additional context
Thoughts about fixing
In search of the reason why my image does not scale, I deepened into the source code. I found, that picture receives size in Picture#beginRecording, then getting long value from Picture#nativeBeginRecording, which also receives picture size, and saves this long value to PictureCanvas. After that, inside Picture#draw, which is called to draw picture on some canvas, Picture#nativeDraw is called. Don't know what magic happens then, but as the result picture is rendered using size recieved in Picture#beginRecording and not Drawable#setBounds. I managed to achieve the desired result using Canvas#scale, I don't know if that can cause performance problems, but at least it works. So, it can be fixed by overwriting DrawablePainter#onDraw for PictureDrawable, here's the example of working code:
// Create canvas with size bigger than picture size
Canvas(Modifier.height(200.dp).width(200.dp).border(2.dp, color = Color.Cyan)) {
// Create simple PictureDrawable
val picture = Picture()
val pictureCanvas = picture.beginRecording(100, 100)
pictureCanvas.drawCircle(50f, 50f, 50f, Paint())
picture.endRecording()
val drawable = PictureDrawable(picture)
// Render PictureDrawable on canvas
drawIntoCanvas { canvas ->
// Set PictureDrawable bounds
drawable.setBounds(0, 0, size.width.roundToInt(), size.height.roundToInt())
// Scale canvas
val scalex = size.width / drawable.intrinsicWidth
val scaley = size.height / drawable.intrinsicHeight
canvas.scale(scalex, scaley)
// Draw PictureDrawable
drawable.draw(canvas.nativeCanvas)
}
}
Why found this bug
I'm writing library with runtime image generation, it uses Picture to render graphics and pass through app. As the result I want to show it somewhere using Compose Image, so I used accompanist-drawablepainter, but faced this issue.
@bentrengrove Check this issue please