fresco icon indicating copy to clipboard operation
fresco copied to clipboard

SVGs - ScaleTypes and Color Filters not working

Open King-Henry opened this issue 7 years ago • 4 comments

Description

I followed this code example: https://github.com/facebook/fresco/tree/master/samples/showcase/src/main/java/com/facebook/fresco/samples/showcase/imageformat/svg

to implement SVGs in my Android app along with the help of AndroidSVG 1.3

I'm experiencing the following:

  1. The scaling of image in my DraweeViews are all messed up. The SVGs are either cut off on the left side or appear in the top left corner. I've tried multiple ScaleTypes.
    • Using getHierarchy().setActualImageScaleType
  2. Depending on the device the SVGs can either be big or small.
  3. Color filters aren't working for me on the SVGs. (getHierarchy().setActualImageColorFilter)
  4. On API 21 & 22, SVGs don't appear at all

This is how I initialize Fresco:

ImageFormat.FormatChecker svgFormatChecker = new FrescoSvgImageFormatChecker();
        ImageDecoder svgDecoder = new FrescoSvgDecoder();
        ImageDecoderConfig svgDecoderConfig = new ImageDecoderConfig.Builder()
                .addDecodingCapability(
                        FrescoSvgImageFormatChecker.Companion.getSvgFormat(),
                        svgFormatChecker,
                        svgDecoder)
                .build();

        ImagePipelineConfig config = ImagePipelineConfig.newBuilder(this)
                .setImageDecoderConfig(svgDecoderConfig)
                .setDownsampleEnabled(true)
                .build();

        DrawableFactory svgDrawableFactory = new FrescoSvgDrawableFactory();
        DraweeConfig draweeConfig = DraweeConfig.newBuilder()
                .addCustomDrawableFactory(svgDrawableFactory)
                .build();

fresco_svg_issue_1 fresco_svg_issue_2

  • Fresco version: 1.7.1
  • Platform version: Happens on every single device.

King-Henry avatar Feb 28 '19 17:02 King-Henry

Hey! The SVG support is only an example of how an implementation could look like, we did not implement all features. Feel free to contribute more features to the sample!

re 1) Looks like the PictureDrawable doesn't properly support this. You probably need a different implementation, see https://github.com/facebook/fresco/blob/master/samples/showcase/src/main/java/com/facebook/fresco/samples/showcase/imageformat/svg/SvgDecoderExample.java#L148 re 2) I suppose your SVGs don't support the notion of DP but everything is based on pixels. re 3) You'd have to add support to the SvgDrawable for this. re 4) That's weird. Maybe there's a new version for the library that can be used. Is there anything in your logcat?

oprisnik avatar Mar 01 '19 15:03 oprisnik

In internet resources, it is suggested to use glide library for svg images: https://github.com/bumptech/glide An example: https://github.com/bumptech/glide/tree/master/samples/svg/src/main/java/com/bumptech/glide/samples/svg source: https://askvoprosy.com/voprosy/is-it-possible-to-load-svg-on-fresco-lib

AikoKiko avatar Apr 15 '19 15:04 AikoKiko

@AikoKiko Glide is using the same SVG library as the Fresco sample, so there should be similar issues there and Fresco's SVG example should also work.

oprisnik avatar Apr 15 '19 19:04 oprisnik

In order to support color filtering for svgs loaded using fresco, you can change SvgPictureDrawable from example to following SvgBitmapDrawable

class SvgBitmapDrawable(private val svg: SVG) : Drawable() {
	private val paint = Paint()
	private var bitmapToDraw: Bitmap? = null

	override fun draw(canvas: Canvas) {
		val bitmap = bitmapToDraw
		if (bitmap != null) {
			canvas.drawBitmap(bitmap, 0f, 0f, paint)
		}
	}

	override fun setAlpha(alpha: Int) {
		paint.alpha = alpha
	}

	override fun setColorFilter(colorFilter: ColorFilter?) {
		paint.colorFilter = colorFilter
	}

	override fun getOpacity(): Int {
		return PixelFormat.TRANSLUCENT
	}

	override fun getIntrinsicWidth(): Int {
		return svg.documentWidth.toInt()
	}

	override fun getIntrinsicHeight(): Int {
		return svg.documentHeight.toInt()
	}

	override fun onBoundsChange(bounds: Rect) {
		super.onBoundsChange(bounds)
		val width = bounds.width()
		val height = bounds.height()
		if (width > 0 && height > 0) {
			bitmapToDraw = createNewSvgBitmap(width, height)
		}
	}

	private fun createNewSvgBitmap(width: Int, height: Int): Bitmap {
		val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
		val canvas = Canvas(bitmap)
		svg.renderToCanvas(canvas)
		return bitmap
	}
}

Main trick here is to first draw svg to a Bitmap. And then draw that bitmap to drawable's canvas using Paint with installed ColorFilter.

I have checked this on fresco version 3.1.0, works fine

k4k7us23 avatar Jan 23 '25 14:01 k4k7us23