Unverified Commit 233ceed4 authored by Oleksandr Karpovich's avatar Oleksandr Karpovich Committed by GitHub

document js Wrapper functions and hide internal functions (#483)

* document js Wrapper functions and hide internal functions

* docs for CanvasRenderer and SkiaLayer in jsMain
Co-authored-by: 's avatarOleksandr Karpovich <oleksandr.karpovich@jetbrains.com>
parent 99eeba54
...@@ -8,19 +8,39 @@ import org.jetbrains.skia.DirectContext ...@@ -8,19 +8,39 @@ import org.jetbrains.skia.DirectContext
import org.jetbrains.skia.Surface import org.jetbrains.skia.Surface
import org.jetbrains.skia.SurfaceColorFormat import org.jetbrains.skia.SurfaceColorFormat
import org.jetbrains.skia.SurfaceOrigin import org.jetbrains.skia.SurfaceOrigin
import org.jetbrains.skiko.wasm.CreateWebGLContext import org.jetbrains.skiko.wasm.createWebGLContext
import org.jetbrains.skiko.wasm.GL import org.jetbrains.skiko.wasm.GL
import org.w3c.dom.HTMLCanvasElement import org.w3c.dom.HTMLCanvasElement
/**
* CanvasRenderer takes an [HTMLCanvasElement] instance and initializes
* skiko's [Canvas] used for drawing (see [initCanvas]).
*
* After initialization [needRedraw] can be used to schedule a call to [drawFrame].
* [drawFrame] has to be implemented to perform the actual drawing on [canvas].
*/
abstract class CanvasRenderer constructor(val htmlCanvas: HTMLCanvasElement) { abstract class CanvasRenderer constructor(val htmlCanvas: HTMLCanvasElement) {
private val contextPointer = CreateWebGLContext(htmlCanvas) private val contextPointer = createWebGLContext(htmlCanvas)
private val context: DirectContext private val context: DirectContext
private var surface: Surface? = null private var surface: Surface? = null
private var renderTarget: BackendRenderTarget? = null private var renderTarget: BackendRenderTarget? = null
var canvas: Canvas? = null
/**
* An instance of skiko [Canvas] used for drawing.
* Created in [initCanvas].
*/
protected var canvas: Canvas? = null
private set
/**
* The current width of [htmlCanvas]
*/
val width: Int val width: Int
get() = htmlCanvas.width get() = htmlCanvas.width
/**
* The current height of [htmlCanvas]
*/
val height: Int val height: Int
get() = htmlCanvas.height get() = htmlCanvas.height
...@@ -29,6 +49,14 @@ abstract class CanvasRenderer constructor(val htmlCanvas: HTMLCanvasElement) { ...@@ -29,6 +49,14 @@ abstract class CanvasRenderer constructor(val htmlCanvas: HTMLCanvasElement) {
context = DirectContext.makeGL() context = DirectContext.makeGL()
} }
/**
* Initializes the canvas.
*
* @param desiredWidth - width in pixels
* @param desiredHeight - height in pixels
* @param scale - a value to adjust the canvas' size
* (https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio)
*/
fun initCanvas(desiredWidth: Int, desiredHeight: Int, scale: Float) { fun initCanvas(desiredWidth: Int, desiredHeight: Int, scale: Float) {
disposeCanvas() disposeCanvas()
htmlCanvas.width = (desiredWidth * scale).toInt() htmlCanvas.width = (desiredWidth * scale).toInt()
...@@ -44,17 +72,25 @@ abstract class CanvasRenderer constructor(val htmlCanvas: HTMLCanvasElement) { ...@@ -44,17 +72,25 @@ abstract class CanvasRenderer constructor(val htmlCanvas: HTMLCanvasElement) {
canvas = surface!!.canvas canvas = surface!!.canvas
} }
fun disposeCanvas() { private fun disposeCanvas() {
surface?.close() surface?.close()
surface = null surface = null
renderTarget?.close() renderTarget?.close()
renderTarget = null renderTarget = null
} }
/**
* This function should implement the actual drawing on the canvas.
*
* @param currentTimestamp - in milliseconds
*/
abstract fun drawFrame(currentTimestamp: Double) abstract fun drawFrame(currentTimestamp: Double)
private var redrawScheduled = false private var redrawScheduled = false
/**
* Schedules a call to [drawFrame] to the appropriate moment.
*/
fun needRedraw() { fun needRedraw() {
if (redrawScheduled) { if (redrawScheduled) {
return return
......
...@@ -8,27 +8,56 @@ import org.w3c.dom.events.KeyboardEvent ...@@ -8,27 +8,56 @@ import org.w3c.dom.events.KeyboardEvent
import org.w3c.dom.events.MouseEvent import org.w3c.dom.events.MouseEvent
import org.w3c.dom.events.WheelEvent import org.w3c.dom.events.WheelEvent
/**
* Provides a way to render the content and to receive the input events.
* Rendering and events processing should be implemented in [skikoView].
*
* SkikoLayer needs to be initialized with [HTMLCanvasElement] instance
* using [attachTo] method.
*/
actual open class SkiaLayer { actual open class SkiaLayer {
private var state: CanvasRenderer? = null private var state: CanvasRenderer? = null
/**
* [GraphicsApi.WEBGL] is the only supported renderApi for k/js (browser).
*/
actual var renderApi: GraphicsApi = GraphicsApi.WEBGL actual var renderApi: GraphicsApi = GraphicsApi.WEBGL
/**
* See https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio
*/
actual val contentScale: Float actual val contentScale: Float
get() = window.devicePixelRatio.toFloat() get() = window.devicePixelRatio.toFloat()
/**
* Fullscreen is not supported
*/
actual var fullscreen: Boolean actual var fullscreen: Boolean
get() = false get() = false
set(value) { set(value) {
if (value) throw Exception("Fullscreen is not supported!") if (value) throw Exception("Fullscreen is not supported!")
} }
/**
* Transparency is not supported
*/
actual var transparency: Boolean actual var transparency: Boolean
get() = false get() = false
set(value) { set(value) {
if (value) throw Exception("Transparency is not supported!") if (value) throw Exception("Transparency is not supported!")
} }
/**
* Schedules a drawFrame to the appropriate moment.
*/
actual fun needRedraw() { actual fun needRedraw() {
state?.needRedraw() state?.needRedraw()
} }
/**
* An implementation of SkikoView with content rendering and
* event processing logic.
*/
actual var skikoView: SkikoView? = null actual var skikoView: SkikoView? = null
actual fun attachTo(container: Any) { actual fun attachTo(container: Any) {
...@@ -44,6 +73,10 @@ actual open class SkiaLayer { ...@@ -44,6 +73,10 @@ actual open class SkiaLayer {
private var desiredWidth = 0 private var desiredWidth = 0
private var desiredHeight = 0 private var desiredHeight = 0
/**
* Initializes the [CanvasRenderer] and events listeners.
* Delegates rendering and events processing to [skikoView].
*/
fun attachTo(htmlCanvas: HTMLCanvasElement, autoDetach: Boolean = true) { fun attachTo(htmlCanvas: HTMLCanvasElement, autoDetach: Boolean = true) {
// Scale canvas to allow high DPI rendering as suggested in // Scale canvas to allow high DPI rendering as suggested in
// https://www.khronos.org/webgl/wiki/HandlingHighDPI. // https://www.khronos.org/webgl/wiki/HandlingHighDPI.
......
...@@ -4,20 +4,26 @@ import org.jetbrains.skia.impl.NativePointer ...@@ -4,20 +4,26 @@ import org.jetbrains.skia.impl.NativePointer
import org.w3c.dom.HTMLCanvasElement import org.w3c.dom.HTMLCanvasElement
import kotlin.js.Promise import kotlin.js.Promise
external val wasmSetup: Promise<Boolean> /**
* Invokes a callback [onReady] as soon as onRuntimeInitialized happens.
* Calling onWasmReady after onRuntimeInitialized invokes [onReady] as well.
* It's safe to call wasm functions within [onReady] callback, or after it was invoked.
*/
external fun onWasmReady(onReady: () -> Unit) external fun onWasmReady(onReady: () -> Unit)
external interface GLInterface { internal external val wasmSetup: Promise<Boolean>
private external interface GLInterface {
fun createContext(context: HTMLCanvasElement, contextAttributes: dynamic): NativePointer; fun createContext(context: HTMLCanvasElement, contextAttributes: dynamic): NativePointer;
fun makeContextCurrent(contextPointer: NativePointer): Boolean; fun makeContextCurrent(contextPointer: NativePointer): Boolean;
} }
external object GL : GLInterface { internal external object GL : GLInterface {
override fun createContext(context: HTMLCanvasElement, contextAttributes: dynamic): Int = definedExternally override fun createContext(context: HTMLCanvasElement, contextAttributes: dynamic): Int = definedExternally
override fun makeContextCurrent(contextPointer: NativePointer): Boolean = definedExternally override fun makeContextCurrent(contextPointer: NativePointer): Boolean = definedExternally
} }
external interface ContextAttributes { internal external interface ContextAttributes {
val alpha: Int? val alpha: Int?
val depth: Int? val depth: Int?
val stencil: Int? val stencil: Int?
...@@ -32,7 +38,7 @@ external interface ContextAttributes { ...@@ -32,7 +38,7 @@ external interface ContextAttributes {
val majorVersion: Int? val majorVersion: Int?
} }
fun ContextAttributes.asJsObject(): dynamic { internal fun ContextAttributes.asJsObject(): dynamic {
val jsObject = js("{}") val jsObject = js("{}")
alpha?.let { jsObject.alpha = alpha } alpha?.let { jsObject.alpha = alpha }
depth?.let { jsObject.depth = depth } depth?.let { jsObject.depth = depth }
...@@ -50,7 +56,7 @@ fun ContextAttributes.asJsObject(): dynamic { ...@@ -50,7 +56,7 @@ fun ContextAttributes.asJsObject(): dynamic {
} }
fun CreateWebGLContext(canvas: HTMLCanvasElement, attr: ContextAttributes? = null): NativePointer { internal fun createWebGLContext(canvas: HTMLCanvasElement, attr: ContextAttributes? = null): NativePointer {
val contextAttributes = object : ContextAttributes { val contextAttributes = object : ContextAttributes {
override val alpha = attr?.alpha ?: 1 override val alpha = attr?.alpha ?: 1
override val depth = attr?.depth ?: 1 override val depth = attr?.depth ?: 1
......
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