Glide で SVG を表示したい

## 概要
Glide は標準で SVG をサポートしてなかったので試してみました。

基本的には[ここに記載されている公式のサンプルソース](https://bumptech.github.io/glide/ref/samples.html)に書いてあることと同じことをしているだけです。

## 手順
### ライブラリの追加
```gradle
plugins {
    ...
    id 'com.google.devtools.ksp'
}
android {
    ...
    dependencies {
        ...
        ksp 'com.github.bumptech.glide:ksp:4.15.1'
        implementation 'com.caverock:androidsvg:1.4'
    }
}
```
### 以下のファイルを作成する

```SvgDecoder.kt
import com.bumptech.glide.load.Options
import com.bumptech.glide.load.ResourceDecoder
import com.bumptech.glide.load.engine.Resource
import com.bumptech.glide.load.resource.SimpleResource
import com.bumptech.glide.request.target.Target
import com.caverock.androidsvg.SVG
import com.caverock.androidsvg.SVGParseException
import java.io.IOException
import java.io.InputStream


/** Decodes an SVG internal representation from an [InputStream].  */
class SvgDecoder : ResourceDecoder<InputStream, SVG> {
    override fun handles(source: InputStream, options: Options): Boolean {
        return true
    }

    @Throws(IOException::class)
    override fun decode(source: InputStream, width: Int, height: Int, options: Options): Resource<SVG> {
        return try {
            val svg = SVG.getFromInputStream(source)
            if (width != Target.SIZE_ORIGINAL) {
                svg.documentWidth = width.toFloat()
            }
            if (height != Target.SIZE_ORIGINAL) {
                svg.documentHeight = height.toFloat()
            }
            SimpleResource(svg)
        } catch (ex: Throwable) {
            throw IOException("Cannot load SVG from stream", ex)
        }
    }
}
```

```SvgDrawableTranscoder.kt
import android.graphics.Picture
import android.graphics.drawable.PictureDrawable
import com.bumptech.glide.load.Options
import com.bumptech.glide.load.engine.Resource
import com.bumptech.glide.load.resource.SimpleResource
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder
import com.caverock.androidsvg.SVG


/**
 * Convert the [SVG]'s internal representation to an Android-compatible one ([Picture]).
 */
class SvgDrawableTranscoder : ResourceTranscoder<SVG, PictureDrawable> {
    override fun transcode(toTranscode: Resource<SVG>, options: Options): Resource<PictureDrawable> {
        val svg = toTranscode.get()
        val picture = svg.renderToPicture()
        val drawable = PictureDrawable(picture)
        return SimpleResource(drawable)
    }
}
```

```SvgModule.kt
import android.content.Context
import android.graphics.drawable.PictureDrawable
import com.bumptech.glide.Glide
import com.bumptech.glide.Registry
import com.bumptech.glide.annotation.GlideModule
import com.bumptech.glide.module.AppGlideModule
import com.caverock.androidsvg.SVG
import java.io.InputStream


/** Module for the SVG sample app.  */
@GlideModule
class SvgModule : AppGlideModule() {
    override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
        registry.register(SVG::class.java, PictureDrawable::class.java, SvgDrawableTranscoder())
            .append(InputStream::class.java, SVG::class.java, SvgDecoder())
    }

    // Disable manifest parsing to avoid adding similar modules twice.
    override fun isManifestParsingEnabled(): Boolean {
        return false
    }
}
```

## あとは使うだけ
```kotlin
Glide.with(context).load("path/to/svg.svg").into(myView)
GlideImage(model = "path/to/svg.svg",contentDescription = "") // Jetpack Compose
```

## 公式のソースとの違い
SVG.getFromInputStream の例外を catch (ex: Throwable) として全て catch するようにしているのが公式との違いです。androidsvg は様々な例外を返すので、あまり行儀が良くないSVGファイルを渡すと元のコードではクラッシュすることがあります。