Slide 1

Slide 1 text

Skia and Skija, Skiko Daichi Furiya #ca_flutter_kmm

Slide 2

Slide 2 text

About me Daichi Furiya (降矢 大地) Google Developers Expert CyberAgent, Inc. @wasabeef_jp wasabeef

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

Skia? • グラフィックライブラリ(エンジン) • Chrome, Android, Flutter, Firefox, .NET, Compose for Desktop などで採用されている • Android 9 以降、デフォルトのレンダラーは Skia に なっている(8 と 9 で UI が変わった)

Slide 6

Slide 6 text

Supported platforms •Windows 7, 8, 8.1, 10 •macOS 10.10.5 or later •iOS 8 or later •Android 4.1 (JellyBean) or later •Ubuntu 14.04+, Debian 8+, openSUSE 13.3+, or Fedora Linux 24+

Slide 7

Slide 7 text

Case: Skia + Flutter

Slide 8

Slide 8 text

Showcase Shapes ベジェ曲線 平行移動と回転 テキストレンダリング シェーダー パス

Slide 9

Slide 9 text

SkCanvas + SkPaint sample void draw(SkCanvas* canvas) { SkPaint p; p.setColor(SK_ColorRED); p.setAntiAlias(true); p.setStyle(SkPaint:::kStroke_Style); p.setStrokeWidth(150); canvas->-drawLine(75, 75, 175, 175, p); } Android 寄りだけど、よくある Canvas API

Slide 10

Slide 10 text

SkCanvas - Backends •Raster - CPU-only. •GPU - Skia's GPU-accelerated backend. •SkPDF - PDF document creation. •SkPicture - Skia's display list format. •NullCanvas - Useful for testing only. •SkXPS - Experimental XPS backend. •SkSVG - Experimental SVG backend. SkCanvas には複数のバックエンドが用意されている

Slide 11

Slide 11 text

GPU GPU には Skia のビルド時に Webkit/Canvas、 OpenGL、OpenGL ES、Vulkan、Metal などのモード を選択することができる。

Slide 12

Slide 12 text

Skia のメリット •コード量の削減(例:LibreOffice は 12k → 4k) •一貫性のある API •クロスプラットフォームの対応 •複数のバックエンドサポート Webkit/Canvas、OpenGL (ES)、Vulkan、Metal

Slide 13

Slide 13 text

Flutter Web でのデメリット •Webkit/Canvas でテキストを描画しているので、文 字列の選択などができない

Slide 14

Slide 14 text

Compose for Desktop

Slide 15

Slide 15 text

Compose for Desktop

Slide 16

Slide 16 text

Desktop アプリを作るということどういうことか 前提:クロスプラットフォーム パフォーマンスが高くない WASM は高速だが、JS + DOM はJVM よりもはるかに低速 • JVM はパフォーマンスは高い が、AWT、Swing、JavaFX はメ モリ割り当てしすぎないように気 をつけないといけない。 • OpenGL は難しい

Slide 17

Slide 17 text

Compose for Desktop fun main() { overrideSchedulers(main = Dispatchers.Main:::asScheduler) val lifecycle = LifecycleRegistry() lifecycle.resume() Window("Todo") { Surface(modifier = Modifier.fillMaxSize()) { MaterialTheme { DesktopTheme { Text(“Hello World!!!”) } } } } } ほぼ Jetpack Compose になっている

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

Skija • JetBrains 開発 • Skia for Java (Java bindings to Skia) • Graphics2D、GraphicsContext は古い • 最新の Typography 対応 • Vulkan* や Metal 対応

Slide 20

Slide 20 text

Skija が目指すところ • 自動でメモリ管理、リークなし • Java のコードスタイルに準拠 • Integer constants よりも enum • Fluent API • Skija から ネイティブ Skia を感じさせない設計

Slide 21

Slide 21 text

Skija - build.gradle repositories { maven { url 'https:///packages.jetbrains.team/maven/p/skija/maven' } } dependencies { /// macOS, windows, linux api “org.jetbrains.skija:skija-${platform}:0.1.+” } ↑ 各 OS 毎に Artifacts が分かれているのでビルド時に切り替えて使う

Slide 22

Slide 22 text

Skiko

Slide 23

Slide 23 text

Skiko? • JetBrains 開発 • Skia for Kotlin (Kotlin MP bindings to Skia)

Slide 24

Slide 24 text

Skiko - build.gradle repositories { maven { url 'https:///packages.jetbrains.team/maven/p/ui/dev' } } dependencies { /// macOS, windows, linux implementation “org.jetbrains.skiko:skiko-jvm-runtime-${platform}:0.1.+” } ↑ 各 OS 毎に Artifacts が分かれているのでビルド時に切り替えて使う

Slide 25

Slide 25 text

Skiko - App.kt fun main(args: Array) { SkiaWindow().apply { layer.renderer = Renderer { renderer, w, h ->- val canvas = renderer.canvas!!! val paint1 = Paint().setColor(0xffff0000.toInt()) /// ARGB canvas.drawRRect(RRect.makeLTRB(10f, 10f, w - 10f, h - 10f, 5f), paint1) val paint2 = Paint().setColor(0xff00ff00.toInt()) /// ARGB canvas.drawRRect(RRect.makeLTRB(30f, 30f, w - 30f, h - 30f, 10f), paint2) } setVisible(true) setSize(800, 600) } } SkiaWindow が UI のコンテナ になるので、その上で描画する

Slide 26

Slide 26 text

Skiko - SkiaLayer open class SkiaWindow : JFrame() { val layer = SkiaLayer() init { contentPane.add(layer) addComponentListener(object : ComponentAdapter() { override fun componentResized(e: ComponentEvent) { layer.reinit() } }) } fun display() = layer.display() } javax.swing.JFrame を実装して SkiaLayer を渡しているだけ

Slide 27

Slide 27 text

Skiko - SkiaLayer open class SkiaLayer() : HardwareLayer() { open val api: GraphicsApi = GraphicsApi.OPENGL /// ..... override fun draw() { if (!inited) { if (skijaState.context === null) { skijaState.context = when (api) { GraphicsApi.OPENGL ->- makeGLContext() GraphicsApi.METAL ->- makeMetalContext() else ->- TODO("Unsupported yet") } } renderer??.onInit() inited = true renderer??.onReshape(width, height) } initSkija() /// ..... } /// ..... } HardwareLayer はただの awt.Canvas で api: GraphicApi でコンテキストを変えている。 Skija が Vulkan の対応はまだ追いついていない 実際に draw している先は Skija Canvas。 ここから Skija の世界へ。

Slide 28

Slide 28 text

CanvasKit

Slide 29

Slide 29 text

CanvasKit • Skia for WebAssembly • WebGL のサポート

Slide 30

Slide 30 text

CanvasKit + Skottie • Lottie Animation Support

Slide 31

Slide 31 text

SkiaSharp

Slide 32

Slide 32 text

SkiaSharp .NET Standard 1.3 .NET Core Tizen Xamarin.Android Xamarin.iOS Xamarin.tvOS Xamarin.watchOS Xamarin.Mac Windows Classic Desktop(Windows.Forms / WPF) Windows UWP (Desktop / Mobile / Xbox / HoloLens) Web Assembly (WASM) • Microsoft 開発

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

 Kotlin MP App   Skiko   Skija   Flutter App   Flutter engine  • Android • iOS • Windows • macOS • Linux  Skia  • Android • Windows • macOS • Linux  Skia  • iOS?

Slide 35

Slide 35 text

twitter.com/wasabeef_jp wasabeef.jp github.com/wasabeef Thanks