Skip to content

Commit

Permalink
Fix fever favicon failed to parse when it's SVG (#514)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
kid1412621 authored Jan 11, 2024
1 parent 5d1bdfb commit cd135cd
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 12 deletions.
61 changes: 50 additions & 11 deletions app/src/main/java/me/ash/reader/ui/component/base/Base64Image.kt
Original file line number Diff line number Diff line change
@@ -1,30 +1,69 @@
package me.ash.reader.ui.component.base

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.util.Base64
import androidx.compose.foundation.Image
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Size
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
fun Base64Image(
modifier: Modifier = Modifier,
base64Uri: String
) {
val bitmap = base64ToBitmap(base64Uri)
val imageBitmap = bitmap.asImageBitmap()
val isSvg = base64Uri.startsWith("image/svg")

Image(
bitmap = imageBitmap,
modifier = modifier,
contentDescription = null
)
if (isSvg) {
Image(
painter = base64ToPainter(base64Uri),
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 imageBytes = Base64.decode(base64Data, Base64.DEFAULT)
return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
return Base64.decode(base64Data, Base64.DEFAULT)
}

@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)
}
}
}
}
}
2 changes: 1 addition & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@
<string name="inoreader" translatable="false">Inoreader</string>
<string name="local_desc">On this device</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="self_hosted">Self-Hosted</string>
<string name="fresh_rss_desc" translatable="false">freshrss.org</string>
Expand Down

0 comments on commit cd135cd

Please sign in to comment.