diff --git a/CHANGELOG.md b/CHANGELOG.md index 01ef0cb47..92375ca0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ All notable changes to this project will be documented in this file. - Cataloguing: identify Apple variant of HDR images +### Fixed + +- rendering of SVG with large header + ## [v1.10.9] - 2024-04-14 ### Fixed diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/SvgRegionFetcher.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/SvgRegionFetcher.kt index 32eaf7e25..6b3d7f9aa 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/SvgRegionFetcher.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/SvgRegionFetcher.kt @@ -10,6 +10,7 @@ import com.caverock.androidsvg.PreserveAspectRatio import com.caverock.androidsvg.RenderOptions import com.caverock.androidsvg.SVG import com.caverock.androidsvg.SVGParseException +import deckers.thibault.aves.metadata.SVGParserBufferedInputStream import deckers.thibault.aves.metadata.SvgHelper.normalizeSize import deckers.thibault.aves.utils.BitmapUtils.ARGB_8888_BYTE_SIZE import deckers.thibault.aves.utils.BitmapUtils.getBytes @@ -47,7 +48,7 @@ class SvgRegionFetcher internal constructor( if (currentSvgRef == null) { val newSvg = StorageUtils.openInputStream(context, uri)?.use { input -> try { - SVG.getFromInputStream(input) + SVG.getFromInputStream(SVGParserBufferedInputStream(input)) } catch (ex: SVGParseException) { result.error("fetch-parse", "failed to parse SVG for uri=$uri regionRect=$regionRect", null) return diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ActivityResultStreamHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ActivityResultStreamHandler.kt index 9fd0d45a0..7d442e98b 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ActivityResultStreamHandler.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ActivityResultStreamHandler.kt @@ -279,6 +279,6 @@ class ActivityResultStreamHandler(private val activity: Activity, arguments: Any companion object { private val LOG_TAG = LogUtils.createTag() const val CHANNEL = "deckers.thibault/aves/activity_result_stream" - private const val BUFFER_SIZE = 2 shl 17 // 256kB + private const val BUFFER_SIZE = 1 shl 18 // 256kB } } \ No newline at end of file diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/decoder/SvgGlideModule.kt b/android/app/src/main/kotlin/deckers/thibault/aves/decoder/SvgGlideModule.kt index d544ba203..bf4e3b6d0 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/decoder/SvgGlideModule.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/decoder/SvgGlideModule.kt @@ -18,6 +18,7 @@ import com.bumptech.glide.module.LibraryGlideModule import com.bumptech.glide.signature.ObjectKey import com.caverock.androidsvg.SVG import com.caverock.androidsvg.SVGParseException +import deckers.thibault.aves.metadata.SVGParserBufferedInputStream import deckers.thibault.aves.metadata.SvgHelper.normalizeSize import deckers.thibault.aves.utils.StorageUtils import kotlin.math.ceil @@ -52,7 +53,7 @@ internal class SvgFetcher(val model: SvgImage, val width: Int, val height: Int) val bitmap: Bitmap? = StorageUtils.openInputStream(context, uri)?.use { input -> try { - SVG.getFromInputStream(input)?.let { svg -> + SVG.getFromInputStream(SVGParserBufferedInputStream(input))?.let { svg -> svg.normalizeSize() val viewBox = svg.documentViewBox val svgWidth = viewBox.width() diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/SvgHelper.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/SvgHelper.kt index 08efc7bb5..da90f0c0e 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/SvgHelper.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/SvgHelper.kt @@ -1,6 +1,9 @@ package deckers.thibault.aves.metadata import com.caverock.androidsvg.SVG +import java.io.BufferedInputStream +import java.io.InputStream +import kotlin.math.max object SvgHelper { fun SVG.normalizeSize() { @@ -10,4 +13,19 @@ object SvgHelper { setDocumentWidth("100%") setDocumentHeight("100%") } -} \ No newline at end of file +} + +// As of AndroidSVG v1.4, SVGParser.ENTITY_WATCH_BUFFER_SIZE is set at 4096. +// This constant is not configurable and used for the internal buffer mark read limit. +// Parsing will fail if the SVG header is larger than this value. +// So we define and apply a minimum read limit. +class SVGParserBufferedInputStream(input: InputStream) : BufferedInputStream(input) { + @Synchronized + override fun mark(readlimit: Int) { + super.mark(max(MINIMUM_READ_LIMIT, readlimit)) + } + + companion object { + private const val MINIMUM_READ_LIMIT = 1 shl 14 // 16kB + } +}