Unverified Commit be90a3fa authored by Shagen Ogandzhanian's avatar Shagen Ogandzhanian Committed by GitHub

Build skiko with kotlin 2.2.20 (#1179)

This is backport of https://github.com/JetBrains/skiko/pull/1173 to
Kotlin 2.2.20

---------
Co-authored-by: 's avatarIvan Matkov <ivan.matkov@jetbrains.com>
parent 89888a47
......@@ -62,13 +62,27 @@ jobs:
name: 'Setup Prerequisites'
- uses: ./.github/actions/docker-skiko-run
name: 'Publish Maven Local'
name: 'Publish KMP and AWT Maven Local'
with:
image_name: linux-compat
command: |
./gradlew --no-daemon --stacktrace \
-Pskiko.native.enabled=true \
:skiko:publishToMavenLocal
-Pskiko.awt.enabled=true \
:skiko:publishKotlinMultiplatformPublicationToMavenLocal \
:skiko:publishAwtPublicationToMavenLocal \
:skiko:publishAwtRuntimeElementsPublicationToMavenLocal
- uses: ./.github/actions/docker-skiko-run
name: 'Publish Native Maven Local'
with:
image_name: linux-amd64
command: |
./gradlew --no-daemon --stacktrace \
-Pskiko.native.enabled=true \
-Pskiko.awt.enabled=false \
:skiko:publishLinuxArm64PublicationToMavenLocal \
:skiko:publishLinuxX64PublicationToMavenLocal
- uses: ./.github/actions/docker-skiko-run
name: 'Check AWT Sample'
......
......@@ -169,7 +169,7 @@ jobs:
- uses: ./.github/actions/docker-skiko-run
name: 'Run Linux (x64) Tests'
with:
image_name: linux-compat
image_name: linux-amd64
virtual-display: true
command: |
./gradlew --no-daemon --stacktrace \
......
[versions]
kotlin = "2.0.10"
kotlin = "2.2.20"
kotlinxBrowser = "0.5.0"
coroutines = "1.8.0"
jetbrainsRuntime-api = "1.5.0"
androidGradlePlugin = "7.4.2"
androidGradlePlugin = "8.2.2"
dokka = "1.9.10"
buildHelpers-publishing = "0.1.28"
......@@ -22,6 +24,8 @@ coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", ve
jetbrainsRuntime-api = { module = "org.jetbrains.runtime:jbr-api", version.ref = "jetbrainsRuntime-api" }
kotlinx-browser = { module = "org.jetbrains.kotlinx:kotlinx-browser", version.ref = "kotlinxBrowser" }
android-gradlePlugin = { module = "com.android.tools.build:gradle", version.ref = "androidGradlePlugin" }
dokka-gradlePlugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "dokka" }
gradleDownloadTask-gradlePlugin = { module = "de.undercouch:gradle-download-task", version.ref = "gradleDownloadTask" }
......
......@@ -23,7 +23,7 @@ repositories {
plugins {
id("com.android.application") version "8.9.0"
kotlin("android") version "1.9.21"
kotlin("android") version "2.2.20"
}
val skikoNativeX64 by configurations.creating
......
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.9.21"
kotlin("jvm") version "2.2.20"
application
}
......@@ -96,5 +96,5 @@ tasks.register("runInterop") {
}
tasks.withType<KotlinCompile>().configureEach {
kotlinOptions.freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn"
compilerOptions.freeCompilerArgs.add("-opt-in=kotlin.RequiresOptIn")
}
......@@ -102,7 +102,11 @@ kotlin {
jvm("awt") {
compilations.all {
kotlinOptions.jvmTarget = "11"
compileTaskProvider.configure {
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11)
}
}
}
}
......@@ -310,7 +314,7 @@ if (hostOs == "macos") {
} else {
// Otherwise copy the executable into the Xcode output directory.
tasks.create("packForXCode", Copy::class.java) {
dependsOn(kotlinBinary.linkTask)
dependsOn(kotlinBinary.linkTaskProvider)
println("Packing for XCode: ${kotlinBinary.target}")
......@@ -371,7 +375,5 @@ fun KotlinNativeTarget.configureToLaunchFromXcode() {
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile>().configureEach {
kotlinOptions {
freeCompilerArgs += "-opt-in=kotlinx.cinterop.ExperimentalForeignApi"
}
compilerOptions.freeCompilerArgs.add("-opt-in=kotlinx.cinterop.ExperimentalForeignApi")
}
kotlin.code.style=official
org.gradle.jvmargs=-Xmx3G -XX:MaxMetaspaceSize=512m
kotlin.version=2.0.10
skiko.version=0.9.24
kotlin.version=2.2.20
skiko.version=0.144.0
#skiko.composite.build=1
......@@ -51,7 +51,7 @@ kotlin {
binaries.executable()
}
wasmJs() {
wasmJs {
browser {
commonWebpackConfig {
outputFileName = "webApp.js"
......@@ -61,24 +61,16 @@ kotlin {
}
sourceSets {
val commonMain by getting {
commonMain.dependencies {
implementation(libs.skiko)
}
webMain {
dependencies {
implementation(libs.skiko)
implementation(libs.browser)
}
}
val webMain by creating {
dependsOn(commonMain)
resources.setSrcDirs(resources.srcDirs)
resources.srcDirs(unpackWasmRuntime.map { it.destinationDir })
}
val jsMain by getting {
dependsOn(webMain)
}
val wasmJsMain by getting {
dependsOn(webMain)
}
}
}
\ No newline at end of file
kotlin.code.style=official
kotlin.version=2.0.10
skiko.version=0.9.24
kotlin.version=2.2.20
skiko.version=0.144.0
#skiko.composite.build=1
......@@ -19,8 +19,11 @@ dependencyResolutionManagement {
versionCatalogs {
create("libs") {
version("skiko", providers.gradleProperty("skiko.version").get())
version("kotlinxBrowser", "0.5.0")
library("skiko", "org.jetbrains.skiko", "skiko").versionRef("skiko")
library("skiko-wasm-runtime", "org.jetbrains.skiko", "skiko-js-wasm-runtime").versionRef("skiko")
library("browser", "org.jetbrains.kotlinx", "kotlinx-browser").versionRef("kotlinxBrowser")
}
}
}
......
......@@ -7,7 +7,7 @@ fun main() {
onWasmReady {
val description = "Skiko running with ${getPlatform().name}"
document.title = description
findElementById("description")?.innerHTML = description
document.getElementById("description")?.innerHTML = description
runApp()
}
}
\ No newline at end of file
......@@ -8,7 +8,7 @@ fun main() {
onWasmReady {
val description = "Skiko running with ${getPlatform().name}"
document.title = description
findElementById("description")?.innerHTML = description
document.getElementById("description")?.innerHTML = description
runApp()
}
}
\ No newline at end of file
package org.jetbrains.skiko.sample.js
import kotlinx.browser.document
import org.jetbrains.skia.Canvas
import org.jetbrains.skia.Paint
import org.jetbrains.skia.Rect
import org.jetbrains.skiko.SkiaLayer
import org.jetbrains.skiko.SkiaLayerRenderDelegate
import org.jetbrains.skiko.SkikoRenderDelegate
import org.w3c.dom.Element
import kotlinx.browser.document
private class DemoApp: SkikoRenderDelegate {
private val paint = Paint()
......@@ -25,7 +24,7 @@ private class DemoApp: SkikoRenderDelegate {
internal fun runApp() {
for (index in 1 .. 3) {
val skiaLayer = SkiaLayer()
val canvas = findElementById("c$index")!!
val canvas = document.getElementById("c$index")!!
val app = if (index == 3) {
DemoApp()
} else {
......@@ -35,6 +34,4 @@ internal fun runApp() {
skiaLayer.attachTo(canvas)
skiaLayer.needRedraw()
}
}
fun findElementById(id: String): Element? = document.getElementById(id)
\ No newline at end of file
}
\ No newline at end of file
@file:OptIn(ExperimentalKotlinGradlePluginApi::class)
@file:OptIn(ExperimentalKotlinGradlePluginApi::class, ExperimentalWasmDsl::class)
import com.android.build.gradle.LibraryExtension
import com.android.build.gradle.LibraryPlugin
......@@ -8,10 +8,11 @@ import org.jetbrains.compose.internal.publishing.MavenCentralProperties
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.dsl.KotlinJsCompile
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
import org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
import tasks.configuration.*
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
plugins {
kotlin("multiplatform")
......@@ -58,6 +59,11 @@ repositories {
}
kotlin {
compilerOptions {
languageVersion.set(KotlinVersion.KOTLIN_2_2)
apiVersion.set(KotlinVersion.KOTLIN_2_2)
}
applyHierarchyTemplate(skikoSourceSetHierarchyTemplate)
skikoProjectContext.declareSkiaTasks()
......@@ -96,7 +102,7 @@ kotlin {
skikoProjectContext.declareWasmTasks()
js {
moduleName = "skiko-kjs" // override the name to avoid name collision with a different skiko.js file
outputModuleName.set("skiko-kjs") // override the name to avoid name collision with a different skiko.js file
browser {
testTask {
useKarma {
......@@ -120,7 +126,7 @@ kotlin {
@OptIn(ExperimentalWasmDsl::class)
wasmJs {
moduleName = "skiko-kjs-wasm" // override the name to avoid name collision with a different skiko.js file
outputModuleName.set("skiko-kjs-wasm") // override the name to avoid name collision with a different skiko.js file
browser {
testTask {
useKarma {
......@@ -183,6 +189,10 @@ kotlin {
implementation(libs.coroutines.core.jvm)
}
skikoProjectContext.webMainSourceSet?.dependencies {
implementation(libs.kotlinx.browser)
}
skikoProjectContext.awtMainSourceSet?.dependencies {
implementation(libs.jetbrainsRuntime.api)
}
......@@ -391,8 +401,6 @@ tasks.register("printSkiaVersion") {
}
tasks.withType<KotlinNativeCompile>().configureEach {
// https://youtrack.jetbrains.com/issue/KT-56583
compilerOptions.freeCompilerArgs.add("-XXLanguage:+ImplicitSignedToUnsignedIntegerConversion")
compilerOptions.freeCompilerArgs.add("-opt-in=kotlinx.cinterop.ExperimentalForeignApi")
}
......
kotlin.version=2.0.10
kotlin.version=2.2.20
......@@ -3,13 +3,6 @@ import org.gradle.api.Project
val Project.wasmImports
get() = layout.buildDirectory.dir("imports").get().asFile
val Project.setupMjs
get() = wasmImports.resolve("setup.mjs")
val Project.setupReexportMjs
get() = wasmImports.resolve("js-reexport-symbols.mjs")
val Project.skikoTestMjs
get() = wasmImports.resolve("skiko-test.mjs")
fun Project.wasmImport(name: String) = wasmImports.resolve(name)
const val IMPORT_GENERATOR = "import-generator"
\ No newline at end of file
......@@ -13,6 +13,8 @@ val SkikoProjectContext.awtTestSourceSet get() = if (project.supportAwt) kotlin.
val SkikoProjectContext.androidMainSourceSet get() = if (project.supportAndroid) kotlin.sourceSets.getByName("androidMain") else null
val SkikoProjectContext.webMainSourceSet get() = if (project.supportWeb) kotlin.sourceSets.getByName("webMain") else null
val SkikoProjectContext.webTestSourceSet get() = if (project.supportWeb) kotlin.sourceSets.getByName("webTest") else null
val SkikoProjectContext.wasmJsTest get() = if (project.supportWeb) kotlin.sourceSets.getByName("wasmJsTest") else null
......
......@@ -182,7 +182,7 @@ fun configureCinterop(
}
target.compilations.getByName("main") {
cinterops.create(cinteropName).apply {
defFileProperty.set(writeCInteropDef.map { it.outputFile.get().asFile })
definitionFile.set(writeCInteropDef.flatMap { it.outputFile })
}
}
}
......@@ -294,9 +294,13 @@ fun SkikoProjectContext.configureNativeTarget(os: OS, arch: Arch, target: Kotlin
target.binaries.all {
freeCompilerArgs += allLibraries.map { listOf("-include-binary", it) }.flatten() + linkerFlags
}
target.compilations.all {
kotlinOptions {
freeCompilerArgs += allLibraries.map { listOf("-include-binary", it) }.flatten() + linkerFlags
compilerOptions.configure {
freeCompilerArgs.addAll(
allLibraries.flatMap { listOf("-include-binary", it) } + linkerFlags
)
}
}
......@@ -343,7 +347,7 @@ fun KotlinMultiplatformExtension.configureIOSTestsWithMetal(project: Project) {
if (targets.names.contains(target)) {
val testBinary = targets.getByName<KotlinNativeTarget>(target).binaries.getTest("DEBUG")
project.tasks.register(target + "TestWithMetal") {
dependsOn(testBinary.linkTask)
dependsOn(testBinary.linkTaskProvider)
doLast {
val simulatorIdPropertyKey = "skiko.iosSimulatorUUID"
val simulatorId = project.findProperty(simulatorIdPropertyKey)?.toString()
......
@file:OptIn(ExperimentalWasmDsl::class)
package tasks.configuration
import Arch
......@@ -19,16 +17,22 @@ import org.gradle.kotlin.dsl.getting
import org.gradle.kotlin.dsl.provideDelegate
import org.gradle.kotlin.dsl.registering
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsTargetDsl
import projectDirs
import registerOrGetSkiaDirProvider
import setupMjs
import setupReexportMjs
import skikoTestMjs
import supportWeb
import wasmImport
import java.io.File
private val Project.setupMjs
get() = wasmImport("setup.mjs")
private val Project.setupReexportMjs
get() = wasmImport("js-reexport-symbols.mjs")
private val Project.skikoTestMjs
get() = wasmImport("skiko-test.mjs")
fun SkikoProjectContext.declareWasmTasks() {
if (!project.supportWeb) {
return
......
......@@ -26,9 +26,6 @@ internal class ImportGeneratorExtension(
importGenerator.getExportSymbols().forEach { symbolName ->
writer.appendLine("export let ${symbolName} = (...a) => ($symbolName = loadedWasm._[\"${symbolName}\"])(...a)")
if (reexportPath == null) {
writer.appendLine("window['${symbolName}'] = (...a) => loadedWasm._[\"${symbolName}\"](...a)")
}
}
}
......
......@@ -20,4 +20,4 @@ class ImportGeneratorRegistrar : CompilerPluginRegistrar() {
)
)
}
}
\ No newline at end of file
}
package org.jetbrains.skiko
import org.jetbrains.kotlin.DeprecatedForRemovalCompilerApi
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrFunction
......@@ -7,6 +8,7 @@ import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.fromSymbolOwner
import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.defaultType
......@@ -25,12 +27,12 @@ internal class ImportGeneratorTransformer(private val pluginContext: IrPluginCon
@Suppress("UNCHECKED_CAST")
private fun IrConstructorCall.getStringValue(value: String): String =
(getValueArgument(Name.identifier(value)) as IrConst<String>).value
(getValueArgument(Name.identifier(value)) as IrConst).value as String
@OptIn(UnsafeDuringIrConstructionAPI::class)
@OptIn(UnsafeDuringIrConstructionAPI::class, DeprecatedForRemovalCompilerApi::class)
private fun IrFunction.addWasmImportAnnotation(name: String) {
val annotationClass = pluginContext.referenceClass(
ClassId.fromString("kotlin/wasm/WasmImport") // Replace with your fully qualified annotation name
ClassId.fromString("kotlin/wasm/WasmImport")
) ?: return
val ctor = annotationClass.owner.constructors.first()
......@@ -61,14 +63,40 @@ internal class ImportGeneratorTransformer(private val pluginContext: IrPluginCon
annotations += annotationCall
}
@OptIn(UnsafeDuringIrConstructionAPI::class, DeprecatedForRemovalCompilerApi::class)
private fun IrFunction.addJsNameAnnotation(name: String) {
val annotationClass = pluginContext.referenceClass(
ClassId.fromString("kotlin/js/JsName")
) ?: return
val ctor = annotationClass.owner.constructors.first()
val annotationCall = IrConstructorCallImpl.fromSymbolOwner(
startOffset = startOffset,
endOffset = endOffset,
type = annotationClass.owner.defaultType,
constructorSymbol = ctor.symbol,
)
annotationCall.putValueArgument(0, IrConstImpl.string(
startOffset,
endOffset,
pluginContext.irBuiltIns.stringType,
name
))
annotations += annotationCall
}
override fun visitFunction(declaration: IrFunction): IrStatement {
return super.visitFunction(declaration).apply {
if (this !is IrFunction) return@apply
val jsNameAnnotation = getAnnotation(FqName("kotlin.js.JsName"))
val webImportAnnotation = getAnnotation(FqName("org.jetbrains.skiko.WebImport"))
?: return@apply
val name = jsNameAnnotation.getStringValue("name")
val name = webImportAnnotation.getStringValue("name")
addJsNameAnnotation(name)
addWasmImportAnnotation(name)
exportSymbols.add(name)
......
......@@ -46,14 +46,14 @@ class CanvasTest {
// Hint: use surface.makeImageSnapshot().printBitmap() to print image as kotlin array
val expected = imageFromIntArray(intArrayOf(
0x00000000.toInt(), 0xffbf2020.toInt(), 0xff9f2040.toInt(), 0xff802060.toInt(), 0xff602080.toInt(), 0xff40209f.toInt(), 0xff2020bf.toInt(), 0xff0020df.toInt(),
0x00000000.toInt(), 0x00000000.toInt(), 0xff806020.toInt(), 0xff606040.toInt(), 0xff406060.toInt(), 0xff206080.toInt(), 0xff00609f.toInt(), 0x00000000.toInt(),
0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0xff409f20.toInt(), 0xff209f40.toInt(), 0xff009f60.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0xff00df20.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0xff20ffdf.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0xff60bfdf.toInt(), 0xff60dfbf.toInt(), 0xff60ff9f.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0x00000000.toInt(), 0x00000000.toInt(), 0xff9f80df.toInt(), 0xff9f9fbf.toInt(), 0xff9fbf9f.toInt(), 0xff9fdf80.toInt(), 0xff9fff60.toInt(), 0x00000000.toInt(),
0x00000000.toInt(), 0xffdf40df.toInt(), 0xffdf60bf.toInt(), 0xffdf809f.toInt(), 0xffdf9f80.toInt(), 0xffdfbf60.toInt(), 0xffdfdf40.toInt(), 0xffdfff20.toInt(),
0x00000000, 0xffbf2020.toInt(), 0xff9f2040.toInt(), 0xff802060.toInt(), 0xff602080.toInt(), 0xff40209f.toInt(), 0xff2020bf.toInt(), 0xff0020df.toInt(),
0x00000000, 0x00000000, 0xff806020.toInt(), 0xff606040.toInt(), 0xff406060.toInt(), 0xff206080.toInt(), 0xff00609f.toInt(), 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0xff409f20.toInt(), 0xff209f40.toInt(), 0xff009f60.toInt(), 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff00df20.toInt(), 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff20ffdf.toInt(), 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0xff60bfdf.toInt(), 0xff60dfbf.toInt(), 0xff60ff9f.toInt(), 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0xff9f80df.toInt(), 0xff9f9fbf.toInt(), 0xff9fbf9f.toInt(), 0xff9fdf80.toInt(), 0xff9fff60.toInt(), 0x00000000,
0x00000000, 0xffdf40df.toInt(), 0xffdf60bf.toInt(), 0xffdf809f.toInt(), 0xffdf9f80.toInt(), 0xffdfbf60.toInt(), 0xffdfdf40.toInt(), 0xffdfff20.toInt(),
), surface.width)
assertContentSame(expected, surface.makeImageSnapshot(), 0.25)
......@@ -79,14 +79,14 @@ class CanvasTest {
)
val expected = imageFromIntArray(intArrayOf(
0xffff0000.toInt(), 0xffff0000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0xffff0000.toInt(), 0xffff0000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0xffff0000.toInt(), 0xffff0000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0x00000000.toInt(), 0x00000000.toInt(), 0xffff0000.toInt(), 0xffff0000.toInt(), 0xffff0000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0x00000000.toInt(), 0xffff0000.toInt(), 0xffff0000.toInt(), 0xffff0000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0x00000000.toInt(), 0xffff0000.toInt(), 0xffff0000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0xffff0000.toInt(),
0xffff0000.toInt(), 0xffff0000.toInt(), 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0xffff0000.toInt(), 0xffff0000.toInt(), 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0xffff0000.toInt(), 0xffff0000.toInt(), 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0xffff0000.toInt(), 0xffff0000.toInt(), 0xffff0000.toInt(), 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0xffff0000.toInt(), 0xffff0000.toInt(), 0xffff0000.toInt(), 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0xffff0000.toInt(), 0xffff0000.toInt(), 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffff0000.toInt(),
), surface.width)
assertContentSame(expected, surface.makeImageSnapshot(), 0.25)
......@@ -176,14 +176,14 @@ class CanvasTest {
val expected = imageFromIntArray(
pixArray = intArrayOf(
0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0xffcb0634.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0x00000000.toInt(), 0x00000000.toInt(), 0xffb63b49.toInt(), 0xff9b3064.toInt(), 0xff762b8a.toInt(), 0xff4b1cb4.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0x00000000.toInt(), 0x00000000.toInt(), 0xff8d6e73.toInt(), 0xff866479.toInt(), 0xff7a6386.toInt(), 0xff675698.toInt(), 0xff3632c9.toInt(), 0x00000000.toInt(),
0x00000000.toInt(), 0xff36cdc9.toInt(), 0xff67a998.toInt(), 0xff7a9c86.toInt(), 0xff869b79.toInt(), 0xff8d9173.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0x00000000.toInt(), 0x00000000.toInt(), 0xff4be3b4.toInt(), 0xff76d48a.toInt(), 0xff9bcf64.toInt(), 0xffb6c449.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0xffcbf934.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0xffcb0634.toInt(), 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0xffb63b49.toInt(), 0xff9b3064.toInt(), 0xff762b8a.toInt(), 0xff4b1cb4.toInt(), 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0xff8d6e73.toInt(), 0xff866479.toInt(), 0xff7a6386.toInt(), 0xff675698.toInt(), 0xff3632c9.toInt(), 0x00000000,
0x00000000, 0xff36cdc9.toInt(), 0xff67a998.toInt(), 0xff7a9c86.toInt(), 0xff869b79.toInt(), 0xff8d9173.toInt(), 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0xff4be3b4.toInt(), 0xff76d48a.toInt(), 0xff9bcf64.toInt(), 0xffb6c449.toInt(), 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffcbf934.toInt(), 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
),
imageWidth = 8
......
......@@ -5,14 +5,14 @@ import org.jetbrains.skia.util.imageFromIntArray
@Suppress("RemoveRedundantCallsOfConversionMethods")
val PIXELS_COLORS_8X8 by lazy { intArrayOf(
0xffff0000.toInt(), 0xffff0000.toInt(), 0xff00ff00.toInt(), 0xff00ff00.toInt(), 0xff0000ff.toInt(), 0xff0000ff.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0xffff0000.toInt(), 0xffff0000.toInt(), 0xff00ff00.toInt(), 0xff00ff00.toInt(), 0xff0000ff.toInt(), 0xff0000ff.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0xff00ffff.toInt(), 0xff00ffff.toInt(), 0xffff00ff.toInt(), 0xffff00ff.toInt(), 0xffffff00.toInt(), 0xffffff00.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0xff00ffff.toInt(), 0xff00ffff.toInt(), 0xffff00ff.toInt(), 0xffff00ff.toInt(), 0xffffff00.toInt(), 0xffffff00.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0xffffffff.toInt(), 0xffffffff.toInt(), 0xff000000.toInt(), 0xff000000.toInt(), 0x80000000.toInt(), 0x80000000.toInt(), 0x03000000.toInt(), 0x00000000.toInt(),
0xffffffff.toInt(), 0xffffffff.toInt(), 0xff000000.toInt(), 0xff000000.toInt(), 0x80000000.toInt(), 0x80000000.toInt(), 0x03000000.toInt(), 0x00000000.toInt(),
0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(), 0x00000000.toInt(),
0xffff0000.toInt(), 0xffff0000.toInt(), 0xff00ff00.toInt(), 0xff00ff00.toInt(), 0xff0000ff.toInt(), 0xff0000ff.toInt(), 0x00000000, 0x00000000,
0xffff0000.toInt(), 0xffff0000.toInt(), 0xff00ff00.toInt(), 0xff00ff00.toInt(), 0xff0000ff.toInt(), 0xff0000ff.toInt(), 0x00000000, 0x00000000,
0xff00ffff.toInt(), 0xff00ffff.toInt(), 0xffff00ff.toInt(), 0xffff00ff.toInt(), 0xffffff00.toInt(), 0xffffff00.toInt(), 0x00000000, 0x00000000,
0xff00ffff.toInt(), 0xff00ffff.toInt(), 0xffff00ff.toInt(), 0xffff00ff.toInt(), 0xffffff00.toInt(), 0xffffff00.toInt(), 0x00000000, 0x00000000,
0xffffffff.toInt(), 0xffffffff.toInt(), 0xff000000.toInt(), 0xff000000.toInt(), 0x80000000.toInt(), 0x80000000.toInt(), 0x03000000, 0x00000000,
0xffffffff.toInt(), 0xffffffff.toInt(), 0xff000000.toInt(), 0xff000000.toInt(), 0x80000000.toInt(), 0x80000000.toInt(), 0x03000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
) }
val IMAGE_COLORS_8X8 by lazy { imageFromIntArray(PIXELS_COLORS_8X8, 8) }
......
......@@ -20,7 +20,7 @@ object SkikoDispatchers {
val Main: CoroutineDispatcher = NsQueueDispatcher(dispatch_get_main_queue())
val IO: CoroutineDispatcher = NsQueueDispatcher(
dispatch_get_global_queue(
QOS_CLASS_BACKGROUND.toLong(), 0)
QOS_CLASS_BACKGROUND.toLong(), 0UL)
)
}
......@@ -91,4 +91,3 @@ private class Timer : DisposableHandle {
CFRelease(timer)
}
}
......@@ -22,7 +22,7 @@ class BasicIosTests {
val f = fopen(path, "r") ?: throw Error("cannot open $path: ${strerror(errno)?.toKString()}")
val buf = ByteArray(200)
buf.usePinned {
val rv = fread(it.addressOf(0), 1, buf.size.toULong(), f)
val rv = fread(it.addressOf(0), 1UL, buf.size.toULong(), f)
assertTrue { rv != 0UL }
}
assertEquals("This is test data.\n", buf.toKString())
......
package org.jetbrains.skia
actual typealias ExternalSymbolName = kotlin.js.JsName
\ No newline at end of file
import org.jetbrains.skiko.WebImport
actual typealias ExternalSymbolName = WebImport
\ No newline at end of file
package org.jetbrains.skia.webext
import kotlinx.coroutines.await
import org.jetbrains.skiko.wasm.awaitSkiko
internal actual suspend fun getSkikoWasm(): SkikoWasm {
return awaitSkiko.await().unsafeCast<SkikoWasm>()
}
internal actual fun skikoArrayBuffer(skikoWasm: SkikoWasm): WebArrayBufferExt =
js("skikoWasm.wasmExports.memory.buffer")
internal actual fun copyBuffer(
src: WebArrayBufferExt,
dst: WebArrayBufferExt,
size: Int,
dstOffset: Int
) {
js("""
var dstView = new Uint8Array(dst);
var srcView = new Uint8Array(src);
dstView.set(srcView, dstOffset);
""")
}
\ No newline at end of file
package org.jetbrains.skiko
internal actual fun getNavigatorInfo(): String =
js("navigator.userAgentData ? navigator.userAgentData.platform : navigator.platform") as String
internal actual external val GL: GLInterface
package org.jetbrains.skiko
import kotlinx.browser.window
import kotlinx.coroutines.await
import org.khronos.webgl.Int8Array
actual suspend fun loadBytesFromPath(path: String): ByteArray {
val arrayBuffer = window.fetch(path)
.await()
.arrayBuffer()
.await()
val byteArray = Int8Array(arrayBuffer)
return byteArray.unsafeCast<ByteArray>()
}
internal actual fun Int8Array.asByteArray(): ByteArray = this.unsafeCast<ByteArray>()
......@@ -2,7 +2,7 @@ package org.jetbrains.skiko.wasm
import org.jetbrains.skia.impl.NativePointer
import org.jetbrains.skiko.GL
import org.jetbrains.skiko.w3c.HTMLCanvasElement
import org.w3c.dom.HTMLCanvasElement
import kotlin.js.*
/**
......
......@@ -5,4 +5,4 @@ package org.jetbrains.skiko.wasm
import kotlin.js.Promise
internal external val awaitSkiko: Promise<Any>
internal actual external val awaitSkiko: Promise<JsAny>
......@@ -5,7 +5,6 @@ import kotlinx.coroutines.await
import kotlinx.coroutines.promise
import org.jetbrains.skiko.wasm.awaitSkiko
actual typealias TestReturnType = Any
/**
* Awaits for `wasmSetup` and then runs the [block] in a coroutine.
*/
......
......@@ -35,7 +35,7 @@ actual suspend fun loadBytesFromPath(path: String): ByteArray {
val bytes = ByteArray(size.toInt())
val result = bytes.usePinned {
fread(it.addressOf(0), 1, size.toULong(), file)
fread(it.addressOf(0), 1UL, size.toULong(), file)
}
fclose(file)
......
package org.jetbrains.skia
actual typealias ExternalSymbolName = kotlin.js.JsName
\ No newline at end of file
import org.jetbrains.skiko.WebImport
actual typealias ExternalSymbolName = WebImport
\ No newline at end of file
package org.jetbrains.skia.webext
import kotlinx.coroutines.await
import org.jetbrains.skiko.wasm.awaitSkiko
internal actual suspend fun getSkikoWasm(): SkikoWasm {
return awaitSkiko.await()
}
internal actual fun skikoArrayBuffer(skikoWasm: SkikoWasm): WebArrayBufferExt =
js("skikoWasm.wasmExports.memory.buffer")
internal actual fun copyBuffer(
src: WebArrayBufferExt,
dst: WebArrayBufferExt,
size: Int,
dstOffset: Int
) {
js("""
var dstView = new Uint8Array(dst);
var srcView = new Uint8Array(src);
dstView.set(srcView, dstOffset);
""")
}
\ No newline at end of file
package org.jetbrains.skiko
import org.w3c.dom.events.UIEvent
internal actual fun getNavigatorInfo(): String =
js("navigator.userAgentData ? navigator.userAgentData.platform : navigator.platform")
package org.jetbrains.skiko
import org.khronos.webgl.Int8Array
import org.khronos.webgl.get
internal actual fun Int8Array.asByteArray(): ByteArray = ByteArray(length) { index -> this[index] }
\ No newline at end of file
package org.jetbrains.skiko
import kotlin.js.*
import kotlinx.coroutines.asDeferred
@JsFun("(path) => window.fetch(path).then((r) => r.arrayBuffer()).then((b) => new Int8Array(b))")
private external fun loadResource(path: String): Promise<JsAny>
@JsFun("(array) => array.length")
private external fun arrayLength(array: JsAny): Int
@JsFun("(array, index) => array[index]")
private external fun arrayGet(array: JsAny, index: Int): Byte
actual suspend fun loadBytesFromPath(path: String): ByteArray {
val resourceArray = loadResource(path).asDeferred<JsAny>().await()
return ByteArray(arrayLength(resourceArray)) {
arrayGet(resourceArray, it)
}
}
package org.jetbrains.skiko.wasm
import kotlinx.coroutines.await
import org.jetbrains.skia.impl.NativePointer
import org.jetbrains.skiko.GL
import org.jetbrains.skiko.w3c.HTMLCanvasElement
import org.khronos.webgl.ArrayBuffer
import org.w3c.dom.HTMLCanvasElement
@JsFun(
"""() => {
......
......@@ -3,4 +3,4 @@ package org.jetbrains.skiko.wasm
import kotlin.js.Promise
internal external val awaitSkiko: Promise<JsAny?>
internal actual external val awaitSkiko: Promise<JsAny>
package org.jetbrains.skiko.tests
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.await
import kotlinx.coroutines.promise
import org.jetbrains.skiko.wasm.awaitSkiko
actual annotation class SkipJsTarget
......@@ -9,13 +11,11 @@ actual typealias SkipWasmTarget = kotlin.test.Ignore
@JsFun("() => ''")
private external fun jsRef(): JsAny
actual typealias TestReturnType = Any
/**
* Runs the [block] in a coroutine.
*/
actual fun runTest(block: suspend () -> Unit): TestReturnType = MainScope().promise {
awaitSkiko.await<Any>()
block()
jsRef()
}
package org.jetbrains.skia
import org.jetbrains.skiko.w3c.window
import kotlinx.browser.window
internal actual fun <R> commonSynchronized(lock: Any, block: () -> R) {
block()
......@@ -33,4 +33,4 @@ val LANG: String by lazy {
actual fun defaultLanguageTag(): String = LANG
actual fun compilePattern(regex: String): Pattern = Pattern(regex)
\ No newline at end of file
actual fun compilePattern(regex: String): Pattern = Pattern(regex)
......@@ -6,30 +6,34 @@ import org.jetbrains.skia.impl.Native
import org.jetbrains.skia.impl.NativePointer
import org.jetbrains.skia.impl._malloc
import org.jetbrains.skiko.ExperimentalSkikoApi
import org.jetbrains.skiko.await
import org.jetbrains.skiko.wasm.awaitSkiko
import org.khronos.webgl.ArrayBuffer
import kotlin.js.JsAny
import kotlin.js.js
internal expect fun skikoArrayBuffer(skikoWasm: SkikoWasm): WebArrayBufferExt
/**
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer
*/
@ExperimentalSkikoApi
external interface WebArrayBufferExt {
val byteLength: Int
operator fun set(ix: Int, value: Byte)
}
internal external interface SkikoWasm
internal fun skikoArrayBuffer(skikoWasm: JsAny): ArrayBuffer =
js("skikoWasm.wasmExports.memory.buffer")
internal suspend fun copyBufferToSkiko(
src: WebArrayBufferExt
src: ArrayBuffer
): NativePointer {
val ptr = _malloc(src.byteLength)
if (ptr != Native.NullPointer) {
val skikoArrayBuffer = skikoArrayBuffer(getSkikoWasm())
copyBuffer(src, skikoArrayBuffer, src.byteLength, ptr)
val skikoArrayBuffer = skikoArrayBuffer(awaitSkiko.await())
copyBuffer(src, skikoArrayBuffer, ptr)
}
return ptr
}
internal expect suspend fun getSkikoWasm(): SkikoWasm
internal expect fun copyBuffer(src: WebArrayBufferExt, dst: WebArrayBufferExt, size: Int, dstOffset: Int)
\ No newline at end of file
internal fun copyBuffer(
src: ArrayBuffer,
dst: ArrayBuffer,
dstOffset: Int
) {
js("""
var dstView = new Uint8Array(dst);
var srcView = new Uint8Array(src);
dstView.set(srcView, dstOffset);
""")
}
\ No newline at end of file
......@@ -7,11 +7,12 @@ import org.jetbrains.skia.impl.Native
import org.jetbrains.skia.impl.NativePointer
import org.jetbrains.skia.impl.getPtr
import org.jetbrains.skiko.ExperimentalSkikoApi
import org.khronos.webgl.ArrayBuffer
@ExperimentalSkikoApi
suspend fun Bitmap.installPixelsFromArrayBuffer(
info: ImageInfo,
pixelsArrayBuffer: WebArrayBufferExt,
pixelsArrayBuffer: ArrayBuffer,
rowBytes: Int
): Boolean {
val pixelsPtr = copyBufferToSkiko(pixelsArrayBuffer)
......
package org.jetbrains.skiko
import org.jetbrains.skiko.w3c.window
import kotlinx.browser.window
import org.w3c.dom.HTMLElement
internal actual inline fun <R> maybeSynchronized(lock: Any, block: () -> R): R =
block()
......@@ -13,4 +14,6 @@ internal actual fun loadOpenGLLibrary() {
internal actual fun loadAngleLibrary() {
// Nothing to do here
}
\ No newline at end of file
}
annotation class WebImport(val name : String)
package org.jetbrains.skiko
import kotlinx.browser.window
import org.jetbrains.skia.*
import org.jetbrains.skia.impl.NativePointer
import org.jetbrains.skiko.w3c.HTMLCanvasElement
import org.jetbrains.skiko.w3c.window
import org.jetbrains.skiko.wasm.ContextAttributes
import org.w3c.dom.HTMLCanvasElement
/**
* CanvasRenderer takes an [HTMLCanvasElement] instance and initializes
......
package org.jetbrains.skiko
import org.jetbrains.skiko.w3c.window
import kotlinx.browser.window
import kotlin.js.js
actual val hostOs: OS = detectHostOs()
......@@ -22,7 +23,9 @@ actual val kotlinBackend: KotlinBackend
* See https://developer.mozilla.org/en-US/docs/Web/API/NavigatorUAData/platform - new API,
* but not supported in all browsers
*/
internal expect fun getNavigatorInfo(): String
internal fun getNavigatorInfo(): String =
js("navigator.userAgentData ? navigator.userAgentData.platform : navigator.platform")
/**
* In a browser, user platform can be obtained from different places:
......
package org.jetbrains.skiko
import kotlinx.browser.window
import org.khronos.webgl.ArrayBuffer
import org.khronos.webgl.Int8Array
import org.w3c.fetch.RequestInit
import org.w3c.fetch.Response
import kotlin.js.ExperimentalWasmJsInterop
import kotlin.js.js
internal expect fun Int8Array.asByteArray(): ByteArray
// Without request init passed explicitly, js target fails
// this looks like a bug in kotlinx.browser definitions
// TODO: to discuss with the Kotlin team
private val defaultFetchInit: RequestInit = js("{}")
@OptIn(ExperimentalWasmJsInterop::class)
actual suspend fun loadBytesFromPath(path: String): ByteArray {
val arrayBuffer = window.fetch(path, defaultFetchInit)
.await<Response>()
.arrayBuffer()
.await<ArrayBuffer>()
return Int8Array(arrayBuffer).asByteArray()
}
\ No newline at end of file
package org.jetbrains.skiko
import kotlinx.browser.window
import org.jetbrains.skia.Canvas
import org.jetbrains.skia.Color
import org.jetbrains.skia.PixelGeometry
import org.jetbrains.skiko.w3c.HTMLCanvasElement
import org.jetbrains.skiko.w3c.window
import org.jetbrains.skiko.wasm.createWebGLContext
import org.w3c.dom.HTMLCanvasElement
/**
* Provides a way to render the content and to receive the input events.
......
package org.jetbrains.skiko
import kotlinx.coroutines.CancellableContinuation
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.js.ExperimentalWasmJsInterop
import kotlin.js.JsAny
import kotlin.js.Promise
import kotlin.js.js
private fun jsThrow(e: JsAny) {
js("throw e;")
}
@JsFun("function (f) { try { f(); } catch (e) { return e;}; return null; }")
private external fun jsCatch(f: () -> Unit): JsAny?
/**
* For a Dynamic value caught in JS, returns the corresponding [Throwable]
* if it was thrown from Kotlin, or null otherwise.
*/
@ExperimentalWasmJsInterop
private fun JsAny.toThrowableOrNull(): Throwable? {
val thisAny: Any = this
if (thisAny is Throwable) return thisAny
var result: Throwable? = null
jsCatch {
try {
jsThrow(this)
} catch (e: Throwable) {
result = e
}
}
return result
}
@Suppress("UNCHECKED_CAST")
@OptIn(ExperimentalWasmJsInterop::class)
internal suspend fun <T> Promise<JsAny?>.await(): T = suspendCancellableCoroutine { cont: CancellableContinuation<T> ->
this@await.then(
onFulfilled = { cont.resume(it as T); null },
onRejected = { cont.resumeWithException(it.toThrowableOrNull() ?: error("Unexpected non-Kotlin exception $it")); null }
)
}
\ No newline at end of file
package org.jetbrains.skiko.w3c
/**
* The purpose of this file is to facilitate shared W3C type declarations
* for use in both kotlin/js and kotlin/wasm code.
* Given that the Kotlin standard library does not provide common (shared between kotlin/js and kotlin/wasm) W3C API,
* this file serves to fill that void with custom partial declarations.
*
* These declarations do not cover all attributes and methods of the respective W3C types,
* but only those needed by our implementations.
*/
@Suppress("ClassName")
internal external object window {
val devicePixelRatio: Double
val navigator: Navigator
val performance: Performance
fun requestAnimationFrame(block: (Double) -> Unit)
fun open(url: String?, target: String?)
}
internal external interface Performance {
fun now(): Double
}
internal external interface Navigator {
val language: String
val clipboard: Clipboard
val userAgent: String
}
internal external interface Clipboard {
fun writeText(text: String)
}
internal abstract external class HTMLCanvasElement {
internal var width: Int
internal var height: Int
internal val style: CSSStyleDeclaration
}
internal abstract external class CSSStyleDeclaration {
var width: String
var height: String
}
\ No newline at end of file
package org.jetbrains.skiko.wasm
import org.jetbrains.skia.impl.NativePointer
import org.jetbrains.skiko.w3c.HTMLCanvasElement
import org.w3c.dom.HTMLCanvasElement
import kotlin.js.JsAny
import kotlin.js.Promise
internal external interface ContextAttributes {
val alpha: Int?
......@@ -20,4 +22,6 @@ internal external interface ContextAttributes {
internal expect fun createWebGLContext(canvas: HTMLCanvasElement, attr: ContextAttributes? = null): NativePointer
internal expect fun onWasmReady(onReady: () -> Unit)
\ No newline at end of file
internal expect fun onWasmReady(onReady: () -> Unit)
internal expect val awaitSkiko: Promise<JsAny>
\ No newline at end of file
// This file is merged with skiko.mjs by emcc
const loadedWasm = {
export const loadedWasm = {
_: {}
}
......
......@@ -6,6 +6,13 @@ const loadedWasm = {
awaitSkiko.then((module) => {
loadedWasm._ = module.wasmExports;
for (let exportName of Object.keys(module.wasmExports)) {
if (exportName.startsWith("org_jetbrains_skiko_tests_")) {
window[exportName] = module.wasmExports[exportName]
}
}
return module
});
......
......@@ -8,6 +8,7 @@ import org.jetbrains.skia.impl.NativePointer
import org.jetbrains.skia.impl._free
import org.jetbrains.skia.impl.skia_memGetByte
import org.jetbrains.skiko.tests.runTest
import org.khronos.webgl.Int8Array
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.time.measureTimedValue
......@@ -17,10 +18,10 @@ class WebExtTest {
@Test
fun canCopyArrayBufferToSkikoMemory() = runTest {
val bytes = ByteArray(16_000_000) { (it and 0xFF).toByte() }
val ba = createInt8ArrayToCopy(bytes.size)
val ba = Int8Array(bytes.size)
for (i in bytes.indices) ba[i] = bytes[i]
val ptr = measureTimedValue<NativePointer> { copyBufferToSkiko(ba.buffer) }
val ptr = measureTimedValue { copyBufferToSkiko(ba.buffer) }
println("copyBufferToSkiko took ${ptr.duration}\n")
// Sanity check
......@@ -50,7 +51,7 @@ class WebExtTest {
}
}
val ba = createInt8ArrayToCopy(bytes.size)
val ba = Int8Array(bytes.size)
for (i in bytes.indices) ba[i] = bytes[i]
val info = ImageInfo(width, height, ColorType.RGBA_8888, ColorAlphaType.PREMUL)
......@@ -80,17 +81,10 @@ class WebExtTest {
}
}
private fun createInt8ArrayToCopy(length: Int): Int8ArrayInternal =
js("new Int8Array(length)")
private external interface Int8ArrayInternal {
val buffer: WebArrayBufferExt
}
private operator fun Int8ArrayInternal.set(index: Int, value: Byte) {
private operator fun Int8Array.set(index: Int, value: Byte) {
int8ArraySet(this, index, value)
}
private fun int8ArraySet(arrayInternal: Int8ArrayInternal, index: Int, value: Byte) {
private fun int8ArraySet(arrayInternal: Int8Array, index: Int, value: Byte) {
js("arrayInternal[index] = value;")
}
\ No newline at end of file
......@@ -14,4 +14,6 @@ actual annotation class SkipNativeTarget
actual fun makeFromFileName(path: String?): Data = Data(0)
actual val isDebugModeOnJvm: Boolean = false
\ No newline at end of file
actual val isDebugModeOnJvm: Boolean = false
actual typealias TestReturnType = Any
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