Skiko (short for Skia for Kotlin) is the graphical library exposing significant part of Skia library APIs to Kotlin, along with the gluing code for rendering context.
Supported platforms:
- Kotlin/JVM on Linux(x86_64 and arm64)
- Kotlin/JVM on Windows(x86_64)
- Kotlin/JVM on macOS(x86_64 and arm64)
- Kotlin/JVM on Android(x86_64 and arm64), starting with API version 24
- Kotlin/JS + WebAssembly in browsers
- Kotlin/Native on iOS(arm64 and x64)
- Kotlin/Native on macOS (arm64 and x64)
See autogenerated API docs at https://jetbrains.github.io/skiko/
To use in build scripts one has to compute appropriate target platform and version, i.e. something like this
repositories { mavenCentral() maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") } val osName = System.getProperty("os.name") val targetOs = when { osName == "Mac OS X" -> "macos" osName.startsWith("Win") -> "windows" osName.startsWith("Linux") -> "linux" else -> error("Unsupported OS: $osName") } val osArch = System.getProperty("os.arch") val targetArch = when (osArch) { "x86_64", "amd64" -> "x64" "aarch64" -> "arm64" else -> error("Unsupported arch: $osArch") } val version = "0.8.9" // or any more recent version val target = "${targetOs}-${targetArch}" dependencies { implementation("org.jetbrains.skiko:skiko-awt-runtime-$target:$version") }Simple example for Kotlin/JVM
fun main() { val skiaLayer = SkiaLayer() skiaLayer.renderDelegate = SkiaLayerRenderDelegate(skiaLayer, object : SkikoRenderDelegate { val paint = Paint().apply { color = Color.RED } override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) { canvas.clear(Color.CYAN) val ts = nanoTime / 5_000_000 canvas.drawCircle( (ts % width).toFloat(), (ts % height).toFloat(), 20f, paint ) } }) SwingUtilities.invokeLater { val window = JFrame("Skiko example").apply { defaultCloseOperation = WindowConstants.EXIT_ON_CLOSE preferredSize = Dimension(800, 600) } skiaLayer.attachTo(window.contentPane) skiaLayer.needRedraw() window.pack() window.isVisible = true } }Simple example for iOS
fun main() { val args = emptyArray<String>() memScoped { val argc = args.size + 1 val argv = (arrayOf("skikoApp") + args).map { it.cstr.ptr }.toCValues() autoreleasepool { UIApplicationMain(argc, argv, null, NSStringFromClass(SkikoAppDelegate)) } } } class SkikoAppDelegate : UIResponder, UIApplicationDelegateProtocol { companion object : UIResponderMeta(), UIApplicationDelegateProtocolMeta @ObjCObjectBase.OverrideInit constructor() : super() private var _window: UIWindow? = null override fun window() = _window override fun setWindow(window: UIWindow?) { _window = window } override fun application(application: UIApplication, didFinishLaunchingWithOptions: Map<Any?, *>?): Boolean { window = UIWindow(frame = UIScreen.mainScreen.bounds) window!!.rootViewController = SkikoViewController( SkikoUIView( SkiaLayer().apply { renderDelegate = SkiaLayerRenderDelegate(skiaLayer, object : SkikoRenderDelegate { val paint = Paint().apply { color = Color.RED } override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) { canvas.clear(Color.CYAN) val ts = nanoTime / 5_000_000 canvas.drawCircle( (ts % width).toFloat(), (ts % height).toFloat(), 20f, paint ) } }) } ) ) window!!.makeKeyAndVisible() return true } }See this sample for complete example.
To use latest development snapshot use version 0.0.0-SNAPSHOT.