magnumrocha
10/18/2024, 9:05 AMdarkmoon_uk
10/18/2024, 9:37 AMmagnumrocha
10/18/2024, 9:39 AMdarkmoon_uk
10/18/2024, 10:39 AMImageVector
format, right? That is to say, they're actually compiled source already, that performs the vector drawing. This is highly efficient as no file or format parsing is needed. You can verify this by navigating into the symbol and seeing the drawing code.darkmoon_uk
10/18/2024, 10:40 AMImage(imageVector = someIcon, ...)
darkmoon_uk
10/18/2024, 10:40 AMdarkmoon_uk
10/18/2024, 10:41 AMcompose-vector-plugin
by 'Irgaly' on Githubdarkmoon_uk
10/18/2024, 10:42 AMImageVector
source at build time. You can then access and draw them in the same way as the Material Icons.magnumrocha
10/18/2024, 10:55 AMdarkmoon_uk
10/18/2024, 11:02 AMdarkmoon_uk
10/18/2024, 11:03 AMUIImage
, the above Image
composable is multiplatform and works on iOS.darkmoon_uk
10/18/2024, 11:04 AMdarkmoon_uk
10/18/2024, 11:05 AMAndrei Salavei
10/18/2024, 8:04 PMAndy Dent
10/20/2024, 4:08 PMmagnumrocha
10/21/2024, 8:16 AMmagnumrocha
10/21/2024, 9:17 AMimport androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.toPixelMap
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.asSkiaPath
import androidx.compose.ui.graphics.toComposeImageBitmap
import androidx.compose.ui.graphics.vector.VectorGroup
import androidx.compose.ui.graphics.vector.VectorNode
import androidx.compose.ui.graphics.vector.VectorPath
import androidx.compose.ui.graphics.vector.toPath
import platform.UIKit.UIImage
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.cinterop.convert
import kotlinx.cinterop.refTo
import org.jetbrains.skia.Color
import org.jetbrains.skia.Surface
import platform.CoreGraphics.CGBitmapContextCreate
import platform.CoreGraphics.CGBitmapContextCreateImage
import platform.CoreGraphics.CGColorSpaceCreateDeviceRGB
import platform.CoreGraphics.CGColorSpaceRelease
import platform.CoreGraphics.CGContextRelease
import platform.CoreGraphics.CGImageAlphaInfo
import platform.CoreGraphics.CGImageRelease
@OptIn(ExperimentalForeignApi::class)
fun ImageVector.toUIImage(width: Int, height: Int): UIImage? =
this.toImageBitmap(width, height).toUIImage()
private fun ImageVector.toImageBitmap(width: Int, height: Int): ImageBitmap {
val surface = Surface.makeRasterN32Premul(width, height)
val canvas = surface.canvas
canvas.clear(Color.TRANSPARENT) // clear the canvas
with(canvas) { // draw the ImageVector
val paint = org.jetbrains.skia.Paint().apply {
color = Color.BLACK // Change color as needed
}
drawPath(toPath().asSkiaPath(), paint)
}
return surface.makeImageSnapshot().toComposeImageBitmap()
}
@OptIn(ExperimentalForeignApi::class)
private fun ImageBitmap.toUIImage(): UIImage? {
val pixelMap = toPixelMap()
val width = pixelMap.width
val height = pixelMap.height
val colorSpace = CGColorSpaceCreateDeviceRGB()
val data = pixelMap.buffer.toUIntArray()
val rowBytes = 4 * width
val context = CGBitmapContextCreate(
data = data.refTo(0),
width = width.convert(),
height = height.convert(),
bitsPerComponent = 8.convert(),
bytesPerRow = rowBytes.convert(),
space = colorSpace,
bitmapInfo = CGImageAlphaInfo.kCGImageAlphaPremultipliedLast.value
)
val cgImage = CGBitmapContextCreateImage(context)
val image = UIImage.imageWithCGImage(cgImage!!)
CGContextRelease(context)
CGColorSpaceRelease(colorSpace)
CGImageRelease(cgImage)
return image
}
private fun ImageVector.toPath(): Path = Path().apply {
traverseNodes(root, this)
}
private fun traverseNodes(node: VectorNode, path: Path) {
when (node) {
is VectorGroup -> {
node.iterator().forEach { childNode ->
traverseNodes(childNode, path)
}
}
is VectorPath -> {
path.addPath(node.pathData.toPath())
}
}
}