You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
91 lines
2.9 KiB
91 lines
2.9 KiB
package org.jetbrains.compose.resources |
|
|
|
import androidx.compose.ui.geometry.Size |
|
import androidx.compose.ui.geometry.isSpecified |
|
import androidx.compose.ui.graphics.ColorFilter |
|
import androidx.compose.ui.graphics.ImageBitmapConfig |
|
import androidx.compose.ui.graphics.drawscope.DrawScope |
|
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas |
|
import androidx.compose.ui.graphics.nativeCanvas |
|
import androidx.compose.ui.graphics.painter.Painter |
|
import androidx.compose.ui.unit.Density |
|
import androidx.compose.ui.unit.IntSize |
|
import org.jetbrains.skia.Rect |
|
import org.jetbrains.skia.svg.SVGDOM |
|
import org.jetbrains.skia.svg.SVGLength |
|
import org.jetbrains.skia.svg.SVGLengthUnit |
|
import org.jetbrains.skia.svg.SVGPreserveAspectRatio |
|
import org.jetbrains.skia.svg.SVGPreserveAspectRatioAlign |
|
import kotlin.math.ceil |
|
|
|
internal class SvgPainter( |
|
private val dom: SVGDOM, |
|
private val density: Density |
|
) : Painter() { |
|
private val root = dom.root |
|
|
|
private val defaultSizePx: Size = run { |
|
val width = root?.width?.withUnit(SVGLengthUnit.PX)?.value ?: 0f |
|
val height = root?.height?.withUnit(SVGLengthUnit.PX)?.value ?: 0f |
|
if (width == 0f && height == 0f) { |
|
Size.Unspecified |
|
} else { |
|
Size(width, height) |
|
} |
|
} |
|
|
|
init { |
|
if (root?.viewBox == null && defaultSizePx.isSpecified) { |
|
root?.viewBox = Rect.makeXYWH(0f, 0f, defaultSizePx.width, defaultSizePx.height) |
|
} |
|
} |
|
|
|
override val intrinsicSize: Size get() { |
|
return if (defaultSizePx.isSpecified) { |
|
defaultSizePx * density.density |
|
} else { |
|
Size.Unspecified |
|
} |
|
} |
|
|
|
private var previousDrawSize: Size = Size.Unspecified |
|
private var alpha: Float = 1.0f |
|
private var colorFilter: ColorFilter? = null |
|
|
|
// with caching into bitmap FPS is 3x-4x higher (tested with idea-logo.svg with 30x30 icons) |
|
private val drawCache = DrawCache() |
|
|
|
override fun applyAlpha(alpha: Float): Boolean { |
|
this.alpha = alpha |
|
return true |
|
} |
|
|
|
override fun applyColorFilter(colorFilter: ColorFilter?): Boolean { |
|
this.colorFilter = colorFilter |
|
return true |
|
} |
|
|
|
override fun DrawScope.onDraw() { |
|
if (previousDrawSize != size) { |
|
drawCache.drawCachedImage( |
|
ImageBitmapConfig.Argb8888, |
|
IntSize(ceil(size.width).toInt(), ceil(size.height).toInt()), |
|
density = this, |
|
layoutDirection, |
|
) { |
|
drawSvg(size) |
|
} |
|
} |
|
|
|
drawCache.drawInto(this, alpha, colorFilter) |
|
} |
|
|
|
private fun DrawScope.drawSvg(size: Size) { |
|
drawIntoCanvas { canvas -> |
|
root?.width = SVGLength(size.width, SVGLengthUnit.PX) |
|
root?.height = SVGLength(size.height, SVGLengthUnit.PX) |
|
root?.preserveAspectRatio = SVGPreserveAspectRatio(SVGPreserveAspectRatioAlign.NONE) |
|
dom.render(canvas.nativeCanvas) |
|
} |
|
} |
|
} |