Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
skiko
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
liuqiang
skiko
Commits
07f4a8ad
Unverified
Commit
07f4a8ad
authored
Aug 03, 2020
by
Nikolay Igotti
Committed by
GitHub
Aug 03, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Direct AWT rendering. (#5)
parent
81e843ff
Changes
28
Show whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
1566 additions
and
22 deletions
+1566
-22
.gitignore
.gitignore
+5
-0
build.gradle
samples/SkijaInjectSample/build.gradle
+32
-0
JetBrainsMono-Regular.ttf
samples/SkijaInjectSample/fonts/JetBrainsMono-Regular.ttf
+0
-0
gradle-wrapper.jar
samples/SkijaInjectSample/gradle/wrapper/gradle-wrapper.jar
+0
-0
gradle-wrapper.properties
...kijaInjectSample/gradle/wrapper/gradle-wrapper.properties
+5
-0
gradlew
samples/SkijaInjectSample/gradlew
+185
-0
gradlew.bat
samples/SkijaInjectSample/gradlew.bat
+104
-0
settings.gradle
samples/SkijaInjectSample/settings.gradle
+20
-0
App.kt
...kijaInjectSample/src/main/kotlin/SkijaInjectSample/App.kt
+123
-0
AppTest.kt
...InjectSample/src/test/kotlin/SkijaInjectSample/AppTest.kt
+14
-0
.gitignore
skiko/.gitignore
+1
-0
build.gradle.kts
skiko/build.gradle.kts
+45
-7
gradle.properties
skiko/gradle.properties
+2
-0
Window.cc
skiko/src/jvmMain/cpp/Window.cc
+0
-6
jawt.cc
skiko/src/jvmMain/cpp/common/jawt.cc
+56
-0
openglapi.cc
skiko/src/jvmMain/cpp/common/openglapi.cc
+44
-0
drawlayer.cc
skiko/src/jvmMain/cpp/linux/drawlayer.cc
+209
-0
drawlayer.cc
skiko/src/jvmMain/cpp/windows/drawlayer.cc
+222
-0
Drawable.kt
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/Drawable.kt
+8
-0
Engine.kt
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/Engine.kt
+49
-0
GraphicsApi.kt
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/GraphicsApi.kt
+5
-0
HardwareLayer.kt
...o/src/jvmMain/kotlin/org/jetbrains/skiko/HardwareLayer.kt
+17
-0
Library.kt
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/Library.kt
+2
-2
Main.kt
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/Main.kt
+11
-1
OSType.kt
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/OSType.kt
+40
-0
OpenGLApi.kt
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/OpenGLApi.kt
+33
-0
SkiaWindow.kt
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/SkiaWindow.kt
+103
-6
drawlayer.m
skiko/src/jvmMain/objectiveC/macos/drawlayer.m
+231
-0
No files found.
.gitignore
View file @
07f4a8ad
skija
skija
build
.gradle
local.properties
.DS_Store
run.sh
.idea
.idea
\ No newline at end of file
samples/SkijaInjectSample/build.gradle
0 → 100644
View file @
07f4a8ad
plugins
{
id
'org.jetbrains.kotlin.jvm'
version
'1.4-M3'
id
'application'
}
repositories
{
mavenLocal
()
jcenter
()
maven
{
url
'https://dl.bintray.com/kotlin/kotlin-eap'
}
}
def
os
=
System
.
getProperty
(
"os.name"
)
def
target
=
"linux"
if
(
os
==
"Mac OS X"
)
{
target
=
"macos"
}
else
if
(
os
.
startsWith
(
"Win"
))
{
target
=
"windows"
}
dependencies
{
implementation
platform
(
'org.jetbrains.kotlin:kotlin-bom'
)
implementation
'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
implementation
"org.jetbrains.skiko:skiko-jvm-runtime-$target:0.1-SNAPSHOT"
testImplementation
'org.jetbrains.kotlin:kotlin-test'
testImplementation
'org.jetbrains.kotlin:kotlin-test-junit'
}
application
{
mainClassName
=
'SkijaInjectSample.AppKt'
}
samples/SkijaInjectSample/fonts/JetBrainsMono-Regular.ttf
0 → 100644
View file @
07f4a8ad
File added
samples/SkijaInjectSample/gradle/wrapper/gradle-wrapper.jar
0 → 100644
View file @
07f4a8ad
File added
samples/SkijaInjectSample/gradle/wrapper/gradle-wrapper.properties
0 → 100644
View file @
07f4a8ad
distributionBase
=
GRADLE_USER_HOME
distributionPath
=
wrapper/dists
distributionUrl
=
https
\:
//services.gradle.org/distributions/gradle-6.5-bin.zip
zipStoreBase
=
GRADLE_USER_HOME
zipStorePath
=
wrapper/dists
samples/SkijaInjectSample/gradlew
0 → 100755
View file @
07f4a8ad
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG
=
"
$0
"
# Need this for relative symlinks.
while
[
-h
"
$PRG
"
]
;
do
ls
=
`
ls
-ld
"
$PRG
"
`
link
=
`
expr
"
$ls
"
:
'.*-> \(.*\)$'
`
if
expr
"
$link
"
:
'/.*'
>
/dev/null
;
then
PRG
=
"
$link
"
else
PRG
=
`
dirname
"
$PRG
"
`
"/
$link
"
fi
done
SAVED
=
"
`
pwd
`
"
cd
"
`
dirname
\"
$PRG
\"
`
/"
>
/dev/null
APP_HOME
=
"
`
pwd
-P
`
"
cd
"
$SAVED
"
>
/dev/null
APP_NAME
=
"Gradle"
APP_BASE_NAME
=
`
basename
"
$0
"
`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS
=
'"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD
=
"maximum"
warn
()
{
echo
"
$*
"
}
die
()
{
echo
echo
"
$*
"
echo
exit
1
}
# OS specific support (must be 'true' or 'false').
cygwin
=
false
msys
=
false
darwin
=
false
nonstop
=
false
case
"
`
uname
`
"
in
CYGWIN
*
)
cygwin
=
true
;;
Darwin
*
)
darwin
=
true
;;
MINGW
*
)
msys
=
true
;;
NONSTOP
*
)
nonstop
=
true
;;
esac
CLASSPATH
=
$APP_HOME
/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if
[
-n
"
$JAVA_HOME
"
]
;
then
if
[
-x
"
$JAVA_HOME
/jre/sh/java"
]
;
then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD
=
"
$JAVA_HOME
/jre/sh/java"
else
JAVACMD
=
"
$JAVA_HOME
/bin/java"
fi
if
[
!
-x
"
$JAVACMD
"
]
;
then
die
"ERROR: JAVA_HOME is set to an invalid directory:
$JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD
=
"java"
which java
>
/dev/null 2>&1
||
die
"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if
[
"
$cygwin
"
=
"false"
-a
"
$darwin
"
=
"false"
-a
"
$nonstop
"
=
"false"
]
;
then
MAX_FD_LIMIT
=
`
ulimit
-H
-n
`
if
[
$?
-eq
0
]
;
then
if
[
"
$MAX_FD
"
=
"maximum"
-o
"
$MAX_FD
"
=
"max"
]
;
then
MAX_FD
=
"
$MAX_FD_LIMIT
"
fi
ulimit
-n
$MAX_FD
if
[
$?
-ne
0
]
;
then
warn
"Could not set maximum file descriptor limit:
$MAX_FD
"
fi
else
warn
"Could not query maximum file descriptor limit:
$MAX_FD_LIMIT
"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if
$darwin
;
then
GRADLE_OPTS
=
"
$GRADLE_OPTS
\"
-Xdock:name=
$APP_NAME
\"
\"
-Xdock:icon=
$APP_HOME
/media/gradle.icns
\"
"
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if
[
"
$cygwin
"
=
"true"
-o
"
$msys
"
=
"true"
]
;
then
APP_HOME
=
`
cygpath
--path
--mixed
"
$APP_HOME
"
`
CLASSPATH
=
`
cygpath
--path
--mixed
"
$CLASSPATH
"
`
JAVACMD
=
`
cygpath
--unix
"
$JAVACMD
"
`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW
=
`
find
-L
/
-maxdepth
1
-mindepth
1
-type
d 2>/dev/null
`
SEP
=
""
for
dir
in
$ROOTDIRSRAW
;
do
ROOTDIRS
=
"
$ROOTDIRS$SEP$dir
"
SEP
=
"|"
done
OURCYGPATTERN
=
"(^(
$ROOTDIRS
))"
# Add a user-defined pattern to the cygpath arguments
if
[
"
$GRADLE_CYGPATTERN
"
!=
""
]
;
then
OURCYGPATTERN
=
"
$OURCYGPATTERN
|(
$GRADLE_CYGPATTERN
)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i
=
0
for
arg
in
"
$@
"
;
do
CHECK
=
`
echo
"
$arg
"
|egrep
-c
"
$OURCYGPATTERN
"
-
`
CHECK2
=
`
echo
"
$arg
"
|egrep
-c
"^-"
`
### Determine if an option
if
[
$CHECK
-ne
0
]
&&
[
$CHECK2
-eq
0
]
;
then
### Added a condition
eval
`
echo
args
$i
`
=
`
cygpath
--path
--ignore
--mixed
"
$arg
"
`
else
eval
`
echo
args
$i
`
=
"
\"
$arg
\"
"
fi
i
=
`
expr
$i
+ 1
`
done
case
$i
in
0
)
set
--
;;
1
)
set
--
"
$args0
"
;;
2
)
set
--
"
$args0
"
"
$args1
"
;;
3
)
set
--
"
$args0
"
"
$args1
"
"
$args2
"
;;
4
)
set
--
"
$args0
"
"
$args1
"
"
$args2
"
"
$args3
"
;;
5
)
set
--
"
$args0
"
"
$args1
"
"
$args2
"
"
$args3
"
"
$args4
"
;;
6
)
set
--
"
$args0
"
"
$args1
"
"
$args2
"
"
$args3
"
"
$args4
"
"
$args5
"
;;
7
)
set
--
"
$args0
"
"
$args1
"
"
$args2
"
"
$args3
"
"
$args4
"
"
$args5
"
"
$args6
"
;;
8
)
set
--
"
$args0
"
"
$args1
"
"
$args2
"
"
$args3
"
"
$args4
"
"
$args5
"
"
$args6
"
"
$args7
"
;;
9
)
set
--
"
$args0
"
"
$args1
"
"
$args2
"
"
$args3
"
"
$args4
"
"
$args5
"
"
$args6
"
"
$args7
"
"
$args8
"
;;
esac
fi
# Escape application args
save
()
{
for
i
do
printf
%s
\\
n
"
$i
"
|
sed
"s/'/'
\\\\
''/g;1s/^/'/;
\$
s/
\$
/'
\\\\
/"
;
done
echo
" "
}
APP_ARGS
=
`
save
"
$@
"
`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set
--
$DEFAULT_JVM_OPTS
$JAVA_OPTS
$GRADLE_OPTS
"
\"
-Dorg.gradle.appname=
$APP_BASE_NAME
\"
"
-classpath
"
\"
$CLASSPATH
\"
"
org.gradle.wrapper.GradleWrapperMain
"
$APP_ARGS
"
exec
"
$JAVACMD
"
"
$@
"
samples/SkijaInjectSample/gradlew.bat
0 → 100755
View file @
07f4a8ad
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
samples/SkijaInjectSample/settings.gradle
0 → 100644
View file @
07f4a8ad
/*
* This file was generated by the Gradle 'init' task.
*
* The settings file is used to specify which projects to include in your build.
*
* Detailed information about configuring a multi-project build in Gradle can be found
* in the user manual at https://docs.gradle.org/6.5/userguide/multi_project_builds.html
*/
pluginManagement
{
repositories
{
mavenCentral
()
gradlePluginPortal
()
maven
{
url
"https://dl.bintray.com/kotlin/kotlin-eap"
}
}
}
rootProject
.
name
=
'SkijaInjectSample'
samples/SkijaInjectSample/src/main/kotlin/SkijaInjectSample/App.kt
0 → 100644
View file @
07f4a8ad
package
SkijaInjectSample
import
org.jetbrains.skiko.OpenGLApi
import
org.jetbrains.skiko.Engine
import
org.jetbrains.skiko.SkiaWindow
import
java.awt.event.MouseEvent
import
javax.swing.WindowConstants
import
javax.swing.event.MouseInputAdapter
import
org.jetbrains.skija.*
import
org.jetbrains.skiko.SkiaRenderer
import
java.awt.event.MouseMotionAdapter
import
kotlin.math.cos
import
kotlin.math.sin
fun
main
(
args
:
Array
<
String
>)
{
createWindow
(
"First window"
);
}
fun
createWindow
(
title
:
String
)
{
val
engine
:
Engine
=
Engine
.
get
()
var
mouseX
=
0
var
mouseY
=
0
val
window
=
SkiaWindow
()
window
.
defaultCloseOperation
=
WindowConstants
.
DISPOSE_ON_CLOSE
val
state
=
State
()
state
.
text
=
title
window
.
layer
.
renderer
=
Renderer
{
renderer
,
w
,
h
->
displayScene
(
renderer
,
w
,
h
,
mouseX
,
mouseY
,
state
)
}
window
.
layer
.
addMouseMotionListener
(
object
:
MouseMotionAdapter
()
{
override
fun
mouseMoved
(
event
:
MouseEvent
)
{
mouseX
=
event
.
x
mouseY
=
event
.
y
engine
.
render
(
window
.
layer
)
}
})
window
.
setVisible
(
true
);
// MANDATORY: set window size after calling setVisible(true)
window
.
setSize
(
800
,
600
);
}
class
Renderer
(
val
displayScene
:
(
Renderer
,
Int
,
Int
)
->
Unit
):
SkiaRenderer
{
val
typeface
=
Typeface
.
makeFromFile
(
"fonts/JetBrainsMono-Regular.ttf"
)
val
font
=
Font
(
typeface
,
40f
)
val
paint
=
Paint
().
apply
{
setColor
(
0
xff9BC730L
.
toInt
())
setMode
(
PaintMode
.
FILL
)
setStrokeWidth
(
1f
)
}
var
canvas
:
Canvas
?
=
null
override
fun
onInit
()
{
}
override
fun
onDispose
()
{
}
override
fun
onReshape
(
width
:
Int
,
height
:
Int
)
{
}
override
fun
onRender
(
canvas
:
Canvas
,
width
:
Int
,
height
:
Int
)
{
this
.
canvas
=
canvas
displayScene
(
this
,
width
,
height
)
}
}
class
State
{
var
frame
:
Int
=
0
var
text
:
String
=
"Hello Skija"
}
fun
displayScene
(
renderer
:
Renderer
,
width
:
Int
,
height
:
Int
,
xpos
:
Int
,
ypos
:
Int
,
state
:
State
)
{
val
canvas
=
renderer
.
canvas
!!
val
watchFill
=
Paint
().
setColor
(
0
xFFFFFFFF
.
toInt
())
val
watchStroke
=
Paint
().
setColor
(
0
xFF000000
.
toInt
()).
setMode
(
PaintMode
.
STROKE
).
setStrokeWidth
(
1f
).
setAntiAlias
(
false
)
val
watchStrokeAA
=
Paint
().
setColor
(
0
xFF000000
.
toInt
()).
setMode
(
PaintMode
.
STROKE
).
setStrokeWidth
(
1f
)
val
watchFillHover
=
Paint
().
setColor
(
0
xFFE4FF01
.
toInt
())
for
(
x
in
0
..
(
width
-
50
)
step
50
)
{
for
(
y
in
0
..
(
height
-
50
)
step
50
)
{
val
hover
=
xpos
>
x
+
0
&&
xpos
<
x
+
50
&&
ypos
>
y
+
0
&&
ypos
<
y
+
50
val
fill
=
if
(
hover
)
watchFillHover
else
watchFill
val
stroke
=
if
(
x
>
width
/
2
)
watchStrokeAA
else
watchStroke
canvas
.
drawOval
(
Rect
.
makeXYWH
(
x
+
5f
,
y
+
5f
,
40f
,
40f
),
fill
)
canvas
.
drawOval
(
Rect
.
makeXYWH
(
x
+
5f
,
y
+
5f
,
40f
,
40f
),
stroke
)
var
angle
=
0f
while
(
angle
<
2f
*
Math
.
PI
)
{
canvas
.
drawLine
(
(
x
+
25
-
17
*
sin
(
angle
)),
(
y
+
25
+
17
*
cos
(
angle
)),
(
x
+
25
-
20
*
sin
(
angle
)),
(
y
+
25
+
20
*
cos
(
angle
)),
stroke
)
angle
+=
(
2.0
*
Math
.
PI
/
12.0
).
toFloat
()
}
val
time
=
System
.
currentTimeMillis
()
%
60000
+
(
x
.
toFloat
()
/
width
*
5000
).
toLong
()
+
(
y
.
toFloat
()
/
width
*
5000
).
toLong
()
val
angle1
=
(
time
.
toFloat
()
/
5000
*
2f
*
Math
.
PI
).
toFloat
()
canvas
.
drawLine
(
x
+
25f
,
y
+
25f
,
x
+
25f
-
15f
*
sin
(
angle1
),
y
+
25f
+
15
*
cos
(
angle1
),
stroke
)
val
angle2
=
(
time
/
60000
*
2f
*
Math
.
PI
).
toFloat
()
canvas
.
drawLine
(
x
+
25f
,
y
+
25f
,
x
+
25f
-
10f
*
sin
(
angle2
),
y
+
25f
+
10f
*
cos
(
angle2
),
stroke
)
}
}
val
text
=
"${state.text} ${state.frame++}!"
canvas
.
drawString
(
text
,
xpos
.
toFloat
(),
ypos
.
toFloat
(),
renderer
.
font
,
renderer
.
paint
)
}
samples/SkijaInjectSample/src/test/kotlin/SkijaInjectSample/AppTest.kt
0 → 100644
View file @
07f4a8ad
/*
* This Kotlin source file was generated by the Gradle 'init' task.
*/
package
SkijaInjectSample
import
kotlin.test.Test
import
kotlin.test.assertNotNull
class
AppTest
{
// @Test fun testAppHasAGreeting() {
// val classUnderTest = App()
// assertNotNull(classUnderTest.greeting, "app should have a greeting")
// }
}
skiko/.gitignore
View file @
07f4a8ad
build
build
.gradle
.gradle
local.properties
local.properties
.DS_Store
skiko/build.gradle.kts
View file @
07f4a8ad
...
@@ -22,6 +22,8 @@ val target = when {
...
@@ -22,6 +22,8 @@ val target = when {
else
->
throw
Error
(
"Unknown os $hostOs"
)
else
->
throw
Error
(
"Unknown os $hostOs"
)
}
}
val
jdkHome
=
System
.
getProperty
(
"java.home"
)
?:
error
(
"'java.home' is null"
)
repositories
{
repositories
{
mavenCentral
()
mavenCentral
()
maven
{
maven
{
...
@@ -77,10 +79,6 @@ kotlin {
...
@@ -77,10 +79,6 @@ kotlin {
// See https://docs.gradle.org/current/userguide/cpp_library_plugin.html.
// See https://docs.gradle.org/current/userguide/cpp_library_plugin.html.
tasks
.
withType
(
CppCompile
::
class
.
java
).
configureEach
{
tasks
.
withType
(
CppCompile
::
class
.
java
).
configureEach
{
source
.
from
(
fileTree
(
"$projectDir/../skija/src/main/cc"
),
fileTree
(
"$projectDir/src/jvmMain/cpp"
)
)
// Prefer 'java.home' system property to simplify overriding from Intellij.
// Prefer 'java.home' system property to simplify overriding from Intellij.
// When used from command-line, it is effectively equal to JAVA_HOME.
// When used from command-line, it is effectively equal to JAVA_HOME.
if
(
JavaVersion
.
current
()
<
JavaVersion
.
VERSION_11
)
{
if
(
JavaVersion
.
current
()
<
JavaVersion
.
VERSION_11
)
{
...
@@ -154,22 +152,49 @@ tasks.withType(CppCompile::class.java).configureEach {
...
@@ -154,22 +152,49 @@ tasks.withType(CppCompile::class.java).configureEach {
}
}
}
}
// Very hacky way to compile Objective-C sources and add the
// resulting object files into the final library.
project
.
tasks
.
register
<
Exec
>(
"objcCompile"
)
{
val
inputDir
=
"$projectDir/src/jvmMain/objectiveC/$target"
val
outDir
=
"$buildDir/objc/$target"
val
objcSrc
=
"drawlayer"
commandLine
=
listOf
(
"clang"
,
"-I$jdkHome/include"
,
"-I$jdkHome/include/darwin"
,
"-c"
,
"$inputDir/$objcSrc.m"
,
"-o"
,
"$outDir/$objcSrc.o"
)
file
(
outDir
).
mkdirs
()
inputs
.
files
(
"$inputDir/$objcSrc.m"
)
outputs
.
files
(
"$outDir/$objcSrc.o"
)
}
tasks
.
withType
(
LinkSharedLibrary
::
class
.
java
).
configureEach
{
tasks
.
withType
(
LinkSharedLibrary
::
class
.
java
).
configureEach
{
when
(
target
)
{
when
(
target
)
{
"macos"
->
{
"macos"
->
{
dependsOn
(
project
.
tasks
.
named
(
"objcCompile"
))
linkerArgs
.
addAll
(
linkerArgs
.
addAll
(
listOf
(
listOf
(
"-dead_strip"
,
"-dead_strip"
,
"-framework"
,
"AppKit"
,
"-framework"
,
"CoreFoundation"
,
"-framework"
,
"CoreFoundation"
,
"-framework"
,
"CoreGraphics"
,
"-framework"
,
"CoreGraphics"
,
"-framework"
,
"CoreServices"
,
"-framework"
,
"CoreServices"
,
"-framework"
,
"CoreText"
"-framework"
,
"CoreText"
,
"-framework"
,
"Foundation"
,
"-framework"
,
"OpenGL"
,
"-framework"
,
"QuartzCore"
// for CoreAnimation
)
)
)
)
}
}
"linux"
->
{
"linux"
->
{
linkerArgs
.
addAll
(
linkerArgs
.
addAll
(
listOf
(
listOf
(
"-lGL"
,
"-lfontconfig"
"-lfontconfig"
)
)
)
)
...
@@ -177,14 +202,24 @@ tasks.withType(LinkSharedLibrary::class.java).configureEach {
...
@@ -177,14 +202,24 @@ tasks.withType(LinkSharedLibrary::class.java).configureEach {
"windows"
->
{
"windows"
->
{
linkerArgs
.
addAll
(
linkerArgs
.
addAll
(
listOf
(
listOf
(
"user32.lib"
,
"gdi32.lib"
,
"opengl32.lib"
"opengl32.lib"
,
"shcore.lib"
,
"user32.lib"
)
)
)
)
}
}
}
}
}
}
extensions
.
configure
<
CppLibrary
>
{
source
.
from
(
fileTree
(
"$projectDir/../skija/src/main/cc"
),
fileTree
(
"$projectDir/src/jvmMain/cpp/common"
),
fileTree
(
"$projectDir/src/jvmMain/cpp/$target"
)
)
}
library
{
library
{
linkage
.
addAll
(
listOf
(
Linkage
.
SHARED
))
linkage
.
addAll
(
listOf
(
Linkage
.
SHARED
))
targetMachines
.
addAll
(
listOf
(
machines
.
macOS
.
x86_64
,
machines
.
linux
.
x86_64
,
machines
.
windows
.
x86_64
))
targetMachines
.
addAll
(
listOf
(
machines
.
macOS
.
x86_64
,
machines
.
linux
.
x86_64
,
machines
.
windows
.
x86_64
))
...
@@ -197,6 +232,9 @@ library {
...
@@ -197,6 +232,9 @@ library {
else
else
include
(
"**.a"
)
include
(
"**.a"
)
})
})
implementation
(
fileTree
(
"$buildDir/objc/$target"
).
matching
{
include
(
"**.o"
)
})
}
}
}
}
...
...
skiko/gradle.properties
View file @
07f4a8ad
kotlin.code.style
=
official
kotlin.code.style
=
official
deploy.version
=
0.1-SNAPSHOT
deploy.version
=
0.1-SNAPSHOT
deploy.ci.version
=
0.1
deploy.ci.version
=
0.1
deploy.version
=
0.1-SNAPSHOT
deploy.ci.version
=
0.1
\ No newline at end of file
skiko/src/jvmMain/cpp/Window.cc
deleted
100644 → 0
View file @
81e843ff
#include <jni.h>
extern
"C"
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skiko_SkiaWindow_nativeMethod
(
JNIEnv
*
env
,
jobject
thiz
,
jlong
param
)
{
return
param
+
1
;
}
\ No newline at end of file
skiko/src/jvmMain/cpp/common/jawt.cc
0 → 100644
View file @
07f4a8ad
#include <jawt.h>
#include <jawt_md.h>
#include <stdlib.h>
#if SK_BUILD_FOR_WIN
#include <windows.h>
#else
#include <dlfcn.h>
#endif
typedef
jboolean
(
*
JAWT_GetAWT_t
)(
JNIEnv
*
,
JAWT
*
);
extern
"C"
jboolean
Skiko_GetAWT
(
JNIEnv
*
env
,
JAWT
*
awt
)
{
static
JAWT_GetAWT_t
func
=
nullptr
;
if
(
!
func
)
{
char
*
jdkHome
=
getenv
(
"JAVA_HOME"
);
if
(
!
jdkHome
)
{
fprintf
(
stderr
,
"No JAVA_HOME defined!"
);
abort
();
}
#if SK_BUILD_FOR_WIN
char
path
[
FILENAME_MAX
];
snprintf
(
path
,
sizeof
(
path
),
"%s
\\
bin
\\
jawt.dll"
,
jdkHome
);
HMODULE
lib
=
LoadLibrary
(
path
);
if
(
!
lib
)
{
fprintf
(
stderr
,
"Cannot open %s
\n
"
,
path
);
abort
();
}
func
=
reinterpret_cast
<
JAWT_GetAWT_t
>
(
GetProcAddress
(
lib
,
"JAWT_GetAWT"
));
if
(
!
func
)
{
fprintf
(
stderr
,
"Cannot find JAWT_GetAWT in %s
\n
"
,
path
);
abort
();
}
#else
char
path
[
FILENAME_MAX
];
snprintf
(
path
,
sizeof
(
path
),
"%s/lib/libjawt%s"
,
jdkHome
,
#if SK_BUILD_FOR_MAC
".dylib"
#else
".so"
#endif
);
void
*
lib
=
dlopen
(
path
,
RTLD_LAZY
|
RTLD_GLOBAL
);
if
(
!
lib
)
{
fprintf
(
stderr
,
"Cannot open %s: %s
\n
"
,
path
,
dlerror
());
abort
();
}
func
=
reinterpret_cast
<
JAWT_GetAWT_t
>
(
dlsym
(
lib
,
"JAWT_GetAWT"
));
if
(
!
func
)
{
fprintf
(
stderr
,
"Cannot find JAWT_GetAWT in %s
\n
"
,
path
);
abort
();
}
#endif
}
return
func
(
env
,
awt
);
}
\ No newline at end of file
skiko/src/jvmMain/cpp/common/openglapi.cc
0 → 100644
View file @
07f4a8ad
#if SK_BUILD_FOR_WIN
#include <SDKDDKVer.h>
#include <windows.h>
#endif
#if SK_BUILD_FOR_MAC
#import <OpenGL/gl3.h>
#else
#include <GL/gl.h>
#endif
#include <jni.h>
extern
"C"
{
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_OpenGLApi_glViewport
(
JNIEnv
*
env
,
jobject
object
,
jint
x
,
jint
y
,
jint
w
,
jint
h
)
{
glViewport
(
x
,
y
,
w
,
h
);
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_OpenGLApi_glClearColor
(
JNIEnv
*
env
,
jobject
object
,
jfloat
r
,
jfloat
g
,
jfloat
b
,
jfloat
a
)
{
glClearColor
(
r
,
g
,
b
,
a
);
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_OpenGLApi_glClear
(
JNIEnv
*
env
,
jobject
object
,
jint
mask
)
{
glClear
(
mask
);
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_OpenGLApi_glFinish
(
JNIEnv
*
env
,
jobject
object
)
{
glFinish
();
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_OpenGLApi_glEnable
(
JNIEnv
*
env
,
jobject
object
,
jint
cap
)
{
glEnable
(
cap
);
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_OpenGLApi_glBindTexture
(
JNIEnv
*
env
,
jobject
object
,
jint
target
,
jint
texture
)
{
glBindTexture
(
target
,
texture
);
}
JNIEXPORT
jint
JNICALL
Java_org_jetbrains_skiko_OpenGLApi_glGetIntegerv
(
JNIEnv
*
env
,
jobject
object
,
jint
pname
)
{
GLint
data
;
glGetIntegerv
(
pname
,
&
data
);
return
(
jint
)
data
;
}
}
\ No newline at end of file
skiko/src/jvmMain/cpp/linux/drawlayer.cc
0 → 100644
View file @
07f4a8ad
// drawcanvas.cpp : Defines the exported functions for the DLL application.
#include <jawt_md.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <unistd.h>
#include <stdio.h>
#include <set>
using
namespace
std
;
typedef
GLXContext
(
*
glXCreateContextAttribsARBProc
)(
Display
*
,
GLXFBConfig
,
GLXContext
,
Bool
,
const
int
*
);
extern
"C"
jboolean
Skiko_GetAWT
(
JNIEnv
*
env
,
JAWT
*
awt
);
JavaVM
*
jvm
=
NULL
;
class
LayersSet
{
public
:
jobject
canvasRef
;
GLXContext
context
;
void
update
()
{
draw
();
}
void
dispose
()
{
context
=
NULL
;
}
private
:
bool
isDrawing
=
false
;
void
draw
()
{
if
(
isDrawing
)
{
return
;
}
isDrawing
=
true
;
if
(
jvm
!=
NULL
)
{
JNIEnv
*
env
;
jvm
->
GetEnv
((
void
**
)
&
env
,
JNI_VERSION_10
);
JAWT
awt
;
JAWT_DrawingSurface
*
ds
=
NULL
;
JAWT_DrawingSurfaceInfo
*
dsi
=
NULL
;
jboolean
result
=
JNI_FALSE
;
jint
lock
=
0
;
JAWT_X11DrawingSurfaceInfo
*
dsi_x11
;
awt
.
version
=
(
jint
)
JAWT_VERSION_9
;
result
=
Skiko_GetAWT
(
env
,
&
awt
);
if
(
result
==
JNI_FALSE
)
{
fprintf
(
stderr
,
"JAWT_GetAWT failed! Result is JNI_FALSE
\n
"
);
return
;
}
ds
=
awt
.
GetDrawingSurface
(
env
,
canvasRef
);
lock
=
ds
->
Lock
(
ds
);
dsi
=
ds
->
GetDrawingSurfaceInfo
(
ds
);
dsi_x11
=
(
JAWT_X11DrawingSurfaceInfo
*
)
dsi
->
platformInfo
;
Display
*
display
=
dsi_x11
->
display
;
Window
window
=
dsi_x11
->
drawable
;
if
(
dsi
!=
NULL
)
{
jvm
->
AttachCurrentThread
((
void
**
)
&
env
,
NULL
);
glXMakeCurrent
(
display
,
window
,
context
);
jclass
wndClass
=
env
->
GetObjectClass
(
canvasRef
);
jmethodID
drawMethod
=
env
->
GetMethodID
(
wndClass
,
"draw"
,
"()V"
);
if
(
NULL
==
drawMethod
)
{
fprintf
(
stderr
,
"The method Window.draw() not found!
\n
"
);
return
;
}
env
->
CallVoidMethod
(
canvasRef
,
drawMethod
);
glXSwapBuffers
(
display
,
window
);
glXMakeCurrent
(
display
,
0
,
0
);
jvm
->
DetachCurrentThread
();
}
ds
->
FreeDrawingSurfaceInfo
(
dsi
);
ds
->
Unlock
(
ds
);
awt
.
FreeDrawingSurface
(
ds
);
}
isDrawing
=
false
;
}
};
set
<
LayersSet
*>
*
windowsSet
=
NULL
;
LayersSet
*
findByObject
(
JNIEnv
*
env
,
jobject
object
)
{
for
(
auto
&
layer
:
*
windowsSet
)
{
if
(
env
->
IsSameObject
(
object
,
layer
->
canvasRef
)
==
JNI_TRUE
)
{
return
layer
;
}
}
fprintf
(
stderr
,
"The set does not contain this window.
\n
"
);
return
NULL
;
}
extern
"C"
{
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_updateLayer
(
JNIEnv
*
env
,
jobject
canvas
)
{
if
(
windowsSet
!=
NULL
)
{
LayersSet
*
layer
=
findByObject
(
env
,
canvas
);
if
(
layer
!=
NULL
)
{
if
(
layer
->
context
==
NULL
)
{
env
->
DeleteGlobalRef
(
layer
->
canvasRef
);
layer
->
canvasRef
=
NULL
;
windowsSet
->
erase
(
layer
);
delete
layer
;
}
return
;
}
}
else
{
windowsSet
=
new
set
<
LayersSet
*>
();
}
if
(
jvm
==
NULL
)
{
env
->
GetJavaVM
(
&
jvm
);
}
JAWT
awt
;
JAWT_DrawingSurface
*
ds
=
NULL
;
JAWT_DrawingSurfaceInfo
*
dsi
=
NULL
;
jboolean
result
=
JNI_FALSE
;
jint
lock
=
0
;
JAWT_X11DrawingSurfaceInfo
*
dsi_x11
;
awt
.
version
=
(
jint
)
JAWT_VERSION_9
;
result
=
Skiko_GetAWT
(
env
,
&
awt
);
if
(
result
==
JNI_FALSE
)
{
fprintf
(
stderr
,
"JAWT_GetAWT failed! Result is JNI_FALSE
\n
"
);
return
;
}
ds
=
awt
.
GetDrawingSurface
(
env
,
canvas
);
lock
=
ds
->
Lock
(
ds
);
dsi
=
ds
->
GetDrawingSurfaceInfo
(
ds
);
dsi_x11
=
(
JAWT_X11DrawingSurfaceInfo
*
)
dsi
->
platformInfo
;
Display
*
display
=
dsi_x11
->
display
;
Window
window
=
dsi_x11
->
drawable
;
if
(
dsi
!=
NULL
)
{
GLint
att
[]
=
{
GLX_RGBA
,
GLX_DOUBLEBUFFER
,
None
};
XVisualInfo
*
vi
=
glXChooseVisual
(
display
,
0
,
att
);
GLXContext
context
=
glXCreateContext
(
display
,
vi
,
NULL
,
GL_TRUE
);
LayersSet
*
layer
=
new
LayersSet
();
windowsSet
->
insert
(
layer
);
jobject
canvasRef
=
env
->
NewGlobalRef
(
canvas
);
layer
->
canvasRef
=
canvasRef
;
layer
->
context
=
context
;
}
ds
->
FreeDrawingSurfaceInfo
(
dsi
);
ds
->
Unlock
(
ds
);
awt
.
FreeDrawingSurface
(
ds
);
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_redrawLayer
(
JNIEnv
*
env
,
jobject
canvas
)
{
LayersSet
*
layer
=
findByObject
(
env
,
canvas
);
if
(
layer
!=
NULL
)
{
layer
->
update
();
}
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_disposeLayer
(
JNIEnv
*
env
,
jobject
canvas
)
{
LayersSet
*
layer
=
findByObject
(
env
,
canvas
);
if
(
layer
!=
NULL
)
{
layer
->
dispose
();
}
}
JNIEXPORT
jfloat
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_getContentScale
(
JNIEnv
*
env
,
jobject
canvas
)
{
return
1.0
f
;
}
}
// extern "C"
\ No newline at end of file
skiko/src/jvmMain/cpp/windows/drawlayer.cc
0 → 100644
View file @
07f4a8ad
// drawcanvas.cpp : Defines the exported functions for the DLL application.
#include <SDKDDKVer.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <gl/GL.h>
#include <jawt_md.h>
#include <set>
#include <Shellscalingapi.h>
#include <stdio.h>
#include <Wingdi.h>
using
namespace
std
;
JavaVM
*
jvm
=
NULL
;
extern
"C"
jboolean
Skiko_GetAWT
(
JNIEnv
*
env
,
JAWT
*
awt
);
class
LayersSet
{
public
:
jobject
windowRef
;
HGLRC
context
;
HWND
glLayer
;
void
update
()
{
draw
();
}
void
dispose
()
{
glLayer
=
NULL
;
context
=
NULL
;
}
private
:
bool
isDrawing
=
false
;
void
draw
()
{
if
(
isDrawing
)
{
return
;
}
isDrawing
=
true
;
HDC
handler
=
GetDC
(
glLayer
);
wglMakeCurrent
(
handler
,
context
);
if
(
jvm
!=
NULL
)
{
JNIEnv
*
env
;
jvm
->
AttachCurrentThread
((
void
**
)
&
env
,
NULL
);
jclass
wndClass
=
env
->
GetObjectClass
(
windowRef
);
jmethodID
drawMethod
=
env
->
GetMethodID
(
wndClass
,
"draw"
,
"()V"
);
if
(
NULL
==
drawMethod
)
{
fprintf
(
stderr
,
"The method Window.draw() not found!
\n
"
);
return
;
}
env
->
CallVoidMethod
(
windowRef
,
drawMethod
);
}
wglMakeCurrent
(
handler
,
NULL
);
isDrawing
=
false
;
}
};
set
<
LayersSet
*>
*
windowsSet
=
NULL
;
LayersSet
*
findByObject
(
JNIEnv
*
env
,
jobject
object
)
{
for
(
auto
&
layer
:
*
windowsSet
)
{
if
(
env
->
IsSameObject
(
object
,
layer
->
windowRef
)
==
JNI_TRUE
)
{
return
layer
;
}
}
fprintf
(
stderr
,
"The set does not contain this window.
\n
"
);
return
NULL
;
}
float
getScaleFloatFromEnum
(
DEVICE_SCALE_FACTOR
scaleFactor
)
{
switch
(
scaleFactor
)
{
case
SCALE_100_PERCENT
:
return
1.0
f
;
case
SCALE_120_PERCENT
:
return
1.2
f
;
case
SCALE_125_PERCENT
:
return
1.25
f
;
case
SCALE_140_PERCENT
:
return
1.4
f
;
case
SCALE_150_PERCENT
:
return
1.5
f
;
case
SCALE_160_PERCENT
:
return
1.6
f
;
case
SCALE_175_PERCENT
:
return
1.75
f
;
case
SCALE_180_PERCENT
:
return
1.8
f
;
case
SCALE_200_PERCENT
:
return
2.0
f
;
case
SCALE_225_PERCENT
:
return
2.25
f
;
case
SCALE_250_PERCENT
:
return
2.5
f
;
case
SCALE_300_PERCENT
:
return
3.0
f
;
case
SCALE_350_PERCENT
:
return
3.5
f
;
case
SCALE_400_PERCENT
:
return
4.0
f
;
case
SCALE_450_PERCENT
:
return
4.5
f
;
case
SCALE_500_PERCENT
:
return
5.0
f
;
case
DEVICE_SCALE_FACTOR_INVALID
:
return
1.0
f
;
}
return
1.0
f
;
}
extern
"C"
{
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_updateLayer
(
JNIEnv
*
env
,
jobject
window
)
{
if
(
windowsSet
!=
NULL
)
{
LayersSet
*
layer
=
findByObject
(
env
,
window
);
if
(
layer
!=
NULL
)
{
if
(
layer
->
glLayer
==
NULL
&&
layer
->
context
==
NULL
)
{
env
->
DeleteGlobalRef
(
layer
->
windowRef
);
layer
->
windowRef
=
NULL
;
windowsSet
->
erase
(
layer
);
delete
layer
;
}
return
;
}
}
else
{
windowsSet
=
new
set
<
LayersSet
*>
();
}
JAWT
awt
;
JAWT_DrawingSurface
*
ds
=
NULL
;
JAWT_DrawingSurfaceInfo
*
dsi
=
NULL
;
PIXELFORMATDESCRIPTOR
pixFormatDscr
;
HGLRC
context
=
NULL
;
jboolean
result
=
JNI_FALSE
;
jint
lock
=
0
;
JAWT_Win32DrawingSurfaceInfo
*
dsi_win
;
awt
.
version
=
(
jint
)
JAWT_VERSION_9
;
result
=
Skiko_GetAWT
(
env
,
&
awt
);
if
(
result
==
JNI_FALSE
)
{
fprintf
(
stderr
,
"JAWT_GetAWT failed! Result is JNI_FALSE
\n
"
);
return
;
}
if
(
jvm
==
NULL
)
{
env
->
GetJavaVM
(
&
jvm
);
}
ds
=
awt
.
GetDrawingSurface
(
env
,
window
);
lock
=
ds
->
Lock
(
ds
);
dsi
=
ds
->
GetDrawingSurfaceInfo
(
ds
);
// Get the platform-specific drawing info
dsi_win
=
(
JAWT_Win32DrawingSurfaceInfo
*
)
dsi
->
platformInfo
;
HWND
hwnd
=
dsi_win
->
hwnd
;
HDC
wndHandler
=
GetDC
(
hwnd
);
if
(
dsi
!=
NULL
)
{
memset
(
&
pixFormatDscr
,
0
,
sizeof
(
PIXELFORMATDESCRIPTOR
));
pixFormatDscr
.
nSize
=
sizeof
(
PIXELFORMATDESCRIPTOR
);
pixFormatDscr
.
nVersion
=
1
;
pixFormatDscr
.
dwFlags
=
PFD_DRAW_TO_WINDOW
|
PFD_SUPPORT_OPENGL
|
PFD_DOUBLEBUFFER_DONTCARE
;
pixFormatDscr
.
iPixelType
=
PFD_TYPE_RGBA
;
pixFormatDscr
.
cColorBits
=
32
;
int
iPixelFormat
=
ChoosePixelFormat
(
wndHandler
,
&
pixFormatDscr
);
SetPixelFormat
(
wndHandler
,
iPixelFormat
,
&
pixFormatDscr
);
DescribePixelFormat
(
wndHandler
,
iPixelFormat
,
sizeof
(
PIXELFORMATDESCRIPTOR
),
&
pixFormatDscr
);
context
=
wglCreateContext
(
wndHandler
);
LayersSet
*
layer
=
new
LayersSet
();
windowsSet
->
insert
(
layer
);
jobject
windowRef
=
env
->
NewGlobalRef
(
window
);
layer
->
windowRef
=
windowRef
;
layer
->
glLayer
=
hwnd
;
layer
->
context
=
context
;
}
ds
->
FreeDrawingSurfaceInfo
(
dsi
);
ds
->
Unlock
(
ds
);
awt
.
FreeDrawingSurface
(
ds
);
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_redrawLayer
(
JNIEnv
*
env
,
jobject
window
)
{
LayersSet
*
layer
=
findByObject
(
env
,
window
);
if
(
layer
!=
NULL
)
{
layer
->
update
();
}
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_disposeLayer
(
JNIEnv
*
env
,
jobject
window
)
{
LayersSet
*
layer
=
findByObject
(
env
,
window
);
if
(
layer
!=
NULL
)
{
layer
->
dispose
();
}
}
JNIEXPORT
jfloat
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_getContentScale
(
JNIEnv
*
env
,
jobject
window
)
{
LayersSet
*
layer
=
findByObject
(
env
,
window
);
if
(
layer
!=
NULL
)
{
// get scale dpi factor of current monitor
DEVICE_SCALE_FACTOR
scaleFactor
;
GetScaleFactorForMonitor
(
MonitorFromWindow
(
layer
->
glLayer
,
MONITOR_DEFAULTTOPRIMARY
),
&
scaleFactor
);
return
getScaleFloatFromEnum
(
scaleFactor
);
}
return
1.0
f
;
}
}
// extern "C"
\ No newline at end of file
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/Drawable.kt
0 → 100644
View file @
07f4a8ad
package
org.jetbrains.skiko
interface
Drawable
{
fun
redrawLayer
()
fun
updateLayer
()
fun
disposeLayer
()
val
contentScale
:
Float
}
\ No newline at end of file
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/Engine.kt
0 → 100644
View file @
07f4a8ad
package
org.jetbrains.skiko
class
Engine
private
constructor
()
{
private
var
api
=
GraphicsApi
.
UNKNOWN
fun
currentApi
():
GraphicsApi
{
return
api
}
/**
* GAG - At the moment always initializes OpenGL.
* @param osType The current OS type of the device.
*/
private
fun
initSuitableGraphicsApi
(
osType
:
OSType
)
{
when
{
osType
===
OSType
.
MAC_OS
->
{
OpenGLApi
.
get
()
// for Metal
instance
.
api
=
GraphicsApi
.
OPENGL
}
osType
===
OSType
.
LINUX
->
{
OpenGLApi
.
get
()
// for Vulkan and OpenGL
instance
.
api
=
GraphicsApi
.
OPENGL
}
osType
===
OSType
.
WINDOWS
->
{
OpenGLApi
.
get
()
// for Vulkan and OpenGL
instance
.
api
=
GraphicsApi
.
OPENGL
}
else
->
{
OpenGLApi
.
get
()
// default
instance
.
api
=
GraphicsApi
.
OPENGL
}
}
}
fun
render
(
drawable
:
Drawable
)
{
drawable
.
updateLayer
()
drawable
.
redrawLayer
()
}
companion
object
{
private
lateinit
var
instance
:
Engine
fun
get
():
Engine
{
if
(!
this
::
instance
.
isInitialized
)
{
instance
=
Engine
()
instance
.
initSuitableGraphicsApi
(
OSType
.
getCurrent
())
}
return
instance
}
}
}
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/GraphicsApi.kt
0 → 100644
View file @
07f4a8ad
package
org.jetbrains.skiko
enum
class
GraphicsApi
{
UNKNOWN
,
OPENGL
,
VULKAN
,
METAL
}
\ No newline at end of file
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/HardwareLayer.kt
0 → 100644
View file @
07f4a8ad
package
org.jetbrains.skiko
import
java.awt.Graphics
import
java.awt.Canvas
open
class
HardwareLayer
:
Canvas
(),
Drawable
{
override
fun
paint
(
g
:
Graphics
)
{
Engine
.
get
().
render
(
this
)
}
open
fun
draw
()
{}
external
override
fun
redrawLayer
()
external
override
fun
updateLayer
()
external
override
fun
disposeLayer
()
override
val
contentScale
:
Float
external
get
}
\ No newline at end of file
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/Library.kt
View file @
07f4a8ad
...
@@ -16,19 +16,19 @@ object Library {
...
@@ -16,19 +16,19 @@ object Library {
val
libFileName
=
"$libPrefix$name$libExtension"
val
libFileName
=
"$libPrefix$name$libExtension"
val
url
=
Library
::
class
.
java
.
getResource
(
resourcePath
+
libFileName
)
val
url
=
Library
::
class
.
java
.
getResource
(
resourcePath
+
libFileName
)
// println("Loading " + url);
val
libFile
=
when
{
val
libFile
=
when
{
url
==
null
->
error
(
"Library $libFileName is not found in $resourcePath"
)
url
==
null
->
error
(
"Library $libFileName is not found in $resourcePath"
)
url
.
protocol
==
"file"
->
File
(
url
.
toURI
())
url
.
protocol
==
"file"
->
File
(
url
.
toURI
())
else
->
url
.
openStream
().
use
{
input
->
else
->
url
.
openStream
().
use
{
input
->
val
tempRoot
=
File
(
System
.
getProperty
(
"java.io.tmpdir"
))
val
tempRoot
=
File
(
System
.
getProperty
(
"java.io.tmpdir"
))
val
tempDir
=
tempRoot
.
resolve
(
"ski
ja
_"
+
System
.
nanoTime
()).
apply
{
mkdirs
()
}
val
tempDir
=
tempRoot
.
resolve
(
"ski
ko
_"
+
System
.
nanoTime
()).
apply
{
mkdirs
()
}
File
(
tempDir
,
libFileName
).
also
{
File
(
tempDir
,
libFileName
).
also
{
it
.
deleteOnExit
()
it
.
deleteOnExit
()
Files
.
copy
(
input
,
it
.
toPath
(),
StandardCopyOption
.
REPLACE_EXISTING
)
Files
.
copy
(
input
,
it
.
toPath
(),
StandardCopyOption
.
REPLACE_EXISTING
)
}
}
}
}
}
}
//println("Loading $url from ${libFile.absolutePath}")
System
.
load
(
libFile
.
absolutePath
)
System
.
load
(
libFile
.
absolutePath
)
loaded
=
true
loaded
=
true
}
}
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/Main.kt
View file @
07f4a8ad
...
@@ -4,7 +4,17 @@ import org.jetbrains.skija.Library
...
@@ -4,7 +4,17 @@ import org.jetbrains.skija.Library
import
org.jetbrains.skija.Surface
import
org.jetbrains.skija.Surface
fun
main
()
{
fun
main
()
{
println
(
Skia
Window
().
nativeMethod
(
41
))
println
(
Skia
LibraryTester
().
nativeMethod
(
41
))
val
surface
=
Surface
.
makeRasterN32Premul
(
100
,
100
)
val
surface
=
Surface
.
makeRasterN32Premul
(
100
,
100
)
println
(
surface
)
println
(
surface
)
}
}
private
class
SkiaLibraryTester
{
companion
object
{
init
{
Library
.
load
(
"/"
,
"skiko"
)
}
}
external
fun
nativeMethod
(
param
:
Long
):
Long
}
\ No newline at end of file
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/OSType.kt
0 → 100644
View file @
07f4a8ad
package
org.jetbrains.skiko
enum
class
OSType
{
MAC_OS
,
LINUX
,
WINDOWS
,
UNKNOWN
;
companion
object
{
private
lateinit
var
currentOSType
:
OSType
fun
getCurrent
():
OSType
{
if
(!
this
::
currentOSType
.
isInitialized
)
{
currentOSType
=
defineOsType
()
}
return
currentOSType
}
private
fun
defineOsType
():
OSType
{
val
osName
=
System
.
getProperty
(
"os.name"
).
toLowerCase
()
if
(
isWindows
(
osName
))
{
return
WINDOWS
}
if
(
isMac
(
osName
))
{
return
MAC_OS
}
return
if
(
isUnix
(
osName
))
{
LINUX
}
else
UNKNOWN
}
private
fun
isWindows
(
name
:
String
):
Boolean
{
return
name
.
indexOf
(
"win"
)
>=
0
}
private
fun
isMac
(
name
:
String
):
Boolean
{
return
name
.
indexOf
(
"mac"
)
>=
0
}
private
fun
isUnix
(
name
:
String
):
Boolean
{
return
name
.
indexOf
(
"nix"
)
>=
0
||
name
.
indexOf
(
"nux"
)
>=
0
||
name
.
indexOf
(
"aix"
)
>=
0
}
}
}
\ No newline at end of file
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/OpenGLApi.kt
0 → 100644
View file @
07f4a8ad
package
org.jetbrains.skiko
/**
* The minimum required OpenGL constants and functions for Skia to work.
* PS. In further development we should find a common pattern of using OpenGL,
* Vulkan, Metal and implement common interface to all graphics APIs.
*/
class
OpenGLApi
private
constructor
()
{
// OpenGL constants
val
GL_TEXTURE_2D
=
0
x0DE1
val
GL_TEXTURE_BINDING_2D
=
0
x8069
val
GL_DRAW_FRAMEBUFFER_BINDING
=
0
x8CA6
val
GL_COLOR_BUFFER_BIT
=
0
x00004000
// OpenGL functions
external
fun
glViewport
(
x
:
Int
,
y
:
Int
,
width
:
Int
,
height
:
Int
)
external
fun
glClearColor
(
r
:
Float
,
g
:
Float
,
b
:
Float
,
a
:
Float
)
external
fun
glClear
(
flags
:
Int
)
external
fun
glFinish
()
external
fun
glEnable
(
flag
:
Int
)
external
fun
glBindTexture
(
target
:
Int
,
texture
:
Int
)
external
fun
glGetIntegerv
(
pname
:
Int
):
Int
companion
object
{
private
lateinit
var
instance
:
OpenGLApi
fun
get
():
OpenGLApi
{
if
(!
this
::
instance
.
isInitialized
)
{
instance
=
OpenGLApi
()
}
return
instance
}
}
}
\ No newline at end of file
skiko/src/jvmMain/kotlin/org/jetbrains/skiko/SkiaWindow.kt
View file @
07f4a8ad
package
org.jetbrains.skiko
package
org.jetbrains.skiko
class
SkiaWindow
{
import
java.awt.event.ComponentAdapter
import
java.awt.event.ComponentEvent
import
javax.swing.JFrame
import
org.jetbrains.skija.BackendRenderTarget
import
org.jetbrains.skija.Canvas
import
org.jetbrains.skija.ColorSpace
import
org.jetbrains.skija.Context
import
org.jetbrains.skija.FramebufferFormat
import
org.jetbrains.skija.Surface
import
org.jetbrains.skija.SurfaceColorFormat
import
org.jetbrains.skija.SurfaceOrigin
private
class
SkijaState
{
var
context
:
Context
?
=
null
var
renderTarget
:
BackendRenderTarget
?
=
null
var
surface
:
Surface
?
=
null
var
canvas
:
Canvas
?
=
null
fun
clear
()
{
surface
?.
close
()
renderTarget
?.
close
()
}
}
interface
SkiaRenderer
{
fun
onInit
()
fun
onRender
(
canvas
:
Canvas
,
width
:
Int
,
height
:
Int
)
fun
onReshape
(
width
:
Int
,
height
:
Int
)
fun
onDispose
()
}
class
SkiaLayer
()
:
HardwareLayer
()
{
var
renderer
:
SkiaRenderer
?
=
null
private
val
skijaState
=
SkijaState
()
var
init
:
Boolean
=
false
public
override
fun
draw
()
{
if
(!
init
)
{
if
(
skijaState
.
context
==
null
)
{
skijaState
.
context
=
Context
.
makeGL
()
}
initSkija
()
init
=
true
}
skijaState
.
apply
{
val
gl
=
OpenGLApi
.
get
()
gl
.
glClearColor
(
1.0f
,
1.0f
,
1.0f
,
1.0f
)
gl
.
glClear
(
gl
.
GL_COLOR_BUFFER_BIT
)
canvas
!!
.
clear
(
0
xFFFFFFF
)
renderer
!!
.
onRender
(
canvas
!!
,
width
,
height
)
context
!!
.
flush
()
gl
.
glFinish
()
}
}
private
fun
initSkija
()
{
val
dpi
=
contentScale
skijaState
.
clear
()
val
gl
:
OpenGLApi
=
OpenGLApi
.
get
()
val
fbId
=
gl
.
glGetIntegerv
(
gl
.
GL_DRAW_FRAMEBUFFER_BINDING
)
skijaState
.
renderTarget
=
BackendRenderTarget
.
makeGL
(
(
width
*
dpi
).
toInt
(),
(
height
*
dpi
).
toInt
(),
0
,
8
,
fbId
,
FramebufferFormat
.
GR_GL_RGBA8
)
skijaState
.
surface
=
Surface
.
makeFromBackendRenderTarget
(
skijaState
.
context
,
skijaState
.
renderTarget
,
SurfaceOrigin
.
BOTTOM_LEFT
,
SurfaceColorFormat
.
RGBA_8888
,
ColorSpace
.
getSRGB
()
)
skijaState
.
canvas
=
skijaState
.
surface
!!
.
canvas
skijaState
.
canvas
!!
.
scale
(
dpi
,
dpi
)
}
}
class
SkiaWindow
()
:
JFrame
()
{
companion
object
{
companion
object
{
init
{
init
{
Library
.
load
(
"/"
,
"skiko"
)
Library
.
load
(
"/"
,
"skiko"
)
}
}
}
}
external
fun
nativeMethod
(
param
:
Long
):
Long
val
layer
:
SkiaLayer
}
init
{
layer
=
SkiaLayer
()
setLayout
(
null
);
add
(
layer
)
addComponentListener
(
object
:
ComponentAdapter
()
{
public
override
fun
componentResized
(
e
:
ComponentEvent
)
{
layer
.
init
=
false
layer
.
setSize
(
width
,
height
)
Engine
.
get
().
render
(
layer
)
}
})
}
}
skiko/src/jvmMain/objectiveC/macos/drawlayer.m
0 → 100644
View file @
07f4a8ad
#import "jawt.h"
#import "jawt_md.h"
#define GL_SILENCE_DEPRECATION
#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>
#import <OpenGL/gl3.h>
@interface
AWTGLLayer
:
CAOpenGLLayer
@property
jobject
windowRef
;
@property
JavaVM
*
jvm
;
@property
bool
isDrawing
;
@end
@implementation
AWTGLLayer
jobject
windowRef
;
JavaVM
*
jvm
;
-
(
id
)
init
{
self
=
[
super
init
];
if
(
self
)
{
self
.
needsDisplayOnBoundsChange
=
YES
;
self
.
asynchronous
=
NO
;
self
.
windowRef
=
NULL
;
self
.
jvm
=
NULL
;
self
.
isDrawing
=
NO
;
}
return
self
;
}
-
(
void
)
drawInCGLContext
:
(
CGLContextObj
)
ctx
pixelFormat
:
(
CGLPixelFormatObj
)
pf
forLayerTime
:
(
CFTimeInterval
)
t
displayTime
:
(
const
CVTimeStamp
*
)
ts
{
if
(
self
.
isDrawing
)
return
;
self
.
isDrawing
=
YES
;
CGLSetCurrentContext
(
ctx
);
if
(
self
.
jvm
!=
NULL
)
{
JNIEnv
*
env
;
(
*
self
.
jvm
)
->
AttachCurrentThread
(
self
.
jvm
,
(
void
**
)
&
env
,
NULL
);
jclass
wndClass
=
(
*
env
)
->
GetObjectClass
(
env
,
self
.
windowRef
);
jmethodID
drawMethod
=
(
*
env
)
->
GetMethodID
(
env
,
wndClass
,
"draw"
,
"()V"
);
if
(
NULL
==
drawMethod
)
{
NSLog
(
@"The method Window.draw() not found!"
);
return
;
}
(
*
env
)
->
CallVoidMethod
(
env
,
self
.
windowRef
,
drawMethod
);
}
[
super
drawInCGLContext
:
ctx
pixelFormat
:
pf
forLayerTime
:
t
displayTime
:
ts
];
self
.
isDrawing
=
NO
;
}
-
(
void
)
dispose
{
self
.
windowRef
=
NULL
;
self
.
jvm
=
NULL
;
}
@end
@interface
LayersSet
:
NSObject
@property
jobject
windowRef
;
@property
(
retain
,
strong
)
CALayer
*
caLayer
;
@property
(
retain
,
strong
)
AWTGLLayer
*
glLayer
;
@end
@implementation
LayersSet
jobject
windowRef
;
CALayer
*
caLayer
;
AWTGLLayer
*
glLayer
;
-
(
id
)
init
{
self
=
[
super
init
];
if
(
self
)
{
self
.
windowRef
=
NULL
;
self
.
caLayer
=
NULL
;
self
.
glLayer
=
NULL
;
}
return
self
;
}
-
(
void
)
syncSize
{
self
.
glLayer
.
bounds
=
self
.
caLayer
.
bounds
;
self
.
glLayer
.
frame
=
self
.
caLayer
.
frame
;
}
-
(
void
)
update
{
[
self
.
glLayer
performSelectorOnMainThread
:
@selector
(
setNeedsDisplay
)
withObject
:
0
waitUntilDone
:
NO
];
[
self
.
glLayer
performSelectorOnMainThread
:
@selector
(
displayIfNeeded
)
withObject
:
0
waitUntilDone
:
NO
];
}
-
(
void
)
dispose
{
[
self
.
glLayer
dispose
];
self
.
glLayer
=
NULL
;
self
.
caLayer
=
NULL
;
}
@end
NSMutableSet
*
windowsSet
=
nil
;
LayersSet
*
findByObject
(
JNIEnv
*
env
,
jobject
object
)
{
for
(
LayersSet
*
value
in
windowsSet
)
{
if
((
*
env
)
->
IsSameObject
(
env
,
object
,
value
.
windowRef
)
==
JNI_TRUE
)
{
return
value
;
}
}
NSLog
(
@"The set does not contain this window."
);
return
NULL
;
}
extern
jboolean
Skiko_GetAWT
(
JNIEnv
*
env
,
JAWT
*
awt
);
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_updateLayer
(
JNIEnv
*
env
,
jobject
window
)
{
if
(
windowsSet
!=
nil
)
{
LayersSet
*
layer
=
findByObject
(
env
,
window
);
if
(
layer
!=
NULL
)
{
if
(
layer
.
caLayer
==
NULL
&&
layer
.
glLayer
==
NULL
)
{
(
*
env
)
->
DeleteGlobalRef
(
env
,
layer
.
windowRef
);
layer
.
windowRef
=
NULL
;
[
windowsSet
removeObject
:
layer
];
return
;
}
[
layer
syncSize
];
return
;
}
}
else
{
windowsSet
=
[[
NSMutableSet
alloc
]
init
];
}
JAWT
awt
;
JAWT_DrawingSurface
*
ds
=
NULL
;
JAWT_DrawingSurfaceInfo
*
dsi
=
NULL
;
CGLPixelFormatObj
pixFormatObj
=
NULL
;
CGLContextObj
context
;
jboolean
result
=
JNI_FALSE
;
jint
lock
=
0
;
NSObject
<
JAWT_SurfaceLayers
>*
dsi_mac
=
NULL
;
awt
.
version
=
JAWT_VERSION_9
;
result
=
Skiko_GetAWT
(
env
,
&
awt
);
assert
(
result
!=
JNI_FALSE
);
JavaVM
*
jvm
;
(
*
env
)
->
GetJavaVM
(
env
,
&
jvm
);
ds
=
awt
.
GetDrawingSurface
(
env
,
window
);
assert
(
ds
!=
NULL
);
lock
=
ds
->
Lock
(
ds
);
assert
((
lock
&
JAWT_LOCK_ERROR
)
==
0
);
dsi
=
ds
->
GetDrawingSurfaceInfo
(
ds
);
if
(
dsi
!=
NULL
)
{
dsi_mac
=
(
__bridge
NSObject
<
JAWT_SurfaceLayers
>
*
)
dsi
->
platformInfo
;
LayersSet
*
layersSet
=
[[
LayersSet
alloc
]
init
];
[
windowsSet
addObject
:
layersSet
];
layersSet
.
caLayer
=
[
dsi_mac
windowLayer
];
NSScreen
*
screen
=
[
NSScreen
mainScreen
];
float
scaleFactor
=
screen
.
backingScaleFactor
;
layersSet
.
caLayer
.
contentsScale
=
scaleFactor
;
layersSet
.
glLayer
=
[
AWTGLLayer
new
];
[
layersSet
.
caLayer
addSublayer
:
layersSet
.
glLayer
];
layersSet
.
glLayer
.
backgroundColor
=
CGColorCreateSRGB
(
1
.
0
f
,
1
.
0
f
,
1
.
0
f
,
1
.
0
f
);
layersSet
.
glLayer
.
contentsScale
=
scaleFactor
;
jobject
windowRef
=
(
*
env
)
->
NewGlobalRef
(
env
,
window
);
[
layersSet
.
glLayer
setJvm
:
jvm
];
[
layersSet
.
glLayer
setWindowRef
:
windowRef
];
[
layersSet
setWindowRef
:
windowRef
];
ds
->
FreeDrawingSurfaceInfo
(
dsi
);
ds
->
Unlock
(
ds
);
awt
.
FreeDrawingSurface
(
ds
);
}
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_redrawLayer
(
JNIEnv
*
env
,
jobject
window
)
{
LayersSet
*
layer
=
findByObject
(
env
,
window
);
if
(
layer
!=
NULL
)
{
[
layer
update
];
}
}
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_disposeLayer
(
JNIEnv
*
env
,
jobject
window
)
{
LayersSet
*
layer
=
findByObject
(
env
,
window
);
if
(
layer
!=
NULL
)
{
[
layer
dispose
];
}
}
JNIEXPORT
jfloat
JNICALL
Java_org_jetbrains_skiko_HardwareLayer_getContentScale
(
JNIEnv
*
env
,
jobject
window
)
{
LayersSet
*
layer
=
findByObject
(
env
,
window
);
if
(
layer
!=
NULL
)
{
return
[
layer
.
glLayer
contentsScale
];
}
return
1
.
0
f
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment