Unverified Commit 1ecd5c8a authored by Nikolay Igotti's avatar Nikolay Igotti Committed by GitHub

More commonized rendering (#258)

parent 41589829
......@@ -53,7 +53,10 @@ kotlin {
binaries {
executable {
entryPoint = "org.jetbrains.skiko.sample.main"
freeCompilerArgs += listOf("-linker-option", "-framework", "-linker-option", "Metal")
freeCompilerArgs += listOf(
"-linker-option", "-framework", "-linker-option", "Metal",
"-linker-option", "-framework", "-linker-option", "CoreText",
)
}
}
}
......
// Use `xcodegen` first, then `open ./SkikoSample.xcodeproj` and then Rub
// Use `xcodegen` first, then `open ./SkikoSample.xcodeproj` and then Run button in XCode.
package org.jetbrains.skiko.sample
import org.jetbrains.skia.*
import org.jetbrains.skiko.*
import kotlinx.cinterop.*
import platform.UIKit.*
import platform.Foundation.*
fun main(args: Array<String>) {
fun main() {
val paint = Paint().apply { color = Color.GREEN }
println("Paint is $paint")
runSkikoMain()
}
fun runSkikoMain(args: Array<String> = emptyArray()) {
memScoped {
val argc = args.size + 1
val argv = (arrayOf("skikoApp") + args).map { it.cstr.ptr }.toCValues()
autoreleasepool {
UIApplicationMain(argc, argv, null, NSStringFromClass(SkikoAppDelegate))
}
}
}
package org.jetbrains.skiko
package org.jetbrains.skiko.sample
import kotlinx.cinterop.*
import platform.Foundation.*
......@@ -23,14 +23,3 @@ class SkikoAppDelegate : UIResponder, UIApplicationDelegateProtocol {
return true
}
}
\ No newline at end of file
fun runSkikoMain(args: Array<String> = emptyArray()) {
memScoped {
val argc = args.size + 1
val argv = (arrayOf("skikoApp") + args).map { it.cstr.ptr }.toCValues()
autoreleasepool {
UIApplicationMain(argc, argv, null, NSStringFromClass(SkikoAppDelegate))
}
}
}
\ No newline at end of file
package org.jetbrains.skiko
package org.jetbrains.skiko.sample
import kotlinx.cinterop.*
import org.jetbrains.skiko.SkiaLayer
import platform.Foundation.*
import platform.UIKit.*
import platform.CoreGraphics.CGPointMake
import platform.CoreGraphics.CGRectMake
import platform.Foundation.NSCoder
import platform.Foundation.NSSelectorFromString
@ExportObjCClass
class SkikoViewController : UIViewController {
......@@ -17,19 +15,6 @@ class SkikoViewController : UIViewController {
@OverrideInit
constructor(coder: NSCoder) : super(coder)
@ObjCOutlet
lateinit var label: UILabel
@ObjCOutlet
lateinit var button: UIButton
var pressed = 0
@ObjCAction
fun buttonPressed() {
label.text = "Hello #${pressed++} from Skiko!"
println("Button pressed")
}
override fun viewDidLoad() {
super.viewDidLoad()
......@@ -38,7 +23,11 @@ class SkikoViewController : UIViewController {
this.size.width to this.size.height
}
val header = UIView().apply {
val layer = SkiaLayer(width.toInt(), height.toInt())
layer.initLayer()
layer.view = UIView().apply {
backgroundColor = UIColor.lightGrayColor
view.addSubview(this)
translatesAutoresizingMaskIntoConstraints = false
......@@ -47,27 +36,5 @@ class SkikoViewController : UIViewController {
widthAnchor.constraintEqualToAnchor(view.widthAnchor).active = true
heightAnchor.constraintEqualToAnchor(view.heightAnchor).active = true
}
label = UILabel().apply {
setFrame(CGRectMake(x = 10.0, y = 10.0, width = width - 100.0, height = 40.0))
center = CGPointMake(x = width / 2, y = 40.0 )
textAlignment = NSTextAlignmentCenter
text = "Press OK"
header.addSubview(this)
}
button = UIButton().apply {
setFrame(CGRectMake(x = 10.0, y = height - 100.0, width = width - 100.0, height = 40.0))
center = CGPointMake(x = width / 2, y = height / 2)
backgroundColor = UIColor.blueColor
setTitle("OK", forState = UIControlStateNormal)
font = UIFont.fontWithName(fontName = font.fontName, size = 28.0)!!
layer.borderWidth = 1.0
layer.borderColor = UIColor.colorWithRed(0x47 / 255.0, 0x43 / 255.0, 0x70 / 255.0, 1.0).CGColor
layer.masksToBounds = true
addTarget(target = this@SkikoViewController, action = NSSelectorFromString("buttonPressed"),
forControlEvents = UIControlEventTouchUpInside)
header.addSubview(this)
}
}
}
......@@ -5,42 +5,18 @@ import platform.AppKit.*
import org.jetbrains.skia.*
import org.jetbrains.skiko.*
import kotlinx.cinterop.*
import kotlin.math.cos
import kotlin.math.sin
fun main() {
// TODO: Remove me! This is to run all cleaners before main() exits.
kotlin.native.internal.Debugging.forceCheckedShutdown = true
NSApplication.sharedApplication()
createWindow("Skia/Native macos sample")
createWindow()
NSApp?.run()
}
fun createWindow(title: String) {
val window = SkiaWindow()
var angle = 0.0f
window.layer.renderer = Renderer(window.layer) {
renderer, w, h, nanoTime -> displayScene(renderer.canvas!!, nanoTime)
fun createWindow() {
val layer = SkiaLayer()
layer.renderer = GenericRenderer(layer) {
canvas, w, h, nanoTime -> displayScene(canvas, nanoTime)
}
val window = SkiaWindow(layer)
window.nsWindow.orderFrontRegardless()
}
class Renderer(
val layer: SkiaLayer,
val displayScene: (Renderer, Int, Int, Long) -> Unit
): SkiaRenderer {
var canvas: Canvas? = null
override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
this.canvas = canvas
val contentScale = layer.contentScale
canvas.scale(contentScale, contentScale)
displayScene(this, (width / contentScale).toInt(), (height / contentScale).toInt(), nanoTime)
layer.needRedraw()
}
}
......@@ -5,7 +5,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile
import org.jetbrains.kotlin.utils.keysToMap
plugins {
kotlin("multiplatform") version "1.5.31"
kotlin("multiplatform") version "1.5.31" // "1.6.0-M1"
`maven-publish`
id("org.gradle.crypto.checksum") version "1.1.0"
id("de.undercouch.download") version "4.1.1"
......
......@@ -3,15 +3,29 @@ package org.jetbrains.skiko
import org.jetbrains.skia.Canvas
import org.jetbrains.skia.Picture
interface SkiaRenderer {
fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long)
}
expect open class SkiaLayer {
expect open class SkiaLayer(properties: SkiaLayerProperties = makeDefaultSkiaLayerProperties()) {
var renderApi: GraphicsApi
val contentScale: Float
var fullscreen: Boolean
var transparency: Boolean
fun needRedraw()
}
interface SkiaRenderer {
fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long)
}
open class GenericRenderer(
val layer: SkiaLayer,
val displayScene: (Canvas, Int, Int, Long) -> Unit
): SkiaRenderer {
override fun onRender(canvas: Canvas, width: Int, height: Int, nanoTime: Long) {
val contentScale = layer.contentScale
canvas.scale(contentScale, contentScale)
displayScene(canvas, (width / contentScale).toInt(), (height / contentScale).toInt(), nanoTime)
layer.needRedraw()
}
}
internal class PictureHolder(val instance: Picture, val width: Int, val height: Int)
package org.jetbrains.skiko
import kotlinx.cinterop.*
import org.jetbrains.skia.PictureRecorder
import org.jetbrains.skia.Rect
import org.jetbrains.skiko.redrawer.Redrawer
import platform.Foundation.*
import platform.UIKit.*
actual open class SkiaLayer {
actual var renderApi: GraphicsApi = GraphicsApi.OPENGL
actual open class SkiaLayer actual constructor(
properties: SkiaLayerProperties
) {
var width: Int = 0
var height: Int = 0
constructor(width: Int, height: Int) : this(
makeDefaultSkiaLayerProperties()) {
this.width = width
this.height = height
}
actual var renderApi: GraphicsApi
get() = GraphicsApi.METAL
set(value) { throw UnsupportedOperationException() }
actual val contentScale: Float
get() = 1.0f
actual var fullscreen: Boolean
get() = TODO("Not yet implemented")
set(value) {}
get() = true
set(value) { throw UnsupportedOperationException() }
actual var transparency: Boolean
get() = TODO("Not yet implemented")
set(value) {}
get() = false
set(value) { throw UnsupportedOperationException() }
actual fun needRedraw() {
redrawer?.needRedraw()
}
lateinit var view: UIView
fun initLayer() {
println("SkiaLayer.initLayer")
//redrawer = createNativeRedrawer(this, renderApi, properties)
redrawer?.redrawImmediately()
}
var renderer: SkiaRenderer? = null
private var redrawer: Redrawer? = null
private var picture: PictureHolder? = null
private val pictureRecorder = PictureRecorder()
fun update(nanoTime: Long) {
println("SkiaLayer.update")
val width = 800f
val height = 600f
val pictureWidth = (width * contentScale).coerceAtLeast(0.0F)
val pictureHeight = (height * contentScale).coerceAtLeast(0.0F)
val bounds = Rect.makeWH(pictureWidth, pictureHeight)
val canvas = pictureRecorder.beginRecording(bounds)
renderer?.onRender(canvas, pictureWidth.toInt(), pictureHeight.toInt(), nanoTime)
val picture = pictureRecorder.finishRecordingAsPicture()
this.picture = PictureHolder(picture, pictureWidth.toInt(), pictureHeight.toInt())
}
}
package org.jetbrains.skiko.redrawer
import org.jetbrains.skiko.SkiaLayer
import org.jetbrains.skiko.SkiaLayerProperties
internal class MetalRedrawer(
private val layer: SkiaLayer,
private val properties: SkiaLayerProperties
) : Redrawer {
override fun dispose() {
TODO()
}
override fun syncSize() {
TODO()
}
override fun needRedraw() {
TODO()
}
override fun redrawImmediately() {
TODO()
}
}
......@@ -2,24 +2,25 @@ package org.jetbrains.skiko.redrawer
import org.jetbrains.skiko.SkiaLayer
import org.jetbrains.skiko.SkiaLayerProperties
import kotlin.system.getTimeNanos
internal class OpenGLRedrawer(
private val layer: SkiaLayer,
private val properties: SkiaLayerProperties
) : Redrawer {
override fun dispose() {
TODO()
println("dispose")
}
override fun syncSize() {
TODO()
println("syncSize")
}
override fun needRedraw() {
TODO()
println("needRedraw")
}
override fun redrawImmediately() {
TODO()
layer.update(getTimeNanos())
}
}
package org.jetbrains.skiko
actual open class SkiaLayer {
actual open class SkiaLayer actual constructor(
properties: SkiaLayerProperties
) {
actual var renderApi: GraphicsApi = GraphicsApi.WEBGL
actual val contentScale: Float
get() = 1.0f
......@@ -10,4 +12,7 @@ actual open class SkiaLayer {
actual var transparency: Boolean
get() = false
set(value) = throw Exception("Transparency is not supported!")
actual fun needRedraw() {
TODO("unimplemented")
}
}
......@@ -28,6 +28,7 @@ actual open class SkiaLayer internal constructor(
private val properties: SkiaLayerProperties = makeDefaultSkiaLayerProperties(),
private val renderFactory: RenderFactory
) : JPanel() {
companion object {
init {
Library.load()
......@@ -43,6 +44,11 @@ actual open class SkiaLayer internal constructor(
internal val backedLayer: HardwareLayer
actual constructor(
properties: SkiaLayerProperties
) : this(null, properties, RenderFactory.Default)
constructor(
properties: SkiaLayerProperties = makeDefaultSkiaLayerProperties(),
externalAccessibleFactory: ((Component) -> Accessible)? = null
......@@ -311,7 +317,7 @@ actual open class SkiaLayer internal constructor(
/**
* Redraw on the next animation Frame (on vsync signal if vsync is enabled).
*/
fun needRedraw() {
actual fun needRedraw() {
check(isEventDispatchThread()) { "Method should be called from AWT event dispatch thread" }
check(!isDisposed) { "SkiaLayer is disposed" }
redrawer?.needRedraw()
......
package org.jetbrains.skiko
actual open class SkiaLayer {
actual open class SkiaLayer actual constructor(
properties: SkiaLayerProperties
) {
actual var renderApi: GraphicsApi
get() = TODO("Not yet implemented")
set(value) {}
......@@ -12,4 +14,7 @@ actual open class SkiaLayer {
actual var transparency: Boolean
get() = TODO("Not yet implemented")
set(value) {}
actual fun needRedraw() {
TODO("unimplemented")
}
}
\ No newline at end of file
......@@ -7,8 +7,8 @@ import org.jetbrains.skiko.redrawer.Redrawer
import platform.AppKit.NSView
import platform.Foundation.NSMakeRect
actual open class SkiaLayer(
private val properties: SkiaLayerProperties = makeDefaultSkiaLayerProperties()
actual open class SkiaLayer actual constructor(
private val properties: SkiaLayerProperties
) {
actual var renderApi: GraphicsApi = GraphicsApi.OPENGL
actual val contentScale: Float
......@@ -50,7 +50,7 @@ actual open class SkiaLayer(
initedCanvas = false
}
fun needRedraw() {
actual fun needRedraw() {
redrawer?.needRedraw()
}
......
......@@ -3,9 +3,7 @@ package org.jetbrains.skiko
import platform.AppKit.*
import platform.Foundation.*
open class SkiaWindow(
properties: SkiaLayerProperties = makeDefaultSkiaLayerProperties()
) {
class SkiaWindow(layer: SkiaLayer) {
private val windowStyle =
NSWindowStyleMaskTitled or
NSWindowStyleMaskMiniaturizable or
......@@ -22,8 +20,6 @@ open class SkiaWindow(
backing = NSBackingStoreBuffered,
defer = true)
val layer = SkiaLayer(properties)
init {
nsWindow.contentView!!.addSubview(layer.nsView)
layer.initLayer()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment