
Graphical library integrating Skia APIs for rendering and window management. Enables cross-platform development with examples for JVM and iOS applications.
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:
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://redirector.kotlinlang.org/maven/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.
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:
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://redirector.kotlinlang.org/maven/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.