Fix fever favicon failed to parse when it's SVG (#514)

* 1. WIP: fix failed to parse base64 image when it's svg+xml;
2. fix a type.

* fix some svg drawing improperly

* refactor a little
This commit is contained in:
kid1412621 2024-01-11 17:47:06 +08:00 committed by GitHub
parent 5d1bdfb5f3
commit cd135cd756
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 51 additions and 12 deletions

View File

@ -1,30 +1,69 @@
package me.ash.reader.ui.component.base package me.ash.reader.ui.component.base
import android.graphics.Bitmap
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.util.Base64 import android.util.Base64
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.nativeCanvas
import androidx.compose.ui.graphics.painter.Painter
import com.caverock.androidsvg.SVG
@Composable @Composable
fun Base64Image( fun Base64Image(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
base64Uri: String base64Uri: String
) { ) {
val bitmap = base64ToBitmap(base64Uri) val isSvg = base64Uri.startsWith("image/svg")
val imageBitmap = bitmap.asImageBitmap()
Image( if (isSvg) {
bitmap = imageBitmap, Image(
modifier = modifier, painter = base64ToPainter(base64Uri),
contentDescription = null modifier = modifier,
) contentDescription = null
)
} else {
val bytes = base64ToBytes(base64Uri)
val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
Image(
bitmap = bitmap.asImageBitmap(),
modifier = modifier,
contentDescription = null
)
}
} }
fun base64ToBitmap(base64String: String): Bitmap { private fun base64ToBytes(base64String: String): ByteArray {
val base64Data = base64String.substringAfter("base64,") val base64Data = base64String.substringAfter("base64,")
val imageBytes = Base64.decode(base64Data, Base64.DEFAULT) return Base64.decode(base64Data, Base64.DEFAULT)
return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size) }
@Composable
private fun base64ToPainter(base64Str: String): Painter {
return remember(base64Str) {
val svg = SVG.getFromString(String(base64ToBytes(base64Str)))
object : Painter() {
override val intrinsicSize: Size
get() {
svg.let {
return Size(it.documentWidth, it.documentHeight)
}
}
override fun DrawScope.onDraw() {
svg.let {
val canvas = drawContext.canvas.nativeCanvas
// see: https://code.google.com/archive/p/androidsvg/wikis/FAQ.wiki#my-document-has-a-viewbox-but-it-is-still-not-scaling
svg.setDocumentHeight("100%")
svg.setDocumentWidth("100%")
svg.renderToCanvas(canvas)
}
}
}
}
} }

View File

@ -356,7 +356,7 @@
<string name="inoreader" translatable="false">Inoreader</string> <string name="inoreader" translatable="false">Inoreader</string>
<string name="local_desc">On this device</string> <string name="local_desc">On this device</string>
<string name="services">Services</string> <string name="services">Services</string>
<string name="feedly_desc" translatable="false">feedll.com</string> <string name="feedly_desc" translatable="false">feedly.com</string>
<string name="inoreader_desc" translatable="false">inoreader.com</string> <string name="inoreader_desc" translatable="false">inoreader.com</string>
<string name="self_hosted">Self-Hosted</string> <string name="self_hosted">Self-Hosted</string>
<string name="fresh_rss_desc" translatable="false">freshrss.org</string> <string name="fresh_rss_desc" translatable="false">freshrss.org</string>