add SVG_RENDERER setting and add support for inkscape rendering

This commit is contained in:
Laura Klünder 2017-10-17 13:03:35 +02:00
parent 206825210f
commit c7893eb26a
2 changed files with 44 additions and 11 deletions

View file

@ -5,11 +5,27 @@ import subprocess
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from itertools import chain from itertools import chain
from django.conf import settings
from django.core.checks import Error, register
from PIL import Image from PIL import Image
from shapely.affinity import scale, translate from shapely.affinity import scale, translate
from shapely.ops import unary_union from shapely.ops import unary_union
@register()
def check_svg_renderer(app_configs, **kwargs):
errors = []
if settings.SVG_RENDERER not in ('rsvg', 'inkscape'):
errors.append(
Error(
'Invalid SVG renderer: '+settings.SVG_RENDERER,
obj='settings.SVG_RENDERER',
id='c3nav.mapdata.E001',
)
)
return errors
class SVGImage: class SVGImage:
def __init__(self, bounds, scale: float=1, buffer=0): def __init__(self, bounds, scale: float=1, buffer=0):
(self.bottom, self.left), (self.top, self.right) = bounds (self.bottom, self.left), (self.top, self.right) = bounds
@ -45,17 +61,33 @@ class SVGImage:
return ET.tostring(self.get_element(buffer=buffer)).decode() return ET.tostring(self.get_element(buffer=buffer)).decode()
def get_png(self): def get_png(self):
p = subprocess.run(('rsvg-convert', '--format', 'png'), crop = False
input=self.get_xml(buffer=True).encode(), stdout=subprocess.PIPE, check=True) if settings.SVG_RENDERER == 'rsvg':
f = io.BytesIO(p.stdout) crop = True
img = Image.open(f) p = subprocess.run(('rsvg-convert', '--format', 'png'),
img = img.crop((self.buffer_px, self.buffer_px, input=self.get_xml(buffer=True).encode(), stdout=subprocess.PIPE, check=True)
self.buffer_px+int(self.width*self.scale), png = p.stdout
self.buffer_px+int(self.height*self.scale))) elif settings.SVG_RENDERER == 'inkscape':
f = io.BytesIO() p = subprocess.run(('inkscape', '-z', '-e', '/dev/stderr', '/dev/stdin'), input=self.get_xml().encode(),
img.save(f, 'PNG') stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
f.seek(0) png = p.stderr
return f.read() png = png[png.index(b'\x89PNG'):]
print(png)
else:
raise ValueError
if crop:
f = io.BytesIO(png)
img = Image.open(f)
img = img.crop((self.buffer_px, self.buffer_px,
self.buffer_px+int(self.width*self.scale),
self.buffer_px+int(self.height*self.scale)))
f = io.BytesIO()
img.save(f, 'PNG')
f.seek(0)
png = f.read()
return png
def new_defid(self): def new_defid(self):
defid = 's'+str(self.def_i) defid = 's'+str(self.def_i)

View file

@ -54,6 +54,7 @@ else:
debug_fallback = "runserver" in sys.argv debug_fallback = "runserver" in sys.argv
DEBUG = config.getboolean('django', 'debug', fallback=debug_fallback) DEBUG = config.getboolean('django', 'debug', fallback=debug_fallback)
RENDER_SCALE = float(config.get('c3nav', 'render_scale', fallback=20.0)) RENDER_SCALE = float(config.get('c3nav', 'render_scale', fallback=20.0))
SVG_RENDERER = config.get('c3nav', 'svg_renderer', fallback='rsvg')
db_backend = config.get('database', 'backend', fallback='sqlite3') db_backend = config.get('database', 'backend', fallback='sqlite3')
DATABASES = { DATABASES = {