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
8aff350d
Unverified
Commit
8aff350d
authored
Dec 01, 2021
by
Aleksandr Veselov
Committed by
GitHub
Dec 01, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement Shaper::shape with RunHandler (#415)
parent
7ce02618
Changes
22
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
951 additions
and
95 deletions
+951
-95
Native.kt
...o/src/commonMain/kotlin/org/jetbrains/skia/impl/Native.kt
+6
-0
FontMgrRunIterator.kt
...in/kotlin/org/jetbrains/skia/shaper/FontMgrRunIterator.kt
+13
-8
HbIcuScriptRunIterator.kt
...otlin/org/jetbrains/skia/shaper/HbIcuScriptRunIterator.kt
+6
-6
IcuBidiRunIterator.kt
...in/kotlin/org/jetbrains/skia/shaper/IcuBidiRunIterator.kt
+6
-6
ManagedRunIterator.kt
...in/kotlin/org/jetbrains/skia/shaper/ManagedRunIterator.kt
+7
-7
RunInfo.kt
...rc/commonMain/kotlin/org/jetbrains/skia/shaper/RunInfo.kt
+3
-2
Shaper.kt
...src/commonMain/kotlin/org/jetbrains/skia/shaper/Shaper.kt
+68
-23
ShaperTest.kt
skiko/src/commonTest/kotlin/org/jetbrains/skia/ShaperTest.kt
+91
-6
Actuals.js.kt
skiko/src/jsMain/kotlin/org/jetbrains/skia/Actuals.js.kt
+9
-1
Native.js.kt
skiko/src/jsMain/kotlin/org/jetbrains/skia/impl/Native.js.kt
+16
-6
FontMgrRunIterator.cc
skiko/src/jvmMain/cpp/common/shaper/FontMgrRunIterator.cc
+8
-6
Shaper.cc
skiko/src/jvmMain/cpp/common/shaper/Shaper.cc
+1
-1
interop.cc
skiko/src/jvmMain/cpp/common/shaper/interop.cc
+1
-1
Native.jvm.kt
.../src/jvmMain/kotlin/org/jetbrains/skia/impl/Native.jvm.kt
+6
-0
Shaper.jvm.kt
...rc/jvmMain/kotlin/org/jetbrains/skia/shaper/Shaper.jvm.kt
+34
-0
common.h
skiko/src/nativeJsMain/cpp/common.h
+12
-1
common_interop.cc
skiko/src/nativeJsMain/cpp/common_interop.cc
+38
-1
FontMgrRunIterator.cc
skiko/src/nativeJsMain/cpp/shaper/FontMgrRunIterator.cc
+27
-3
Shaper.cc
skiko/src/nativeJsMain/cpp/shaper/Shaper.cc
+306
-2
Shaper.nativejs.kt
...sMain/kotlin/org/jetbrains/skia/shaper/Shaper.nativejs.kt
+240
-0
Actuals.native.kt
...rc/nativeMain/kotlin/org/jetbrains/skia/Actuals.native.kt
+21
-1
Native.native.kt
...ativeMain/kotlin/org/jetbrains/skia/impl/Native.native.kt
+32
-14
No files found.
skiko/src/commonMain/kotlin/org/jetbrains/skia/impl/Native.kt
View file @
8aff350d
...
...
@@ -45,10 +45,16 @@ expect class InteropScope() {
// Callbacks
fun
callback
(
callback
:
(()
->
Unit
)?):
InteropPointer
fun
intCallback
(
callback
:
(()
->
Int
)?):
InteropPointer
fun
nativePointerCallback
(
callback
:
(()
->
NativePointer
)?):
InteropPointer
fun
interopPointerCallback
(
callback
:
(()
->
InteropPointer
)?):
InteropPointer
fun
booleanCallback
(
callback
:
(()
->
Boolean
)?):
InteropPointer
// Virtual methods
fun
virtual
(
method
:
()
->
Unit
):
InteropPointer
fun
virtualInt
(
method
:
()
->
Int
):
InteropPointer
fun
virtualNativePointer
(
method
:
()
->
NativePointer
):
InteropPointer
fun
virtualInteropPointer
(
method
:
()
->
InteropPointer
):
InteropPointer
fun
virtualBoolean
(
method
:
()
->
Boolean
):
InteropPointer
fun
release
()
...
...
skiko/src/commonMain/kotlin/org/jetbrains/skia/shaper/FontMgrRunIterator.kt
View file @
8aff350d
@file
:
Suppress
(
"NESTED_EXTERNAL_DECLARATION"
)
package
org.jetbrains.skia.shaper
import
org.jetbrains.skia.impl.Library.Companion.staticLoad
import
org.jetbrains.skia.*
import
org.jetbrains.skia.impl.Stats
import
org.jetbrains.skia.impl.reachabilityBarrier
import
org.jetbrains.skia.ExternalSymbolName
import
org.jetbrains.skia.Font
import
org.jetbrains.skia.FontMgr
import
org.jetbrains.skia.ManagedString
import
org.jetbrains.skia.impl.Library.Companion.staticLoad
import
org.jetbrains.skia.impl.NativePointer
import
org.jetbrains.skia.impl.Stats
import
org.jetbrains.skia.impl.getPtr
import
org.jetbrains.skia.impl.reachabilityBarrier
class
FontMgrRunIterator
(
text
:
ManagedString
?,
manageText
:
Boolean
,
font
:
Font
?,
opts
:
ShapingOptions
)
:
ManagedRunIterator
<
FontRun
?
>(
_nMake
(
getPtr
(
text
),
getPtr
(
font
),
opts
),
text
,
manageText
_nMake
(
getPtr
(
text
),
getPtr
(
font
),
getPtr
(
opts
.
fontMgr
),
opts
.
_booleanPropsToInt
()
),
text
,
manageText
)
{
companion
object
{
init
{
...
...
@@ -19,6 +21,9 @@ class FontMgrRunIterator(text: ManagedString?, manageText: Boolean, font: Font?,
}
}
private
val
_font
:
Font
?
=
font
private
val
_fontMgr
:
FontMgr
?
=
opts
.
fontMgr
constructor
(
text
:
String
?,
font
:
Font
?,
opts
:
ShapingOptions
)
:
this
(
ManagedString
(
text
),
true
,
font
,
opts
)
constructor
(
text
:
String
?,
font
:
Font
?)
:
this
(
ManagedString
(
text
),
true
,
font
,
ShapingOptions
.
DEFAULT
)
...
...
@@ -43,8 +48,8 @@ class FontMgrRunIterator(text: ManagedString?, manageText: Boolean, font: Font?,
}
}
@ExternalSymbolName
(
"org_jetbrains_skia_FontMgrRunIterator__1nMake"
)
private
external
fun
_nMake
(
textPtr
:
NativePointer
,
fontPtr
:
NativePointer
,
opts
:
ShapingOptions
?
):
NativePointer
@ExternalSymbolName
(
"org_jetbrains_skia_
shaper_
FontMgrRunIterator__1nMake"
)
private
external
fun
_nMake
(
textPtr
:
NativePointer
,
fontPtr
:
NativePointer
,
fontMgrPtr
:
NativePointer
,
optsBooleanProps
:
Int
):
NativePointer
@ExternalSymbolName
(
"org_jetbrains_skia_FontMgrRunIterator__1nGetCurrentFont"
)
@ExternalSymbolName
(
"org_jetbrains_skia_
shaper_
FontMgrRunIterator__1nGetCurrentFont"
)
private
external
fun
_nGetCurrentFont
(
ptr
:
NativePointer
):
NativePointer
skiko/src/commonMain/kotlin/org/jetbrains/skia/shaper/HbIcuScriptRunIterator.kt
View file @
8aff350d
@file
:
Suppress
(
"NESTED_EXTERNAL_DECLARATION"
)
package
org.jetbrains.skia.shaper
import
org.jetbrains.skia.impl.Library.Companion.staticLoad
import
org.jetbrains.skia.ManagedString
import
org.jetbrains.skia.impl.Stats
import
org.jetbrains.skia.impl.reachabilityBarrier
import
org.jetbrains.skia.ExternalSymbolName
import
org.jetbrains.skia.ManagedString
import
org.jetbrains.skia.impl.Library.Companion.staticLoad
import
org.jetbrains.skia.impl.NativePointer
import
org.jetbrains.skia.impl.Stats
import
org.jetbrains.skia.impl.getPtr
import
org.jetbrains.skia.impl.reachabilityBarrier
class
HbIcuScriptRunIterator
(
text
:
ManagedString
?,
manageText
:
Boolean
)
:
ManagedRunIterator
<
ScriptRun
?
>(
_nMake
(
...
...
@@ -42,8 +42,8 @@ class HbIcuScriptRunIterator(text: ManagedString?, manageText: Boolean) : Manage
}
@ExternalSymbolName
(
"org_jetbrains_skia_HbIcuScriptRunIterator__1nMake"
)
@ExternalSymbolName
(
"org_jetbrains_skia_
shaper_
HbIcuScriptRunIterator__1nMake"
)
private
external
fun
_nMake
(
textPtr
:
NativePointer
):
NativePointer
@ExternalSymbolName
(
"org_jetbrains_skia_HbIcuScriptRunIterator__1nGetCurrentScriptTag"
)
@ExternalSymbolName
(
"org_jetbrains_skia_
shaper_
HbIcuScriptRunIterator__1nGetCurrentScriptTag"
)
private
external
fun
_nGetCurrentScriptTag
(
ptr
:
NativePointer
):
Int
skiko/src/commonMain/kotlin/org/jetbrains/skia/shaper/IcuBidiRunIterator.kt
View file @
8aff350d
@file
:
Suppress
(
"NESTED_EXTERNAL_DECLARATION"
)
package
org.jetbrains.skia.shaper
import
org.jetbrains.skia.impl.Library.Companion.staticLoad
import
org.jetbrains.skia.ManagedString
import
org.jetbrains.skia.impl.Stats
import
org.jetbrains.skia.impl.reachabilityBarrier
import
org.jetbrains.skia.ExternalSymbolName
import
org.jetbrains.skia.ManagedString
import
org.jetbrains.skia.impl.Library.Companion.staticLoad
import
org.jetbrains.skia.impl.NativePointer
import
org.jetbrains.skia.impl.Stats
import
org.jetbrains.skia.impl.getPtr
import
org.jetbrains.skia.impl.reachabilityBarrier
class
IcuBidiRunIterator
(
text
:
ManagedString
?,
manageText
:
Boolean
,
bidiLevel
:
Int
)
:
ManagedRunIterator
<
BidiRun
?
>(
_nMake
(
getPtr
(
text
),
bidiLevel
),
text
,
manageText
...
...
@@ -39,8 +39,8 @@ class IcuBidiRunIterator(text: ManagedString?, manageText: Boolean, bidiLevel: I
}
}
@ExternalSymbolName
(
"org_jetbrains_skia_IcuBidiRunIterator__1nMake"
)
@ExternalSymbolName
(
"org_jetbrains_skia_
shaper_
IcuBidiRunIterator__1nMake"
)
private
external
fun
_nMake
(
textPtr
:
NativePointer
,
bidiLevel
:
Int
):
NativePointer
@ExternalSymbolName
(
"org_jetbrains_skia_IcuBidiRunIterator__1nGetCurrentLevel"
)
@ExternalSymbolName
(
"org_jetbrains_skia_
shaper_
IcuBidiRunIterator__1nGetCurrentLevel"
)
private
external
fun
_nGetCurrentLevel
(
ptr
:
NativePointer
):
Int
skiko/src/commonMain/kotlin/org/jetbrains/skia/shaper/ManagedRunIterator.kt
View file @
8aff350d
@file
:
Suppress
(
"NESTED_EXTERNAL_DECLARATION"
)
package
org.jetbrains.skia.shaper
import
org.jetbrains.skia.
impl.Library.Companion.staticLoad
import
org.jetbrains.skia.
ExternalSymbolName
import
org.jetbrains.skia.ManagedString
import
org.jetbrains.skia.impl.Library.Companion.staticLoad
import
org.jetbrains.skia.impl.Managed
import
org.jetbrains.skia.impl.reachabilityBarrier
import
org.jetbrains.skia.ExternalSymbolName
import
org.jetbrains.skia.impl.NativePointer
import
org.jetbrains.skia.impl.getPtr
import
org.jetbrains.skia.impl.reachabilityBarrier
abstract
class
ManagedRunIterator
<
T
>
internal
constructor
(
ptr
:
NativePointer
,
...
...
@@ -53,14 +53,14 @@ abstract class ManagedRunIterator<T> internal constructor(
}
@ExternalSymbolName
(
"org_jetbrains_skia_ManagedRunIterator__1nGetFinalizer"
)
@ExternalSymbolName
(
"org_jetbrains_skia_
shaper_
ManagedRunIterator__1nGetFinalizer"
)
private
external
fun
_nGetFinalizer
():
NativePointer
@ExternalSymbolName
(
"org_jetbrains_skia_ManagedRunIterator__1nConsume"
)
@ExternalSymbolName
(
"org_jetbrains_skia_
shaper_
ManagedRunIterator__1nConsume"
)
internal
external
fun
_nConsume
(
ptr
:
NativePointer
)
@ExternalSymbolName
(
"org_jetbrains_skia_ManagedRunIterator__1nGetEndOfCurrentRun"
)
@ExternalSymbolName
(
"org_jetbrains_skia_
shaper_
ManagedRunIterator__1nGetEndOfCurrentRun"
)
private
external
fun
_nGetEndOfCurrentRun
(
ptr
:
NativePointer
,
textPtr
:
NativePointer
):
Int
@ExternalSymbolName
(
"org_jetbrains_skia_ManagedRunIterator__1nIsAtEnd"
)
@ExternalSymbolName
(
"org_jetbrains_skia_
shaper_
ManagedRunIterator__1nIsAtEnd"
)
private
external
fun
_nIsAtEnd
(
ptr
:
NativePointer
):
Boolean
skiko/src/commonMain/kotlin/org/jetbrains/skia/shaper/RunInfo.kt
View file @
8aff350d
package
org.jetbrains.skia.shaper
import
org.jetbrains.skia.*
import
org.jetbrains.skia.Font
import
org.jetbrains.skia.Point
import
org.jetbrains.skia.impl.Native
import
org.jetbrains.skia.impl.NativePointer
class
RunInfo
(
var
_fontPtr
:
NativePointer
,
val
bidiLevel
:
Int
,
val
advanceX
:
Float
,
val
advanceY
:
Float
,
val
glyphCount
:
NativePointer
,
var
_fontPtr
:
NativePointer
,
val
bidiLevel
:
Int
,
val
advanceX
:
Float
,
val
advanceY
:
Float
,
val
glyphCount
:
Int
,
/**
* WARN does not work in Shaper.makeCoreText https://bugs.chromium.org/p/skia/issues/detail?id=10899
*/
...
...
skiko/src/commonMain/kotlin/org/jetbrains/skia/shaper/Shaper.kt
View file @
8aff350d
@file
:
Suppress
(
"NESTED_EXTERNAL_DECLARATION"
)
package
org.jetbrains.skia.shaper
import
org.jetbrains.skia.impl.Library.Companion.staticLoad
import
org.jetbrains.skia.*
import
org.jetbrains.skia.ExternalSymbolName
import
org.jetbrains.skia.FontFeature.Companion.arrayOfFontFeaturesToInterop
import
org.jetbrains.skia.impl.*
import
org.jetbrains.skia.impl.Library.Companion.staticLoad
/**
* Shapes text using HarfBuzz and places the shaped text into a
...
...
@@ -185,21 +184,7 @@ class Shaper internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerH
runHandler
:
RunHandler
):
Shaper
{
Stats
.
onNativeCall
()
interopScope
{
_nShape
(
_ptr
,
getPtr
(
textUtf8
),
fontIter
,
bidiIter
,
scriptIter
,
langIter
,
optsFeaturesLen
=
opts
.
features
?.
size
?:
0
,
optsFeaturesIntArray
=
arrayOfFontFeaturesToInterop
(
opts
.
features
),
optsBooleanProps
=
opts
.
_booleanPropsToInt
(),
width
=
width
,
runHandler
=
runHandler
)
}
doShape
(
textUtf8
,
fontIter
,
bidiIter
,
scriptIter
,
langIter
,
opts
,
width
,
runHandler
)
return
this
}
...
...
@@ -233,6 +218,17 @@ class Shaper internal constructor(ptr: NativePointer) : Managed(ptr, _FinalizerH
}
}
internal
expect
fun
Shaper
.
doShape
(
textUtf8
:
ManagedString
,
fontIter
:
Iterator
<
FontRun
?
>,
bidiIter
:
Iterator
<
BidiRun
?
>,
scriptIter
:
Iterator
<
ScriptRun
?
>,
langIter
:
Iterator
<
LanguageRun
?
>,
opts
:
ShapingOptions
,
width
:
Float
,
runHandler
:
RunHandler
)
@ExternalSymbolName
(
"org_jetbrains_skia_shaper_Shaper__1nGetFinalizer"
)
private
external
fun
Shaper_nGetFinalizer
():
NativePointer
...
...
@@ -280,16 +276,65 @@ private external fun _nShapeLine(
):
NativePointer
@ExternalSymbolName
(
"org_jetbrains_skia_shaper_Shaper__1nShape"
)
private
external
fun
_nShape
(
internal
external
fun
Shaper
_nShape
(
ptr
:
NativePointer
,
textPtr
:
NativePointer
,
fontIter
:
I
terator
<
FontRun
?
>?
,
bidiIter
:
I
terator
<
BidiRun
?
>?
,
scriptIter
:
I
terator
<
ScriptRun
?
>?
,
langIter
:
I
terator
<
LanguageRun
?
>?
,
fontIter
:
I
nteropPointer
,
bidiIter
:
I
nteropPointer
,
scriptIter
:
I
nteropPointer
,
langIter
:
I
nteropPointer
,
optsFeaturesLen
:
Int
,
optsFeaturesIntArray
:
InteropPointer
,
optsBooleanProps
:
Int
,
width
:
Float
,
runHandler
:
RunHandler
?
runHandler
:
InteropPointer
)
// Native/JS only
@ExternalSymbolName
(
"org_jetbrains_skia_shaper_Shaper_RunIterator_1nGetFinalizer"
)
internal
external
fun
RunIterator_nGetFinalizer
():
NativePointer
@ExternalSymbolName
(
"org_jetbrains_skia_shaper_Shaper_RunIterator_1nCreateRunIterator"
)
internal
external
fun
RunIterator_nCreateRunIterator
(
type
:
Int
,
textPtr
:
NativePointer
):
NativePointer
@ExternalSymbolName
(
"org_jetbrains_skia_shaper_Shaper_RunIterator_1nInitRunIterator"
)
internal
external
fun
RunIterator_nInitRunIterator
(
ptr
:
NativePointer
,
type
:
Int
,
onConsume
:
InteropPointer
,
onEndOfCurrentRun
:
InteropPointer
,
onAtEnd
:
InteropPointer
,
onCurrent
:
InteropPointer
)
@ExternalSymbolName
(
"org_jetbrains_skia_shaper_Shaper_RunHandler_1nCreate"
)
internal
external
fun
RunHandler_nCreate
():
NativePointer
@ExternalSymbolName
(
"org_jetbrains_skia_shaper_Shaper_RunHandler_1nGetFinalizer"
)
internal
external
fun
RunHandler_nGetFinalizer
():
NativePointer
@ExternalSymbolName
(
"org_jetbrains_skia_shaper_Shaper_RunHandler_1nInit"
)
internal
external
fun
RunHandler_nInit
(
ptr
:
NativePointer
,
onBeginLine
:
InteropPointer
,
onRunInfo
:
InteropPointer
,
onCommitRunInfo
:
InteropPointer
,
onRunOffset
:
InteropPointer
,
onCommitRun
:
InteropPointer
,
onCommitLine
:
InteropPointer
)
@ExternalSymbolName
(
"org_jetbrains_skia_shaper_Shaper_RunHandler_1nGetGlyphs"
)
internal
external
fun
RunHandler_nGetGlyphs
(
ptr
:
NativePointer
,
result
:
InteropPointer
)
@ExternalSymbolName
(
"org_jetbrains_skia_shaper_Shaper_RunHandler_1nGetClusters"
)
internal
external
fun
RunHandler_nGetClusters
(
ptr
:
NativePointer
,
result
:
InteropPointer
)
@ExternalSymbolName
(
"org_jetbrains_skia_shaper_Shaper_RunHandler_1nGetPositions"
)
internal
external
fun
RunHandler_nGetPositions
(
ptr
:
NativePointer
,
result
:
InteropPointer
)
@ExternalSymbolName
(
"org_jetbrains_skia_shaper_Shaper_RunHandler_1nSetOffset"
)
internal
external
fun
RunHandler_nSetOffset
(
ptr
:
NativePointer
,
x
:
Float
,
y
:
Float
)
@ExternalSymbolName
(
"org_jetbrains_skia_shaper_Shaper_RunHandler_1nGetRunInfo"
)
internal
external
fun
RunHandler_nGetRunInfo
(
ptr
:
NativePointer
,
result
:
InteropPointer
):
NativePointer
skiko/src/commonTest/kotlin/org/jetbrains/skia/ShaperTest.kt
View file @
8aff350d
package
org.jetbrains.skia
import
org.jetbrains.skia.shaper.RunHandler
import
org.jetbrains.skia.shaper.RunInfo
import
org.jetbrains.skia.shaper.Shaper
import
org.jetbrains.skia.shaper.ShapingOptions
import
org.jetbrains.skia.tests.assertContentCloseEnough
import
org.jetbrains.skia.tests.makeFromResource
import
org.jetbrains.skiko.tests.SkipJsTarget
import
org.jetbrains.skiko.tests.SkipNativeTarget
import
org.jetbrains.skiko.tests.runTest
import
kotlin.test.Test
import
kotlin.test.assertContentEquals
import
kotlin.test.assertEquals
import
kotlin.test.assertNotEquals
import
kotlin.test.*
class
ShaperTest
{
...
...
@@ -45,4 +44,90 @@ class ShaperTest {
)
}
@Test
fun
canShapeWithRunHandler
()
=
runTest
{
val
callCount
=
object
{
var
beginLine
=
0
var
runInfo
=
0
var
commitRunInfo
=
0
var
runOffset
=
0
var
commitRun
=
0
var
commitLine
=
0
}
data class
CommitRunArgs
(
val
glyphs
:
ShortArray
?,
val
positions
:
Array
<
Point
?>?,
val
clusters
:
IntArray
?
)
val
commitRuns
=
mutableListOf
<
CommitRunArgs
>()
val
runInfos
=
mutableListOf
<
RunInfo
?>()
Shaper
.
make
().
shape
(
text
=
"text\ntext text\r\ntext"
,
font
=
fontInter36
(),
opts
=
ShapingOptions
.
DEFAULT
,
width
=
100f
,
runHandler
=
object
:
RunHandler
{
override
fun
beginLine
()
{
callCount
.
beginLine
+=
1
}
override
fun
runInfo
(
info
:
RunInfo
?)
{
callCount
.
runInfo
+=
1
runInfos
.
add
(
info
)
}
override
fun
commitRunInfo
()
{
callCount
.
commitRunInfo
+=
1
}
override
fun
runOffset
(
info
:
RunInfo
?):
Point
{
callCount
.
runOffset
+=
1
return
Point
.
ZERO
}
override
fun
commitRun
(
info
:
RunInfo
?,
glyphs
:
ShortArray
?,
positions
:
Array
<
Point
?
>?,
clusters
:
IntArray
?
)
{
callCount
.
commitRun
+=
1
commitRuns
.
add
(
CommitRunArgs
(
glyphs
,
positions
,
clusters
))
}
override
fun
commitLine
()
{
callCount
.
commitLine
+=
1
}
}
)
assertEquals
(
4
,
callCount
.
beginLine
)
assertEquals
(
4
,
callCount
.
runInfo
)
assertEquals
(
4
,
callCount
.
commitRunInfo
)
assertEquals
(
4
,
callCount
.
runOffset
)
assertEquals
(
4
,
callCount
.
commitRun
)
assertEquals
(
4
,
callCount
.
commitLine
)
assertTrue
(
runInfos
[
2
]
!!
.
advance
.
x
>
80.0f
)
assertEquals
(
10
,
runInfos
[
2
]
?.
rangeBegin
)
assertEquals
(
16
,
runInfos
[
2
]
?.
rangeEnd
)
assertEquals
(
6
,
runInfos
[
2
]
?.
glyphCount
)
// For some reasons \r and \n are handled differently on macos and ios, so they are ignored during tests
assertContentEquals
(
intArrayOf
(
10
,
11
,
12
,
13
,
14
,
15
),
commitRuns
[
2
].
clusters
)
assertContentEquals
(
shortArrayOf
(
882
,
611
,
943
,
882
),
commitRuns
[
2
].
glyphs
?.
sliceArray
(
0
..
3
))
@Suppress
(
"UNCHECKED_CAST"
)
assertContentCloseEnough
(
arrayOf
(
Point
(
0.0f
,
0.0f
),
Point
(
12.795441f
,
0.0f
),
Point
(
33.284073f
,
0.0f
),
Point
(
52.284073f
,
0.0f
),
Point
(
65.28407f
,
0.0f
)
),
commitRuns
[
2
].
positions
!!
.
sliceArray
(
0
..
4
)
as
Array
<
Point
>,
0.01f
)
}
}
skiko/src/jsMain/kotlin/org/jetbrains/skia/Actuals.js.kt
View file @
8aff350d
package
org.jetbrains.skia
import
kotlinx.browser.window
actual
abstract
class
OutputStream
actual
fun
<
R
>
commonSynchronized
(
lock
:
Any
,
block
:
()
->
R
)
{
...
...
@@ -27,7 +29,13 @@ actual class Matcher constructor(private val regex: Regex, private val input: Ch
actual
fun
matches
():
Boolean
=
matches
}
actual
fun
defaultLanguageTag
():
String
=
TODO
()
@Suppress
(
"RedundantNullableReturnType"
)
val
LANG
:
String
by
lazy
{
val
lang
:
String
?
=
window
.
navigator
.
language
if
(
lang
==
null
||
lang
.
isEmpty
())
{
"en-US"
}
else
{
lang
}
}
actual
fun
defaultLanguageTag
():
String
=
LANG
actual
fun
compilePattern
(
regex
:
String
):
Pattern
=
Pattern
(
regex
)
...
...
skiko/src/jsMain/kotlin/org/jetbrains/skia/impl/Native.js.kt
View file @
8aff350d
...
...
@@ -195,14 +195,19 @@ actual class InteropScope actual constructor() {
return
toInterop
(
interopPointers
.
toIntArray
())
}
actual
fun
booleanCallback
(
callback
:
(()
->
Boolean
)?):
InteropPointer
{
private
fun
<
T
>
callbackImpl
(
callback
:
(()
->
T
)?):
InteropPointer
{
if
(
callback
==
null
)
{
return
0
}
initCallbacks
()
val
data
=
CallbackData
<
Boolean
>(
null
)
val
data
=
CallbackData
<
T
>(
null
)
return
_registerCallback
({
data
.
value
=
callback
()
},
data
,
global
=
false
)
}
actual
fun
booleanCallback
(
callback
:
(()
->
Boolean
)?)
=
callbackImpl
(
callback
)
actual
fun
intCallback
(
callback
:
(()
->
Int
)?)
=
callbackImpl
(
callback
)
actual
fun
nativePointerCallback
(
callback
:
(()
->
NativePointer
)?)
=
callbackImpl
(
callback
)
actual
fun
interopPointerCallback
(
callback
:
(()
->
InteropPointer
)?)
=
callbackImpl
(
callback
)
actual
fun
callback
(
callback
:
(()
->
Unit
)?):
InteropPointer
{
if
(
callback
==
null
)
{
return
0
}
initCallbacks
()
...
...
@@ -210,14 +215,19 @@ actual class InteropScope actual constructor() {
return
_registerCallback
({
callback
()
},
null
,
global
=
false
)
}
private
fun
<
T
>
virtualImpl
(
method
:
()
->
T
):
InteropPointer
{
val
data
=
CallbackData
<
T
>(
null
)
return
_registerCallback
({
data
.
value
=
method
()
},
data
,
global
=
true
)
}
actual
fun
virtual
(
method
:
()
->
Unit
):
InteropPointer
{
return
_registerCallback
({
method
()
},
null
,
global
=
true
)
}
actual
fun
virtualBoolean
(
method
:
()
->
Boolean
)
:
InteropPointer
{
val
data
=
CallbackData
<
Boolean
>(
null
)
return
_registerCallback
({
data
.
value
=
method
()
},
data
,
global
=
true
);
}
actual
fun
virtualBoolean
(
method
:
()
->
Boolean
)
=
virtualImpl
(
method
)
actual
fun
virtualInt
(
method
:
()
->
Int
)
=
virtualImpl
(
method
)
actual
fun
virtualNativePointer
(
method
:
()
->
NativePointer
)
=
virtualImpl
(
method
)
actual
fun
virtualInteropPointer
(
method
:
()
->
InteropPointer
)
=
virtualImpl
(
method
)
actual
fun
release
()
{
elements
.
forEach
{
...
...
skiko/src/jvmMain/cpp/common/shaper/FontMgrRunIterator.cc
View file @
8aff350d
...
...
@@ -6,24 +6,26 @@
#include "SkShaper.h"
extern
"C"
JNIEXPORT
jlong
JNICALL
Java_org_jetbrains_skia_shaper_FontMgrRunIteratorKt__1nMake
(
JNIEnv
*
env
,
jclass
jclass
,
jlong
textPtr
,
jlong
fontPtr
,
jobject
opt
s
)
{
(
JNIEnv
*
env
,
jclass
jclass
,
jlong
textPtr
,
jlong
fontPtr
,
jobject
fontMgrPtr
,
jint
optsBooleanProp
s
)
{
SkString
*
text
=
reinterpret_cast
<
SkString
*>
(
static_cast
<
uintptr_t
>
(
textPtr
));
SkFont
*
font
=
reinterpret_cast
<
SkFont
*>
(
static_cast
<
uintptr_t
>
(
fontPtr
));
jobject
fontMgrObj
=
env
->
GetObjectField
(
opts
,
skija
::
shaper
::
ShapingOptions
::
_fontMgr
);
sk_sp
<
SkFontMgr
>
fontMgr
=
fontMgrObj
==
nullptr
sk_sp
<
SkFontMgr
>
fontMgr
=
fontMgrPtr
==
nullptr
?
SkFontMgr
::
RefDefault
()
:
sk_ref_sp
(
reinterpret_cast
<
SkFontMgr
*>
(
skija
::
impl
::
Native
::
fromJava
(
env
,
fontMgr
Obj
,
skija
::
FontMgr
::
cls
)));
:
sk_ref_sp
(
reinterpret_cast
<
SkFontMgr
*>
(
skija
::
impl
::
Native
::
fromJava
(
env
,
fontMgr
Ptr
,
skija
::
FontMgr
::
cls
)));
std
::
shared_ptr
<
UBreakIterator
>
graphemeIter
=
skija
::
shaper
::
graphemeBreakIterator
(
*
text
);
if
(
!
graphemeIter
)
return
0
;
bool
approximatePunctuation
=
(
optsBooleanProps
&
0x01
)
!=
0
;
bool
approximateSpaces
=
(
optsBooleanProps
&
0x02
)
!=
0
;
auto
instance
=
new
FontRunIterator
(
text
->
c_str
(),
text
->
size
(),
*
font
,
fontMgr
,
graphemeIter
,
env
->
GetBooleanField
(
opts
,
skija
::
shaper
::
ShapingOptions
::
_approximateSpaces
)
,
env
->
GetBooleanField
(
opts
,
skija
::
shaper
::
ShapingOptions
::
_approximatePunctuation
)
approximateSpaces
,
approximatePunctuation
);
return
reinterpret_cast
<
jlong
>
(
instance
);
}
...
...
skiko/src/jvmMain/cpp/common/shaper/Shaper.cc
View file @
8aff350d
...
...
@@ -335,7 +335,7 @@ private:
std
::
vector
<
jint
>
fClusters
;
};
extern
"C"
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skia_shaper_ShaperKt__1nShape
extern
"C"
JNIEXPORT
void
JNICALL
Java_org_jetbrains_skia_shaper_ShaperKt_
Shaper
_1nShape
(
JNIEnv
*
env
,
jclass
jclass
,
jlong
ptr
,
jlong
textPtr
,
jobject
fontRunIterObj
,
jobject
bidiRunIterObj
,
jobject
scriptRunIterObj
,
jobject
languageRunIterObj
,
jint
optsFeaturesLen
,
jintArray
optsFeatures
,
jint
optsBooleanProps
,
jfloat
width
,
jobject
runHandlerObj
)
{
SkShaper
*
instance
=
reinterpret_cast
<
SkShaper
*>
(
static_cast
<
uintptr_t
>
(
ptr
));
...
...
skiko/src/jvmMain/cpp/common/shaper/interop.cc
View file @
8aff350d
...
...
@@ -113,7 +113,7 @@ namespace skija {
void
onLoad
(
JNIEnv
*
env
)
{
jclass
local
=
env
->
FindClass
(
"org/jetbrains/skia/shaper/RunInfo"
);
cls
=
static_cast
<
jclass
>
(
env
->
NewGlobalRef
(
local
));
ctor
=
env
->
GetMethodID
(
cls
,
"<init>"
,
"(JIFF
J
II)V"
);
ctor
=
env
->
GetMethodID
(
cls
,
"<init>"
,
"(JIFF
I
II)V"
);
_fontPtr
=
env
->
GetFieldID
(
cls
,
"_fontPtr"
,
"J"
);
}
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skia/impl/Native.jvm.kt
View file @
8aff350d
...
...
@@ -80,9 +80,15 @@ actual open class InteropScope actual constructor() {
actual
fun
toInteropForArraysOfPointers
(
interopPointers
:
Array
<
InteropPointer
>):
InteropPointer
=
interopPointers
actual
fun
callback
(
callback
:
(()
->
Unit
)?)
=
callback
as
Any
?
actual
fun
intCallback
(
callback
:
(()
->
Int
)?)
=
callback
as
Any
?
actual
fun
nativePointerCallback
(
callback
:
(()
->
NativePointer
)?)
=
callback
as
Any
?
actual
fun
interopPointerCallback
(
callback
:
(()
->
InteropPointer
)?)
=
callback
as
Any
?
actual
fun
booleanCallback
(
callback
:
(()
->
Boolean
)?)
=
callback
as
Any
?
actual
fun
virtual
(
method
:
()
->
Unit
)
=
callback
(
method
)
actual
fun
virtualInt
(
method
:
()
->
Int
)
=
intCallback
(
method
)
actual
fun
virtualNativePointer
(
method
:
()
->
NativePointer
)
=
nativePointerCallback
(
method
)
actual
fun
virtualInteropPointer
(
method
:
()
->
InteropPointer
)
=
interopPointerCallback
(
method
)
actual
fun
virtualBoolean
(
method
:
()
->
Boolean
)
=
booleanCallback
(
method
)
actual
fun
release
()
{}
...
...
skiko/src/jvmMain/kotlin/org/jetbrains/skia/shaper/Shaper.jvm.kt
0 → 100644
View file @
8aff350d
package
org.jetbrains.skia.shaper
import
org.jetbrains.skia.FontFeature.Companion.arrayOfFontFeaturesToInterop
import
org.jetbrains.skia.ManagedString
import
org.jetbrains.skia.impl.InteropPointer
import
org.jetbrains.skia.impl.getPtr
import
org.jetbrains.skia.impl.interopScope
internal
actual
fun
Shaper
.
doShape
(
textUtf8
:
ManagedString
,
fontIter
:
Iterator
<
FontRun
?
>,
bidiIter
:
Iterator
<
BidiRun
?
>,
scriptIter
:
Iterator
<
ScriptRun
?
>,
langIter
:
Iterator
<
LanguageRun
?
>,
opts
:
ShapingOptions
,
width
:
Float
,
runHandler
:
RunHandler
)
{
interopScope
{
Shaper_nShape
(
_ptr
,
getPtr
(
textUtf8
),
fontIter
as
InteropPointer
,
bidiIter
as
InteropPointer
,
scriptIter
as
InteropPointer
,
langIter
as
InteropPointer
,
optsFeaturesLen
=
opts
.
features
?.
size
?:
0
,
optsFeaturesIntArray
=
arrayOfFontFeaturesToInterop
(
opts
.
features
),
optsBooleanProps
=
opts
.
_booleanPropsToInt
(),
width
=
width
,
runHandler
=
runHandler
as
InteropPointer
)
}
}
\ No newline at end of file
skiko/src/nativeJsMain/cpp/common.h
View file @
8aff350d
...
...
@@ -167,15 +167,23 @@ static inline KFloat fromBits(KInt i) {
typedef
void
(
*
SkikoDisposeCallback
)(
KInteropPointer
);
typedef
void
(
*
SkikoCallVoidCallback
)(
KInteropPointer
);
typedef
KBoolean
(
*
SkikoCallBooleanCallback
)(
KInteropPointer
);
typedef
KInt
(
*
SkikoCallIntCallback
)(
KInteropPointer
);
typedef
KNativePointer
(
*
SkikoCallNativePointerCallback
)(
KInteropPointer
);
typedef
KInteropPointer
(
*
SkikoCallInteropPointerCallback
)(
KInteropPointer
);
typedef
void
*
KOpaquePointer
;
void
disposeCallback
(
KInteropPointer
cb
);
void
callVoidCallback
(
KInteropPointer
cb
);
KBoolean
callBooleanCallback
(
KInteropPointer
cb
);
KInt
callIntCallback
(
KInteropPointer
cb
);
KNativePointer
callNativePointerCallback
(
KInteropPointer
cb
);
KInteropPointer
callInteropPointerCallback
(
KInteropPointer
cb
);
template
<
typename
T
,
T
(
*
Apply
)(
KInteropPointer
)
>
class
KCallback
{
public
:
using
return_type
=
T
;
explicit
KCallback
(
KInteropPointer
data
)
:
data
(
data
)
{}
virtual
~
KCallback
()
{
...
...
@@ -193,7 +201,7 @@ public:
other
.
data
=
t
;
}
KCallback
&
operator
=
(
KCallback
&&
other
)
{
KCallback
&
operator
=
(
KCallback
&&
other
)
noexcept
{
std
::
swap
(
data
,
other
.
data
);
return
*
this
;
}
...
...
@@ -207,6 +215,9 @@ private:
typedef
KCallback
<
KBoolean
,
callBooleanCallback
>
KBooleanCallback
;
typedef
KCallback
<
void
,
callVoidCallback
>
KVoidCallback
;
typedef
KCallback
<
KInt
,
callIntCallback
>
KIntCallback
;
typedef
KCallback
<
KNativePointer
,
callNativePointerCallback
>
KNativePointerCallback
;
typedef
KCallback
<
KInteropPointer
,
callInteropPointerCallback
>
KInteropPointerCallback
;
#endif
/* SKIKO_COMMON_H */
skiko/src/nativeJsMain/cpp/common_interop.cc
View file @
8aff350d
...
...
@@ -351,6 +351,27 @@ KBoolean callBooleanCallback(KInteropPointer cb) {
return
static_cast
<
KBoolean
>
(
value
);
}
KInt
callIntCallback
(
KInteropPointer
cb
)
{
int
value
=
EM_ASM_INT
({
return
_callCallback
(
$
0
).
value
;
},
cb
);
return
static_cast
<
KInt
>
(
value
);
}
KNativePointer
callNativePointerCallback
(
KInteropPointer
cb
)
{
int
value
=
EM_ASM_INT
({
return
_callCallback
(
$
0
).
value
;
},
cb
);
return
reinterpret_cast
<
KNativePointer
>
(
value
);
}
KInteropPointer
callInteropPointerCallback
(
KInteropPointer
cb
)
{
int
value
=
EM_ASM_INT
({
return
_callCallback
(
$
0
).
value
;
},
cb
);
return
reinterpret_cast
<
KInteropPointer
>
(
value
);
}
void
callVoidCallback
(
KInteropPointer
cb
)
{
EM_ASM
({
_callCallback
(
$
0
);
...
...
@@ -362,9 +383,13 @@ void callVoidCallback(KInteropPointer cb) {
static
SkikoDisposeCallback
disposeCallbackImpl
=
nullptr
;
static
SkikoCallBooleanCallback
callBooleanCallbackImpl
=
nullptr
;
static
SkikoCallVoidCallback
callVoidCallbackImpl
=
nullptr
;
static
SkikoCallIntCallback
callIntCallbackImpl
=
nullptr
;
static
SkikoCallNativePointerCallback
callNativePointerCallbackImpl
=
nullptr
;
SKIKO_EXPORT
void
skiko_initCallbacks
(
KOpaquePointer
callBoolean
,
KOpaquePointer
callVoid
,
KOpaquePointer
dispose
)
{
SKIKO_EXPORT
void
skiko_initCallbacks
(
KOpaquePointer
callBoolean
,
KOpaquePointer
call
Int
,
KOpaquePointer
callNativePointer
,
KOpaquePointer
call
Void
,
KOpaquePointer
dispose
)
{
callBooleanCallbackImpl
=
reinterpret_cast
<
SkikoCallBooleanCallback
>
(
callBoolean
);
callIntCallbackImpl
=
reinterpret_cast
<
SkikoCallIntCallback
>
(
callInt
);
callNativePointerCallbackImpl
=
reinterpret_cast
<
SkikoCallNativePointerCallback
>
(
callNativePointer
);
callVoidCallbackImpl
=
reinterpret_cast
<
SkikoCallVoidCallback
>
(
callVoid
);
disposeCallbackImpl
=
reinterpret_cast
<
SkikoDisposeCallback
>
(
dispose
);
}
...
...
@@ -377,6 +402,18 @@ KBoolean callBooleanCallback(KInteropPointer cb) {
return
callBooleanCallbackImpl
(
cb
);
}
KInt
callIntCallback
(
KInteropPointer
cb
)
{
return
callIntCallbackImpl
(
cb
);
}
KNativePointer
callNativePointerCallback
(
KInteropPointer
cb
)
{
return
callNativePointerCallbackImpl
(
cb
);
}
KInteropPointer
callInteropPointerCallback
(
KInteropPointer
cb
)
{
return
callNativePointerCallbackImpl
(
cb
);
}
void
callVoidCallback
(
KInteropPointer
cb
)
{
return
callVoidCallbackImpl
(
cb
);
}
...
...
skiko/src/nativeJsMain/cpp/shaper/FontMgrRunIterator.cc
View file @
8aff350d
...
...
@@ -4,14 +4,38 @@
#include "SkFontMgr.h"
#include "SkShaper.h"
#include "common.h"
#include "FontRunIterator.hh"
SKIKO_EXPORT
KNativePointer
org_jetbrains_skia_shaper_FontMgrRunIterator__1nMake
(
KNativePointer
textPtr
,
KNativePointer
fontPtr
,
KInteropPointer
opts
)
{
TODO
(
"implement org_jetbrains_skia_shaper_FontMgrRunIterator__1nMake"
);
(
KNativePointer
textPtr
,
KNativePointer
fontPtr
,
KNativePointer
fontMgrPtr
,
KInt
optsBooleanProps
)
{
SkString
*
text
=
reinterpret_cast
<
SkString
*>
(
textPtr
);
SkFont
*
font
=
reinterpret_cast
<
SkFont
*>
(
fontPtr
);
sk_sp
<
SkFontMgr
>
fontMgr
=
fontMgrPtr
==
nullptr
?
SkFontMgr
::
RefDefault
()
:
sk_ref_sp
(
reinterpret_cast
<
SkFontMgr
*>
(
fontMgrPtr
));
std
::
shared_ptr
<
UBreakIterator
>
graphemeIter
=
skija
::
shaper
::
graphemeBreakIterator
(
*
text
);
if
(
!
graphemeIter
)
return
nullptr
;
bool
approximatePunctuation
=
(
optsBooleanProps
&
0x01
)
!=
0
;
bool
approximateSpaces
=
(
optsBooleanProps
&
0x02
)
!=
0
;
auto
instance
=
new
FontRunIterator
(
text
->
c_str
(),
text
->
size
(),
*
font
,
fontMgr
,
graphemeIter
,
approximateSpaces
,
approximatePunctuation
);
return
reinterpret_cast
<
KNativePointer
>
(
instance
);
}
SKIKO_EXPORT
KNativePointer
org_jetbrains_skia_shaper_FontMgrRunIterator__1nGetCurrentFont
(
KNativePointer
ptr
)
{
TODO
(
"implement org_jetbrains_skia_shaper_FontMgrRunIterator__1nGetCurrentFont"
);
SkShaper
::
FontRunIterator
*
instance
=
reinterpret_cast
<
SkShaper
::
FontRunIterator
*>
(
ptr
);
SkFont
*
font
=
new
SkFont
(
instance
->
currentFont
());
return
reinterpret_cast
<
KNativePointer
>
(
font
);
}
skiko/src/nativeJsMain/cpp/shaper/Shaper.cc
View file @
8aff350d
...
...
@@ -144,7 +144,311 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skia_shaper_Shaper__1nShapeLine
}
SKIKO_EXPORT
void
org_jetbrains_skia_shaper_Shaper__1nShape
(
KNativePointer
ptr
,
KNativePointer
textPtr
,
KInteropPointer
fontRunIterObj
,
KInteropPointer
bidiRunIterObj
,
KInteropPointer
scriptRunIterObj
,
KInteropPointer
languageRunIterObj
,
KInt
eropPointer
opt
s
,
KFloat
width
,
KInteropPointer
runHandlerObj
)
(
KNativePointer
ptr
,
KNativePointer
textPtr
,
KInteropPointer
fontRunIterObj
,
KInteropPointer
bidiRunIterObj
,
KInteropPointer
scriptRunIterObj
,
KInteropPointer
languageRunIterObj
,
KInt
optsFeaturesLen
,
KInt
*
optsFeatures
,
KInt
optsBooleanProp
s
,
KFloat
width
,
KInteropPointer
runHandlerObj
)
{
TODO
(
"implement org_jetbrains_skia_shaper_Shaper__1nShape"
);
auto
*
instance
=
reinterpret_cast
<
SkShaper
*>
(
ptr
);
SkString
&
text
=
*
(
reinterpret_cast
<
SkString
*>
(
textPtr
));
if
(
text
.
size
()
==
0
)
{
return
;
}
std
::
vector
<
SkShaper
::
Feature
>
features
=
skija
::
shaper
::
ShapingOptions
::
getFeaturesFromIntsArray
(
optsFeatures
,
optsFeaturesLen
);
auto
*
fontRunIter
=
reinterpret_cast
<
SkShaper
::
FontRunIterator
*>
(
fontRunIterObj
);
auto
*
languageRunIter
=
reinterpret_cast
<
SkShaper
::
LanguageRunIterator
*>
(
languageRunIterObj
);
auto
*
scriptRunIter
=
reinterpret_cast
<
SkShaper
::
ScriptRunIterator
*>
(
scriptRunIterObj
);
auto
*
bidiRunIter
=
reinterpret_cast
<
SkShaper
::
BiDiRunIterator
*>
(
bidiRunIterObj
);
auto
*
runHandler
=
reinterpret_cast
<
SkShaper
::
RunHandler
*>
(
runHandlerObj
);
instance
->
shape
(
text
.
c_str
(),
text
.
size
(),
*
fontRunIter
,
*
bidiRunIter
,
*
scriptRunIter
,
*
languageRunIter
,
features
.
data
(),
features
.
size
(),
width
,
runHandler
);
}
template
<
typename
T
,
typename
CurrentCallback
>
class
SkikoRunIterator
:
public
T
{
static_assert
(
std
::
is_base_of
<
SkShaper
::
RunIterator
,
T
>::
value
,
""
);
public
:
SkikoRunIterator
(
const
SkString
&
text
)
:
_onCurrent
(
nullptr
),
_onAtEnd
(
nullptr
),
_onEndOfCurrentRun
(
nullptr
),
_onConsume
(
nullptr
),
_indicesConverter
(
text
)
{}
void
consume
()
override
{
_onConsume
();
_endOfCurrentRun
=
_indicesConverter
.
from16To8
(
_onEndOfCurrentRun
());
}
size_t
endOfCurrentRun
()
const
override
{
return
_endOfCurrentRun
;
}
bool
atEnd
()
const
override
{
return
static_cast
<
bool
>
(
_onAtEnd
());
}
void
init
(
KInteropPointer
onConsume
,
KInteropPointer
onEndOfCurrentRun
,
KInteropPointer
onAtEnd
,
KInteropPointer
onCurrent
)
{
_onConsume
=
KVoidCallback
(
onConsume
);
_onEndOfCurrentRun
=
KIntCallback
(
onEndOfCurrentRun
);
_onAtEnd
=
KBooleanCallback
(
onAtEnd
);
_onCurrent
=
CurrentCallback
(
onCurrent
);
}
protected
:
CurrentCallback
_onCurrent
;
typename
CurrentCallback
::
return_type
current
()
const
{
auto
current
=
_onCurrent
();
return
current
;
}
private
:
KVoidCallback
_onConsume
;
KIntCallback
_onEndOfCurrentRun
;
KBooleanCallback
_onAtEnd
;
skija
::
UtfIndicesConverter
_indicesConverter
;
size_t
_endOfCurrentRun
=
0
;
};
class
SkikoFontRunIterator
:
public
SkikoRunIterator
<
SkShaper
::
FontRunIterator
,
KNativePointerCallback
>
{
public
:
SkikoFontRunIterator
(
const
SkString
&
text
)
:
SkikoRunIterator
<
SkShaper
::
FontRunIterator
,
KNativePointerCallback
>
(
text
)
{}
const
SkFont
&
currentFont
()
const
override
{
return
*
reinterpret_cast
<
SkFont
*>
(
current
());
}
};
class
SkikoBiDiRunIterator
:
public
SkikoRunIterator
<
SkShaper
::
BiDiRunIterator
,
KIntCallback
>
{
public
:
SkikoBiDiRunIterator
(
const
SkString
&
text
)
:
SkikoRunIterator
<
SkShaper
::
BiDiRunIterator
,
KIntCallback
>
(
text
)
{}
uint8_t
currentLevel
()
const
override
{
return
static_cast
<
uint8_t
>
(
current
());
}
};
class
SkikoScriptRunIterator
:
public
SkikoRunIterator
<
SkShaper
::
ScriptRunIterator
,
KIntCallback
>
{
public
:
SkikoScriptRunIterator
(
const
SkString
&
text
)
:
SkikoRunIterator
<
SkShaper
::
ScriptRunIterator
,
KIntCallback
>
(
text
)
{}
SkFourByteTag
currentScript
()
const
override
{
return
static_cast
<
SkFourByteTag
>
(
current
());
}
};
class
SkikoLanguageRunIterator
:
public
SkikoRunIterator
<
SkShaper
::
LanguageRunIterator
,
KInteropPointerCallback
>
{
public
:
SkikoLanguageRunIterator
(
const
SkString
&
text
)
:
SkikoRunIterator
<
SkShaper
::
LanguageRunIterator
,
KInteropPointerCallback
>
(
text
)
{}
const
char
*
currentLanguage
()
const
override
{
return
reinterpret_cast
<
char
*>
(
current
());
}
};
static
void
deleteRunIterator
(
SkShaper
::
RunIterator
*
runIterator
)
{
delete
runIterator
;
}
SKIKO_EXPORT
KNativePointer
org_jetbrains_skia_shaper_Shaper_RunIterator_1nGetFinalizer
()
{
return
reinterpret_cast
<
KNativePointer
>
(
deleteRunIterator
);
}
SKIKO_EXPORT
KNativePointer
org_jetbrains_skia_shaper_Shaper_RunIterator_1nCreateRunIterator
(
KInt
type
,
KNativePointer
textPtr
)
{
const
auto
&
text
=
*
(
reinterpret_cast
<
SkString
*>
(
textPtr
));
switch
(
type
)
{
case
1
:
// FontRunIterator
return
reinterpret_cast
<
KNativePointer
>
(
new
SkikoFontRunIterator
(
text
));
case
2
:
// BiDiRunIterator
return
reinterpret_cast
<
KNativePointer
>
(
new
SkikoBiDiRunIterator
(
text
));
case
3
:
// ScriptRunIterator
return
reinterpret_cast
<
KNativePointer
>
(
new
SkikoScriptRunIterator
(
text
));
case
4
:
// LanguageRunIterator
return
reinterpret_cast
<
KNativePointer
>
(
new
SkikoLanguageRunIterator
(
text
));
default:
TODO
(
"unsupported run iterator type"
);
}
}
SKIKO_EXPORT
void
org_jetbrains_skia_shaper_Shaper_RunIterator_1nInitRunIterator
(
KNativePointer
ptr
,
KInt
type
,
KInteropPointer
onConsume
,
KInteropPointer
onEndOfCurrentRun
,
KInteropPointer
onAtEnd
,
KInteropPointer
onCurrent
)
{
switch
(
type
)
{
case
1
:
{
// FontRunIterator
auto
*
runIter
=
reinterpret_cast
<
SkikoFontRunIterator
*>
(
ptr
);
runIter
->
init
(
onConsume
,
onEndOfCurrentRun
,
onAtEnd
,
onCurrent
);
break
;
}
case
2
:
{
// BiDiRunIterator
auto
*
runIter
=
reinterpret_cast
<
SkikoBiDiRunIterator
*>
(
ptr
);
runIter
->
init
(
onConsume
,
onEndOfCurrentRun
,
onAtEnd
,
onCurrent
);
break
;
}
case
3
:
{
// ScriptRunIterator
auto
*
runIter
=
reinterpret_cast
<
SkikoScriptRunIterator
*>
(
ptr
);
runIter
->
init
(
onConsume
,
onEndOfCurrentRun
,
onAtEnd
,
onCurrent
);
break
;
}
case
4
:
{
// LanguageRunIterator
auto
*
runIter
=
reinterpret_cast
<
SkikoLanguageRunIterator
*>
(
ptr
);
runIter
->
init
(
onConsume
,
onEndOfCurrentRun
,
onAtEnd
,
onCurrent
);
break
;
}
default:
TODO
(
"unsupported run iterator type"
);
}
}
// Run Handler
class
SkikoRunHandler
:
public
SkShaper
::
RunHandler
{
public
:
SkikoRunHandler
()
:
_onBeginLine
(
nullptr
),
_onRunInfo
(
nullptr
),
_onCommitRunInfo
(
nullptr
),
_onRunOffset
(
nullptr
),
_onCommitRun
(
nullptr
),
_onCommitLine
(
nullptr
),
_runInfo
(
nullptr
)
{}
void
init
(
KInteropPointer
onBeginLine
,
KInteropPointer
onRunInfo
,
KInteropPointer
onCommitRunInfo
,
KInteropPointer
onRunOffset
,
KInteropPointer
onCommitRun
,
KInteropPointer
onCommitLine
)
{
_onBeginLine
=
KVoidCallback
(
onBeginLine
);
_onRunInfo
=
KVoidCallback
(
onRunInfo
);
_onCommitRunInfo
=
KVoidCallback
(
onCommitRunInfo
);
_onRunOffset
=
KVoidCallback
(
onRunOffset
);
_onCommitRun
=
KVoidCallback
(
onCommitRun
);
_onCommitLine
=
KVoidCallback
(
onCommitLine
);
}
void
beginLine
()
override
{
_onBeginLine
();
}
void
runInfo
(
const
RunInfo
&
info
)
override
{
_runInfo
=
&
info
;
_onRunInfo
();
_runInfo
=
nullptr
;
}
void
commitRunInfo
()
override
{
_onCommitRunInfo
();
}
Buffer
runBuffer
(
const
RunInfo
&
info
)
override
{
_glyphs
=
std
::
vector
<
SkGlyphID
>
(
info
.
glyphCount
);
_positions
=
std
::
vector
<
SkPoint
>
(
info
.
glyphCount
);
_clusters
=
std
::
vector
<
uint32_t
>
(
info
.
glyphCount
);
_runInfo
=
&
info
;
_onRunOffset
();
_runInfo
=
nullptr
;
return
{
_glyphs
.
data
(),
_positions
.
data
(),
nullptr
,
_clusters
.
data
(),
_point
};
}
void
commitRunBuffer
(
const
RunInfo
&
info
)
override
{
_runInfo
=
&
info
;
_onCommitRun
();
_runInfo
=
nullptr
;
}
virtual
void
commitLine
()
override
{
_onCommitLine
();
}
void
setOffset
(
KFloat
x
,
KFloat
y
)
{
_point
=
{
x
,
y
};
}
const
std
::
vector
<
SkGlyphID
>&
glyphs
()
const
{
return
_glyphs
;
}
const
std
::
vector
<
SkPoint
>&
positions
()
const
{
return
_positions
;
}
const
std
::
vector
<
uint32_t
>&
clusters
()
const
{
return
_clusters
;
}
const
RunInfo
&
runInfo
()
const
{
return
*
_runInfo
;
}
private
:
KVoidCallback
_onBeginLine
;
KVoidCallback
_onRunInfo
;
KVoidCallback
_onCommitRunInfo
;
KVoidCallback
_onRunOffset
;
KVoidCallback
_onCommitRun
;
KVoidCallback
_onCommitLine
;
SkPoint
_point
;
std
::
vector
<
SkGlyphID
>
_glyphs
;
std
::
vector
<
SkPoint
>
_positions
;
std
::
vector
<
uint32_t
>
_clusters
;
const
RunInfo
*
_runInfo
;
};
static
void
deleteRunHandler
(
SkikoRunHandler
*
runHandler
)
{
delete
runHandler
;
}
SKIKO_EXPORT
KNativePointer
org_jetbrains_skia_shaper_Shaper_RunHandler_1nGetFinalizer
()
{
return
reinterpret_cast
<
KNativePointer
>
(
deleteRunHandler
);
}
SKIKO_EXPORT
KNativePointer
org_jetbrains_skia_shaper_Shaper_RunHandler_1nGetRunInfo
(
KNativePointer
ptr
,
KInteropPointer
fields
)
{
auto
*
instance
=
reinterpret_cast
<
SkikoRunHandler
*>
(
ptr
);
KInt
*
repr
=
reinterpret_cast
<
KInt
*>
(
fields
);
repr
[
0
]
=
instance
->
runInfo
().
fBidiLevel
;
repr
[
1
]
=
rawBits
(
instance
->
runInfo
().
fAdvance
.
x
());
repr
[
2
]
=
rawBits
(
instance
->
runInfo
().
fAdvance
.
y
());
repr
[
3
]
=
instance
->
runInfo
().
glyphCount
;
repr
[
4
]
=
instance
->
runInfo
().
utf8Range
.
begin
();
repr
[
5
]
=
instance
->
runInfo
().
utf8Range
.
size
();
auto
*
font
=
const_cast
<
SkFont
*>
(
&
(
instance
->
runInfo
().
fFont
));
return
reinterpret_cast
<
KNativePointer
>
(
font
);
}
SKIKO_EXPORT
void
org_jetbrains_skia_shaper_Shaper_RunHandler_1nGetGlyphs
(
KNativePointer
ptr
,
KInteropPointer
result
)
{
auto
*
instance
=
reinterpret_cast
<
SkikoRunHandler
*>
(
ptr
);
auto
&
src
=
instance
->
glyphs
();
std
::
copy
(
src
.
cbegin
(),
src
.
cend
(),
reinterpret_cast
<
SkGlyphID
*>
(
result
));
}
SKIKO_EXPORT
void
org_jetbrains_skia_shaper_Shaper_RunHandler_1nGetPositions
(
KNativePointer
ptr
,
KInteropPointer
result
)
{
auto
*
instance
=
reinterpret_cast
<
SkikoRunHandler
*>
(
ptr
);
auto
&
src
=
instance
->
positions
();
std
::
copy
(
src
.
cbegin
(),
src
.
cend
(),
reinterpret_cast
<
SkPoint
*>
(
result
));
}
SKIKO_EXPORT
void
org_jetbrains_skia_shaper_Shaper_RunHandler_1nGetClusters
(
KNativePointer
ptr
,
KInteropPointer
result
)
{
auto
*
instance
=
reinterpret_cast
<
SkikoRunHandler
*>
(
ptr
);
auto
&
src
=
instance
->
clusters
();
std
::
copy
(
src
.
cbegin
(),
src
.
cend
(),
reinterpret_cast
<
uint32_t
*>
(
result
));
}
SKIKO_EXPORT
void
org_jetbrains_skia_shaper_Shaper_RunHandler_1nSetOffset
(
KNativePointer
ptr
,
KFloat
x
,
KFloat
y
)
{
auto
*
instance
=
reinterpret_cast
<
SkikoRunHandler
*>
(
ptr
);
instance
->
setOffset
(
x
,
y
);
}
SKIKO_EXPORT
KNativePointer
org_jetbrains_skia_shaper_Shaper_RunHandler_1nCreate
()
{
return
reinterpret_cast
<
KNativePointer
>
(
new
SkikoRunHandler
());
}
SKIKO_EXPORT
void
org_jetbrains_skia_shaper_Shaper_RunHandler_1nInit
(
KNativePointer
ptr
,
KInteropPointer
onBeginLine
,
KInteropPointer
onRunInfo
,
KInteropPointer
onCommitRunInfo
,
KInteropPointer
onRunOffset
,
KInteropPointer
onCommitRun
,
KInteropPointer
onCommitLine
)
{
auto
*
instance
=
reinterpret_cast
<
SkikoRunHandler
*>
(
ptr
);
instance
->
init
(
onBeginLine
,
onRunInfo
,
onCommitRunInfo
,
onRunOffset
,
onCommitRun
,
onCommitLine
);
}
\ No newline at end of file
skiko/src/nativeJsMain/kotlin/org/jetbrains/skia/shaper/Shaper.nativejs.kt
0 → 100644
View file @
8aff350d
package
org.jetbrains.skia.shaper
import
org.jetbrains.skia.FontFeature.Companion.arrayOfFontFeaturesToInterop
import
org.jetbrains.skia.ManagedString
import
org.jetbrains.skia.Point
import
org.jetbrains.skia.impl.*
internal
actual
fun
Shaper
.
doShape
(
textUtf8
:
ManagedString
,
fontIter
:
Iterator
<
FontRun
?
>,
bidiIter
:
Iterator
<
BidiRun
?
>,
scriptIter
:
Iterator
<
ScriptRun
?
>,
langIter
:
Iterator
<
LanguageRun
?
>,
opts
:
ShapingOptions
,
width
:
Float
,
runHandler
:
RunHandler
)
{
val
managedFontIter
=
toManaged
(
fontIter
,
textUtf8
)
val
managedBidiIter
=
toManaged
(
bidiIter
,
textUtf8
)
val
managedScriptIter
=
toManaged
(
scriptIter
,
textUtf8
)
val
managedLangIter
=
toManaged
(
langIter
,
textUtf8
)
val
managedRunHandler
=
RunHandlerImpl
(
runHandler
)
try
{
interopScope
{
@Suppress
(
"CAST_NEVER_SUCCEEDS"
)
Shaper_nShape
(
_ptr
,
getPtr
(
textUtf8
),
getPtr
(
managedFontIter
)
as
InteropPointer
,
getPtr
(
managedBidiIter
)
as
InteropPointer
,
getPtr
(
managedScriptIter
)
as
InteropPointer
,
getPtr
(
managedLangIter
)
as
InteropPointer
,
optsFeaturesLen
=
opts
.
features
?.
size
?:
0
,
optsFeaturesIntArray
=
arrayOfFontFeaturesToInterop
(
opts
.
features
),
optsBooleanProps
=
opts
.
_booleanPropsToInt
(),
width
=
width
,
runHandler
=
getPtr
(
managedRunHandler
)
as
InteropPointer
)
}
}
finally
{
reachabilityBarrier
(
managedFontIter
)
reachabilityBarrier
(
managedBidiIter
)
reachabilityBarrier
(
managedScriptIter
)
reachabilityBarrier
(
managedLangIter
)
reachabilityBarrier
(
managedRunHandler
)
reachabilityBarrier
(
textUtf8
)
}
}
private
fun
toManaged
(
iter
:
Iterator
<
FontRun
?
>,
text
:
ManagedString
):
Managed
=
if
(
iter
is
ManagedRunIterator
<
FontRun
?>)
{
iter
}
else
{
RunIteratorBase
.
fromIterator
(
iter
,
text
)
}
private
fun
toManaged
(
iter
:
Iterator
<
LanguageRun
?
>,
text
:
ManagedString
):
Managed
=
if
(
iter
is
ManagedRunIterator
<
LanguageRun
?>)
{
iter
}
else
{
RunIteratorBase
.
fromIterator
(
iter
,
text
)
}
private
fun
toManaged
(
iter
:
Iterator
<
BidiRun
?
>,
text
:
ManagedString
):
Managed
=
if
(
iter
is
ManagedRunIterator
<
BidiRun
?>)
{
iter
}
else
{
RunIteratorBase
.
fromIterator
(
iter
,
text
)
}
private
fun
toManaged
(
iter
:
Iterator
<
ScriptRun
?
>,
text
:
ManagedString
):
Managed
=
if
(
iter
is
ManagedRunIterator
<
ScriptRun
?>)
{
iter
}
else
{
RunIteratorBase
.
fromIterator
(
iter
,
text
)
}
sealed
class
RunIteratorBase
(
type
:
Int
,
ptr
:
NativePointer
)
:
Managed
(
ptr
,
_FinalizerHolder
.
PTR
)
{
private
object
_FinalizerHolder
{
val
PTR
=
RunIterator_nGetFinalizer
()
}
abstract
fun
consume
()
abstract
fun
endOfCurrentRun
():
Int
abstract
fun
atEnd
():
Boolean
init
{
interopScope
{
RunIterator_nInitRunIterator
(
_ptr
,
type
,
onConsume
=
virtual
{
this
@RunIteratorBase
.
consume
()
},
onEndOfCurrentRun
=
virtualInt
{
this
@RunIteratorBase
.
endOfCurrentRun
()
},
onAtEnd
=
virtualBoolean
{
this
@RunIteratorBase
.
atEnd
()
},
onCurrent
=
getOnCurrentCallback
(),
)
}
}
protected
abstract
fun
InteropScope
.
getOnCurrentCallback
():
InteropPointer
companion
object
{
fun
fromIterator
(
iterator
:
Iterator
<
BidiRun
?
>,
text
:
ManagedString
):
RunIteratorBase
=
IteratorBasedBidiRunIterator
(
RunIterator_nCreateRunIterator
(
BIDI_RUN_ITERATOR_TYPE
,
getPtr
(
text
)),
iterator
)
fun
fromIterator
(
iterator
:
Iterator
<
FontRun
?
>,
text
:
ManagedString
):
RunIteratorBase
=
IteratorBasedFontRunIterator
(
RunIterator_nCreateRunIterator
(
FONT_RUN_ITERATOR_TYPE
,
getPtr
(
text
)),
iterator
)
fun
fromIterator
(
iterator
:
Iterator
<
ScriptRun
?
>,
text
:
ManagedString
):
RunIteratorBase
=
IteratorBasedScriptRunIterator
(
RunIterator_nCreateRunIterator
(
SCRIPT_RUN_ITERATOR_TYPE
,
getPtr
(
text
)),
iterator
)
fun
fromIterator
(
iterator
:
Iterator
<
LanguageRun
?
>,
text
:
ManagedString
):
RunIteratorBase
=
IteratorBasedLanguageRunIterator
(
RunIterator_nCreateRunIterator
(
LANGUAGE_RUN_ITERATOR_TYPE
,
getPtr
(
text
)),
iterator
)
}
}
private
sealed
class
FontRunIterator
(
ptr
:
NativePointer
):
RunIteratorBase
(
FONT_RUN_ITERATOR_TYPE
,
ptr
)
{
abstract
fun
currentFont
():
FontRun
?
override
fun
InteropScope
.
getOnCurrentCallback
()
=
virtualNativePointer
{
getPtr
(
currentFont
()
?.
font
)
}
}
private
sealed
class
BiDiRunIterator
(
ptr
:
NativePointer
):
RunIteratorBase
(
BIDI_RUN_ITERATOR_TYPE
,
ptr
)
{
abstract
fun
currentLevel
():
BidiRun
?
override
fun
InteropScope
.
getOnCurrentCallback
()
=
virtualInt
{
currentLevel
()
?.
level
?:
0
}
}
private
sealed
class
ScriptRunIterator
(
ptr
:
NativePointer
):
RunIteratorBase
(
SCRIPT_RUN_ITERATOR_TYPE
,
ptr
)
{
abstract
fun
currentScript
():
ScriptRun
?
override
fun
InteropScope
.
getOnCurrentCallback
()
=
virtualInt
{
currentScript
()
?.
scriptTag
?:
0
}
}
private
sealed
class
LanguageRunIterator
(
ptr
:
NativePointer
):
RunIteratorBase
(
LANGUAGE_RUN_ITERATOR_TYPE
,
ptr
)
{
abstract
fun
currentLanguage
():
LanguageRun
?
abstract
fun
currentLanguageInterop
():
InteropPointer
override
fun
InteropScope
.
getOnCurrentCallback
()
=
virtualInteropPointer
{
currentLanguageInterop
()
}
}
private
class
IteratorBasedFontRunIterator
(
ptr
:
NativePointer
,
val
iterator
:
Iterator
<
FontRun
?>)
:
FontRunIterator
(
ptr
)
{
private
var
current
:
FontRun
?
=
null
override
fun
currentFont
()
=
current
override
fun
consume
()
{
current
=
iterator
.
next
()
}
override
fun
endOfCurrentRun
()
=
current
?.
end
?:
0
override
fun
atEnd
()
=
!
iterator
.
hasNext
()
}
private
class
IteratorBasedBidiRunIterator
(
ptr
:
NativePointer
,
val
iterator
:
Iterator
<
BidiRun
?>)
:
BiDiRunIterator
(
ptr
)
{
private
var
current
:
BidiRun
?
=
null
override
fun
currentLevel
()
=
current
override
fun
consume
()
{
current
=
iterator
.
next
()
}
override
fun
endOfCurrentRun
()
=
current
?.
end
?:
0
override
fun
atEnd
()
=
!
iterator
.
hasNext
()
}
private
class
IteratorBasedScriptRunIterator
(
ptr
:
NativePointer
,
val
iterator
:
Iterator
<
ScriptRun
?>)
:
ScriptRunIterator
(
ptr
)
{
private
var
current
:
ScriptRun
?
=
null
override
fun
currentScript
()
=
current
override
fun
consume
()
{
current
=
iterator
.
next
()
}
override
fun
endOfCurrentRun
()
=
current
?.
end
?:
0
override
fun
atEnd
()
=
!
iterator
.
hasNext
()
}
private
class
IteratorBasedLanguageRunIterator
(
ptr
:
NativePointer
,
val
iterator
:
Iterator
<
LanguageRun
?>)
:
LanguageRunIterator
(
ptr
)
{
private
var
current
:
LanguageRun
?
=
null
private
var
interopScope
:
InteropScope
?
=
null
private
var
currentInterop
:
InteropPointer
=
interopScope
{
toInterop
(
null
as
ByteArray
?)
}
override
fun
currentLanguage
()
=
current
override
fun
currentLanguageInterop
()
=
currentInterop
override
fun
endOfCurrentRun
()
=
current
?.
end
?:
0
override
fun
atEnd
()
=
!
iterator
.
hasNext
()
override
fun
consume
()
{
current
=
iterator
.
next
()
currentInterop
=
langToInterop
()
}
private
fun
langToInterop
():
InteropPointer
{
if
(
interopScope
!=
null
)
{
interopScope
!!
.
release
()
}
interopScope
=
InteropScope
()
return
interopScope
!!
.
toInterop
(
currentLanguage
()
?.
language
)
}
}
private
const
val
FONT_RUN_ITERATOR_TYPE
:
Int
=
1
private
const
val
BIDI_RUN_ITERATOR_TYPE
:
Int
=
2
private
const
val
SCRIPT_RUN_ITERATOR_TYPE
:
Int
=
3
private
const
val
LANGUAGE_RUN_ITERATOR_TYPE
:
Int
=
4
private
class
RunHandlerImpl
(
val
runHandler
:
RunHandler
)
:
Managed
(
RunHandler_nCreate
(),
_FinalizerHolder
.
PTR
)
{
init
{
val
impl
=
this
interopScope
{
RunHandler_nInit
(
_ptr
,
onBeginLine
=
virtual
{
runHandler
.
beginLine
()
},
onCommitRunInfo
=
virtual
{
runHandler
.
commitRunInfo
()
},
onCommitLine
=
virtual
{
runHandler
.
commitLine
()
},
onCommitRun
=
virtual
{
val
info
=
impl
.
runInfo
val
glyphs
=
impl
.
getGlyphs
(
info
.
glyphCount
)
val
clusters
=
impl
.
getClusters
(
info
.
glyphCount
)
val
positions
=
impl
.
getPositions
(
info
.
glyphCount
)
runHandler
.
commitRun
(
info
,
glyphs
,
positions
,
clusters
)
},
onRunInfo
=
virtual
{
runHandler
.
runInfo
(
impl
.
runInfo
)
},
onRunOffset
=
virtual
{
runHandler
.
runOffset
(
impl
.
runInfo
)
?.
let
{
impl
.
setOffset
(
it
)
}
}
)
}
}
private
fun
getGlyphs
(
count
:
Int
)
=
withResult
(
ShortArray
(
count
))
{
RunHandler_nGetGlyphs
(
_ptr
,
it
)
}
private
fun
getClusters
(
count
:
Int
)
=
withResult
(
IntArray
(
count
))
{
RunHandler_nGetClusters
(
_ptr
,
it
)
}
private
fun
getPositions
(
count
:
Int
)
=
Point
.
fromArray
(
withResult
(
FloatArray
(
count
*
2
))
{
RunHandler_nGetPositions
(
_ptr
,
it
)
}
)
private
fun
setOffset
(
point
:
Point
)
{
RunHandler_nSetOffset
(
_ptr
,
point
.
x
,
point
.
y
)
}
private
val
runInfo
:
RunInfo
get
()
{
var
fontPtr
=
NullPointer
val
repr
=
withResult
(
IntArray
(
6
))
{
fontPtr
=
RunHandler_nGetRunInfo
(
_ptr
,
it
)
}
return
RunInfo
(
_fontPtr
=
fontPtr
,
bidiLevel
=
repr
[
0
],
advanceX
=
Float
.
fromBits
(
repr
[
1
]),
advanceY
=
Float
.
fromBits
(
repr
[
2
]),
glyphCount
=
repr
[
3
],
rangeBegin
=
repr
[
4
],
rangeSize
=
repr
[
5
]
)
}
private
object
_FinalizerHolder
{
val
PTR
=
RunHandler_nGetFinalizer
()
}
}
skiko/src/nativeMain/kotlin/org/jetbrains/skia/Actuals.native.kt
View file @
8aff350d
package
org.jetbrains.skia
import
kotlinx.cinterop.ByteVar
import
kotlinx.cinterop.CPointer
import
org.jetbrains.skia.impl.InteropPointer
import
org.jetbrains.skia.impl.withResult
actual
abstract
class
OutputStream
actual
fun
<
R
>
commonSynchronized
(
lock
:
Any
,
block
:
()
->
R
)
{
...
...
@@ -27,8 +32,23 @@ actual class Matcher constructor(private val regex: Regex, private val input: Ch
actual
fun
matches
():
Boolean
=
matches
}
actual
fun
defaultLanguageTag
():
String
=
TODO
()
private
val
LANG
by
lazy
{
val
localeFromICU
=
uloc_getDefault
()
var
length
=
0
val
maxLength
=
128
val
langTag
=
withResult
(
ByteArray
(
maxLength
))
{
length
=
uloc_toLanguageTag
(
localeFromICU
,
it
,
maxLength
,
false
,
toInterop
(
intArrayOf
(
0
)))
}.
decodeToString
(
0
,
length
)
langTag
.
ifEmpty
{
"en-US"
}
}
actual
fun
defaultLanguageTag
():
String
=
LANG
actual
fun
compilePattern
(
regex
:
String
):
Pattern
=
Pattern
(
regex
)
actual
typealias
ExternalSymbolName
=
kotlin
.
native
.
SymbolName
@SymbolName
(
"uloc_getDefault"
)
private
external
fun
uloc_getDefault
():
CPointer
<
ByteVar
>
@SymbolName
(
"uloc_toLanguageTag"
)
private
external
fun
uloc_toLanguageTag
(
localeId
:
CPointer
<
ByteVar
>,
buffer
:
InteropPointer
,
size
:
Int
,
strict
:
Boolean
,
err
:
InteropPointer
):
Int
\ No newline at end of file
skiko/src/nativeMain/kotlin/org/jetbrains/skia/impl/Native.native.kt
View file @
8aff350d
...
...
@@ -26,6 +26,8 @@ actual abstract class Native actual constructor(ptr: NativePointer) {
init
{
initCallbacks
(
staticCFunction
(
::
callBooleanCallback
),
staticCFunction
(
::
callIntCallback
),
staticCFunction
(
::
callNativePtrCallback
),
staticCFunction
(
::
callVoidCallback
),
staticCFunction
(
::
disposeCallback
),
)
...
...
@@ -201,20 +203,17 @@ actual class InteropScope actual constructor() {
return
toInterop
(
interopPointers
.
map
{
it
.
toLong
()
}.
toLongArray
())
}
actual
fun
booleanCallback
(
callback
:
(()
->
Boolean
)?):
InteropPointer
=
callback
?.
let
{
val
ptr
=
StableRef
.
create
(
it
).
asCPointer
(
)
NativePtr
.
NULL
.
plus
(
ptr
.
toLong
()
)
}
?:
NativePtr
.
NULL
actual
fun
callback
(
callback
:
(()
->
Unit
)?)
=
callbackImpl
(
callback
)
actual
fun
intCallback
(
callback
:
(()
->
Int
)?)
=
callbackImpl
(
callback
)
actual
fun
nativePointerCallback
(
callback
:
(()
->
NativePointer
)?)
=
callbackImpl
(
callback
)
actual
fun
interopPointerCallback
(
callback
:
(()
->
InteropPointer
)?)
=
callbackImpl
(
callback
)
actual
fun
booleanCallback
(
callback
:
(()
->
Boolean
)?)
=
callbackImpl
(
callback
)
actual
fun
callback
(
callback
:
(()
->
Unit
)?):
InteropPointer
=
callback
?.
let
{
val
ptr
=
StableRef
.
create
(
it
).
asCPointer
()
NativePtr
.
NULL
.
plus
(
ptr
.
toLong
())
}
?:
NativePtr
.
NULL
actual
fun
virtual
(
method
:
()
->
Unit
)
=
callback
(
method
)
actual
fun
virtualBoolean
(
method
:
()
->
Boolean
)
=
booleanCallback
(
method
)
actual
fun
virtual
(
method
:
()
->
Unit
)
=
callbackImpl
(
method
)
actual
fun
virtualInt
(
method
:
()
->
Int
)
=
callbackImpl
(
method
)
actual
fun
virtualNativePointer
(
method
:
()
->
NativePointer
)
=
callbackImpl
(
method
)
actual
fun
virtualInteropPointer
(
method
:
()
->
InteropPointer
)
=
callbackImpl
(
method
)
actual
fun
virtualBoolean
(
method
:
()
->
Boolean
)
=
callbackImpl
(
method
)
actual
fun
release
()
{
elements
.
forEach
{
...
...
@@ -222,6 +221,11 @@ actual class InteropScope actual constructor() {
}
}
private
fun
<
T
>
callbackImpl
(
callback
:
(()
->
T
)?):
InteropPointer
=
callback
?.
let
{
val
ptr
=
StableRef
.
create
(
it
).
asCPointer
()
NativePtr
.
NULL
.
plus
(
ptr
.
toLong
())
}
?:
NativePtr
.
NULL
private
val
elements
=
mutableListOf
<
Pinned
<*>>()
}
...
...
@@ -250,9 +254,23 @@ private fun callBooleanCallback(ptr: COpaquePointer): Boolean {
return
ptr
.
asStableRef
<()
->
Boolean
>().
get
().
invoke
()
}
private
fun
callIntCallback
(
ptr
:
COpaquePointer
):
Int
{
return
ptr
.
asStableRef
<()
->
Int
>().
get
().
invoke
()
}
private
fun
callNativePtrCallback
(
ptr
:
COpaquePointer
):
Long
{
return
ptr
.
asStableRef
<()
->
NativePointer
>().
get
().
invoke
().
toLong
()
}
private
fun
disposeCallback
(
ptr
:
COpaquePointer
)
{
ptr
.
asStableRef
<
Any
>().
dispose
()
}
@ExternalSymbolName
(
"skiko_initCallbacks"
)
private
external
fun
initCallbacks
(
callBoolean
:
COpaquePointer
,
callVoid
:
COpaquePointer
,
dispose
:
COpaquePointer
)
\ No newline at end of file
private
external
fun
initCallbacks
(
callBoolean
:
COpaquePointer
,
callInt
:
COpaquePointer
,
callNativePointer
:
COpaquePointer
,
callVoid
:
COpaquePointer
,
dispose
:
COpaquePointer
)
\ No newline at end of file
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