プラグインを使ってSVGからJetpack ComposeのImageVectorを生成する

# 概要
svg画像からJetpack ComposeのIcons.Default.PersonのようなImageVector画像をプラグインを用いて生成する方法です。

# 解決したいこと
- SVG画像をJetpack Composeの[androidx.compose.material.icons](https://developer.android.com/reference/kotlin/androidx/compose/material/icons/package-summary)のIconsのような感じで使えるようにしたい
- drawableにvectorを追加したくない
- painterResourceを使用することなくsvgをIconとして使えるようにしたい

## なぜSVG画像をJetpack ComposeのIconsのような感じで使えるようにしたいのか
Iconsのような感じで使えるようにしたい理由としては下記の理由があります。
- painterResourceを使う方法はAndroidに依存してしまうので、Compose Desktopなどでこの方法を用いることができない
- 宣言的UIなのでxmlなどのリソースに依存するのではなく、コードベースで管理したいというお気持ちがある

## なぜdrawableにvector(xml)を追加したくないのか
drawableにvector(xml)を追加する問題点として下記のものがあります。
- リソースが使われなくなった時削除されないまま放置される可能性がある
- ディレクトリに分けてリソースを整理することができない

## Iconsの仕組み
IconsはImageVectorを返すような仕組みになっており、初期化されていない状態の時は、
ImageVector.Builderを用いてImageVectorを構築するような仕組みになっています。
今回は下記のようなコードをSVGを元にプラグインを使って生成します。
```Kotlin
package androidx.compose.material.icons.filled

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.materialIcon
import androidx.compose.material.icons.materialPath
import androidx.compose.ui.graphics.vector.ImageVector

public val Icons.Filled.Favorite: ImageVector
    get() {
        if (_favorite != null) {
            return _favorite!!
        }
        _favorite = materialIcon(name = "Filled.Favorite") {
            materialPath {
                moveTo(12.0f, 21.35f)
                lineToRelative(-1.45f, -1.32f)
                curveTo(5.4f, 15.36f, 2.0f, 12.28f, 2.0f, 8.5f)
                curveTo(2.0f, 5.42f, 4.42f, 3.0f, 7.5f, 3.0f)
                curveToRelative(1.74f, 0.0f, 3.41f, 0.81f, 4.5f, 2.09f)
                curveTo(13.09f, 3.81f, 14.76f, 3.0f, 16.5f, 3.0f)
                curveTo(19.58f, 3.0f, 22.0f, 5.42f, 22.0f, 8.5f)
                curveToRelative(0.0f, 3.78f, -3.4f, 6.86f, -8.55f, 11.54f)
                lineTo(12.0f, 21.35f)
                close()
            }
        }
        return _favorite!!
    }

private var _favorite: ImageVector? = null

```


# 解決策
解決策としてはSVGをComposeのImageVectorを生成するコードを生成するプラグインがあるのでそれを用いてコードの生成を行います。
## プラグインを導入する
SVG画像をComposeに変換してくれるプラグイン「Svg to Compose」というものがあるので
JetBrainsのMarcketspaceからインストールします。
※ Android StudioのPluginsからインストールすることもできます。
https://plugins.jetbrains.com/plugin/18619-svg-to-compose
![スクリーンショット 2023-02-06 15.53.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274835/0f1e50ee-5709-ed64-8209-5702e45e8c6f.png)

## Accessorを作成する
Accessorとは[androidx.compose.material.icons](https://developer.android.com/reference/kotlin/androidx/compose/material/icons/package-summary)でいうところのIconsのようなもので、
このAccessorを経由してImageVectorを取得します。
今回はMyIconsという名前のAccessorを作成しました。
またこのAccessorは後述するSVGをImageVectorに変換する時に必要になります。
```Kotlin
object MyIcons {
}
```

## SVGをImageVectorに変換する
ImageVectorを生成したいパッケージを右クリックして、
New → Jetpack Compose ImageVectorを選択します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274835/934317b8-3145-7d85-1637-bff71c44f373.png" width="480">

## 画像を選択してImageVectorを生成する
New → Jetpack Compose ImageVectorを選択すると下記のようなダイアログが表示されるので、
Accessor nameにあらかじめ作成しておいたAccessorの名称であるMyIconsを入力し、
Vector images directoryにSVG画像のファイルがあるパスを指定します。
![スクリーンショット 2023-02-06 15.59.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274835/2ea8fac7-a72b-1fa1-00c8-e3e952d7c2cd.png)

Createを選択すると下記のようなコードが生成されます。

```Kotlin
package net.pantasystem.milktea.setting.activities.myicons

import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.PathFillType.Companion.NonZero
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.StrokeCap.Companion.Butt
import androidx.compose.ui.graphics.StrokeJoin.Companion.Miter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.ImageVector.Builder
import androidx.compose.ui.graphics.vector.path
import androidx.compose.ui.unit.dp
import net.pantasystem.milktea.setting.activities.MyIcons

public val MyIcons.SettingsFill0Wght400Grad0Opsz48: ImageVector
    get() {
        if (_settingsFill0Wght400Grad0Opsz48 != null) {
            return _settingsFill0Wght400Grad0Opsz48!!
        }
        _settingsFill0Wght400Grad0Opsz48 = Builder(name = "SettingsFill0Wght400Grad0Opsz48",
                defaultWidth = 48.0.dp, defaultHeight = 48.0.dp, viewportWidth = 48.0f,
                viewportHeight = 48.0f).apply {
            path(fill = SolidColor(Color(0xFF000000)), stroke = null, strokeLineWidth = 0.0f,
                    strokeLineCap = Butt, strokeLineJoin = Miter, strokeLineMiter = 4.0f,
                    pathFillType = NonZero) {
                moveToRelative(19.4f, 44.0f)
                lineToRelative(-1.0f, -6.3f)
                quadToRelative(-0.95f, -0.35f, -2.0f, -0.95f)
                reflectiveQuadToRelative(-1.85f, -1.25f)
                lineToRelative(-5.9f, 2.7f)
                lineTo(4.0f, 30.0f)
                lineToRelative(5.4f, -3.95f)
                quadToRelative(-0.1f, -0.45f, -0.125f, -1.025f)
                quadTo(9.25f, 24.45f, 9.25f, 24.0f)
                quadToRelative(0.0f, -0.45f, 0.025f, -1.025f)
                reflectiveQuadTo(9.4f, 21.95f)
                lineTo(4.0f, 18.0f)
                lineToRelative(4.65f, -8.2f)
                lineToRelative(5.9f, 2.7f)
                quadToRelative(0.8f, -0.65f, 1.85f, -1.25f)
                reflectiveQuadToRelative(2.0f, -0.9f)
                lineToRelative(1.0f, -6.35f)
                horizontalLineToRelative(9.2f)
                lineToRelative(1.0f, 6.3f)
                quadToRelative(0.95f, 0.35f, 2.025f, 0.925f)
                quadTo(32.7f, 11.8f, 33.45f, 12.5f)
                lineToRelative(5.9f, -2.7f)
                lineTo(44.0f, 18.0f)
                lineToRelative(-5.4f, 3.85f)
                quadToRelative(0.1f, 0.5f, 0.125f, 1.075f)
                quadToRelative(0.025f, 0.575f, 0.025f, 1.075f)
                reflectiveQuadToRelative(-0.025f, 1.05f)
                quadToRelative(-0.025f, 0.55f, -0.125f, 1.05f)
                lineTo(44.0f, 30.0f)
                lineToRelative(-4.65f, 8.2f)
                lineToRelative(-5.9f, -2.7f)
                quadToRelative(-0.8f, 0.65f, -1.825f, 1.275f)
                quadToRelative(-1.025f, 0.625f, -2.025f, 0.925f)
                lineToRelative(-1.0f, 6.3f)
                close()
                moveTo(24.0f, 30.5f)
                quadToRelative(2.7f, 0.0f, 4.6f, -1.9f)
                quadToRelative(1.9f, -1.9f, 1.9f, -4.6f)
                quadToRelative(0.0f, -2.7f, -1.9f, -4.6f)
                quadToRelative(-1.9f, -1.9f, -4.6f, -1.9f)
                quadToRelative(-2.7f, 0.0f, -4.6f, 1.9f)
                quadToRelative(-1.9f, 1.9f, -1.9f, 4.6f)
                quadToRelative(0.0f, 2.7f, 1.9f, 4.6f)
                quadToRelative(1.9f, 1.9f, 4.6f, 1.9f)
                close()
                moveTo(24.0f, 27.5f)
                quadToRelative(-1.45f, 0.0f, -2.475f, -1.025f)
                quadTo(20.5f, 25.45f, 20.5f, 24.0f)
                quadToRelative(0.0f, -1.45f, 1.025f, -2.475f)
                quadTo(22.55f, 20.5f, 24.0f, 20.5f)
                quadToRelative(1.45f, 0.0f, 2.475f, 1.025f)
                quadTo(27.5f, 22.55f, 27.5f, 24.0f)
                quadToRelative(0.0f, 1.45f, -1.025f, 2.475f)
                quadTo(25.45f, 27.5f, 24.0f, 27.5f)
                close()
                moveTo(24.0f, 24.0f)
                close()
                moveTo(21.8f, 41.0f)
                horizontalLineToRelative(4.4f)
                lineToRelative(0.7f, -5.6f)
                quadToRelative(1.65f, -0.4f, 3.125f, -1.25f)
                reflectiveQuadTo(32.7f, 32.1f)
                lineToRelative(5.3f, 2.3f)
                lineToRelative(2.0f, -3.6f)
                lineToRelative(-4.7f, -3.45f)
                quadToRelative(0.2f, -0.85f, 0.325f, -1.675f)
                quadToRelative(0.125f, -0.825f, 0.125f, -1.675f)
                quadToRelative(0.0f, -0.85f, -0.1f, -1.675f)
                quadToRelative(-0.1f, -0.825f, -0.35f, -1.675f)
                lineTo(40.0f, 17.2f)
                lineToRelative(-2.0f, -3.6f)
                lineToRelative(-5.3f, 2.3f)
                quadToRelative(-1.15f, -1.3f, -2.6f, -2.175f)
                quadToRelative(-1.45f, -0.875f, -3.2f, -1.125f)
                lineTo(26.2f, 7.0f)
                horizontalLineToRelative(-4.4f)
                lineToRelative(-0.7f, 5.6f)
                quadToRelative(-1.7f, 0.35f, -3.175f, 1.2f)
                quadToRelative(-1.475f, 0.85f, -2.625f, 2.1f)
                lineTo(10.0f, 13.6f)
                lineToRelative(-2.0f, 3.6f)
                lineToRelative(4.7f, 3.45f)
                quadToRelative(-0.2f, 0.85f, -0.325f, 1.675f)
                quadToRelative(-0.125f, 0.825f, -0.125f, 1.675f)
                quadToRelative(0.0f, 0.85f, 0.125f, 1.675f)
                quadToRelative(0.125f, 0.825f, 0.325f, 1.675f)
                lineTo(8.0f, 30.8f)
                lineToRelative(2.0f, 3.6f)
                lineToRelative(5.3f, -2.3f)
                quadToRelative(1.2f, 1.2f, 2.675f, 2.05f)
                quadTo(19.45f, 35.0f, 21.1f, 35.4f)
                close()
            }
        }
        .build()
        return _settingsFill0Wght400Grad0Opsz48!!
    }

private var _settingsFill0Wght400Grad0Opsz48: ImageVector? = null

```

## 名称などを調節する
元々のSVGの名称から名称が決定されてしまい、場合によっては扱いづらいこともあるので適切な名前にリネームしてください。

## 実際に使用する
うまくいくと下記のように扱うことができると思います。　
```Kotlin
@Composable
fun SettingIconComponent() {
    Icon(MyIcons.SettingsFill0Wght400Grad0Opsz48, contentDescription = "testtest")
}
```

# まとめ
- Svg to ComposeというプラグインでSVGをImageVectorを生成するコードを生成することができる
- この方法を用いることによって、独自のリソースを[androidx.compose.material.icons](https://developer.android.com/reference/kotlin/androidx/compose/material/icons/package-summary)のIconsのような感じで扱えるようにできる
- Androidに依存していないため、Comopse Desktopなどでもこの方法を用いて独自のSVGアイコンを使用することができるようになる。