Search code examples
svgwxpython

display SVG with gaussian blur in wxPython


I want to display in a wxPython frame an SVG image that uses a feGaussianBlur. The following example shows the image but the gaussian blur is not applied. I checked the SVG code, and it seeems fine.

Please note that this is a minimal test, but I intent to use this code in a context where SVG code is not stored in a file but generated by some code. Also, the background color needs to be set outside of the SVG code.

Am I doing something wrong? Or whould I switch to another renderer than wx.svg?

import wx
import wx.svg
import numpy as np
import utils

class MyClass(wx.Frame):
    def __init__(self, parent, title):
        super(MyClass, self).__init__(parent, title=title, size=(400, 400))
        
        self.svg_filename = "uiIcons\\Smart_views\\Dance.svg"
        self.backgroundColor = "rgb(255,0,0,255)"
        self.foregroundColor = "rgb(0,0,255,255)"
        
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Show()
    
    def OnPaint(self, event):
        dc = wx.PaintDC(self)
        width, height = self.GetSize()
        
        buffer = wx.Bitmap(width*2, height*2)
        pdc = wx.BufferedPaintDC(self, buffer)
        try:
            dc = wx.GCDC(pdc)
        except:
            dc = pdc
        
        dc.SetPen(wx.TRANSPARENT_PEN)
        
        dc.SetBrush(wx.Brush(self.backgroundColor))
        dc.DrawRectangle(0, 0, height, height)
        

        self.blur_bmp = self.CreateBitmapFromSvg(width, height)
        dc.DrawBitmap(self.blur_bmp, 0, 0)
        
    
    def CreateBitmapFromSvg(self, width, height):
        svg = """
    <?xml version="1.0" ?>
    <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
        <defs id="defs1">
            <filter
                xmlns="http://www.w3.org/2000/svg" id="gaussianblur" x="0" y="0">
                <feGaussianBlur in="SourceGraphic" stdDeviation="5"/>
            </filter>
        </defs>
         <rect x="50" y="50" width="200" height="200" fill="blue" filter="url(#gaussianblur)"/>
    </svg>
        """
        
        img = wx.svg.SVGimage.CreateFromBytes(str.encode(svg))
        
        dcdim = height/2
        imgdim = max(img.width, img.height)
        scale = dcdim / imgdim
        imgwidth = int(img.width * scale)
        imgheight = int(img.height * scale)
        x = int((width-imgwidth)/2)
        y = int((height-imgheight)/2)
        
        bmp = img.ConvertToBitmap(scale=scale, width=imgwidth, height=imgheight)
        
        return bmp

if __name__ == '__main__':
    app = wx.App()
    frame = MyClass(None, "Mon application")
    app.MainLoop()

Solution

  • Currently, wxPython is based on wxWidgets 3.2 which uses nanosvg to render SVG images. nanosvg does not support Gaussian blur. wxWidgets 3.3 will have a new SVG rendering library, however Gaussian blur is not currently supported in that library either.