Skip to content

Instantly share code, notes, and snippets.

@superlou
Last active March 10, 2021 23:41
Show Gist options
  • Save superlou/5885625 to your computer and use it in GitHub Desktop.
Save superlou/5885625 to your computer and use it in GitHub Desktop.
Rendering SVGs in wxPython
import wx
import rsvg
import numpy
try:
import wx.lib.wxcairo
import cairo
haveCairo = True
except ImportError:
haveCairo = False
class ComponentFrame(wx.Frame):
def __init__(self, parent, id, title, pos, size):
wx.Frame.__init__(self, parent, id, title, pos, size)
self.panel = wx.Panel(self)
vbox = wx.BoxSizer(wx.HORIZONTAL)
component = SvgComponent(self.panel)
vbox.Add(component, 1, wx.EXPAND | wx.ALL, 10)
self.panel.SetSizer(vbox)
self.Show(True)
class SvgComponent(wx.PyControl):
def __init__(self, parent, label="",
id=wx.ID_ANY,
pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.NO_BORDER, validator=wx.DefaultValidator,
name="CustomMeter"):
wx.PyControl.__init__(self, parent, id, pos, size, style, validator, name)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
if not haveCairo or not wx.GraphicsRenderer.GetCairoRenderer():
print "Cairo unavailable!"
def OnPaint(self, event):
dc = wx.BufferedPaintDC(self)
self.Draw(dc)
def Draw(self, dc):
width, height = self.GetClientSize()
if not width or not height:
return
imgW = width
imgH = height
brga = numpy.ndarray(shape=(imgH, imgW, 4), dtype=numpy.uint8)
brga[:, :, 0].fill(180) # blue
brga[:, :, 1].fill(180) # green
brga[:, :, 2].fill(180) # red
rgba = numpy.ndarray(shape=(imgH, imgW, 4), dtype=numpy.uint8)
data24 = numpy.ndarray(shape=(imgH, imgW, 3), dtype=numpy.uint8)
stride = imgW * 4
surface = cairo.ImageSurface.create_for_data(brga,
cairo.FORMAT_ARGB32,
imgW,
imgH,
stride)
ctx = cairo.Context(surface)
rsvg.set_default_dpi(900)
svg = rsvg.Handle('tiger.svg')
svg.render_cairo(ctx)
rgba[:, :, 0] = brga[:, :, 2]
rgba[:, :, 1] = brga[:, :, 1]
rgba[:, :, 2] = brga[:, :, 0]
rgba[:, :, 3] = brga[:, :, 3]
data24[:, :, 0] = brga[:, :, 2]
data24[:, :, 1] = brga[:, :, 1]
data24[:, :, 2] = brga[:, :, 0]
#img = wx.ImageFromData(imgW, imgH, data24)
#bmp = wx.BitmapFromImage(img)
bmp = wx.BitmapFromBufferRGBA(imgW, imgH, rgba) # wxPython 2.8
wx.StaticBitmap(self, bitmap=bmp, size=wx.Size(width, height))
def OnSize(self, event):
self.Refresh(False)
def OnEraseBackground(self, event):
pass
def DoGetBestSize(self):
"""
Overridden base class virtual. Determines the best size of the control
based on the label size, the bitmap size and the current font.
"""
best = wx.Size(400, 400)
self.CacheBestSize(best)
return best
if __name__ == '__main__':
app = wx.App()
frame = ComponentFrame(None, wx.ID_ANY, 'test rsvg', (200, 200), (800, 800))
app.MainLoop()
import wx
import rsvg
import numpy
try:
import wx.lib.wxcairo
import cairo
haveCairo = True
except ImportError:
haveCairo = False
class ComponentFrame(wx.Frame):
def __init__(self, parent, id, title, pos, size):
wx.Frame.__init__(self, parent, id, title, pos, size)
self.panel = wx.Panel(self)
vbox = wx.BoxSizer(wx.HORIZONTAL)
component = SvgComponent(self.panel)
vbox.Add(component, 1, wx.EXPAND | wx.ALL, 10)
self.panel.SetSizer(vbox)
self.Show(True)
class SvgComponent(wx.PyControl):
def __init__(self, parent, label="",
id=wx.ID_ANY,
pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.NO_BORDER, validator=wx.DefaultValidator,
name="CustomMeter"):
wx.PyControl.__init__(self, parent, id, pos, size, style, validator, name)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
if not haveCairo or not wx.GraphicsRenderer.GetCairoRenderer():
print "Cairo unavailable!"
def OnPaint(self, event):
dc = wx.BufferedPaintDC(self)
self.Draw(dc)
def Draw(self, dc):
width, height = self.GetClientSize()
if not width or not height:
return
ctx = wx.lib.wxcairo.ContextFromDC(dc)
with open('demo.svg', 'r') as content_file:
xml_data = content_file.read()
svg = rsvg.Handle(data=xml_data)
svg.render_cairo(ctx)
def OnSize(self, event):
self.Refresh(True)
def OnEraseBackground(self, event):
pass
def DoGetBestSize(self):
"""
Overridden base class virtual. Determines the best size of the control
based on the label size, the bitmap size and the current font.
"""
best = wx.Size(400, 400)
self.CacheBestSize(best)
return best
if __name__ == '__main__':
app = wx.App()
frame = ComponentFrame(None, wx.ID_ANY, 'test rsvg', (200, 200), (400, 400))
app.MainLoop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment