From 9f4e115c9a4c043f879f1c0bdc3c4d6290230e10 Mon Sep 17 00:00:00 2001 From: Florian Festi Date: Mon, 27 Jun 2016 09:10:00 +0200 Subject: [PATCH] Support formats via pstoedit --- boxes/__init__.py | 42 ++++++++----------------- boxes/formats.py | 76 +++++++++++++++++++++++++++++++++++++++++++++ scripts/boxesserver | 4 ++- 3 files changed, 92 insertions(+), 30 deletions(-) create mode 100644 boxes/formats.py diff --git a/boxes/__init__.py b/boxes/__init__.py index ace1093..510ab15 100755 --- a/boxes/__init__.py +++ b/boxes/__init__.py @@ -21,7 +21,7 @@ from argparse import ArgumentParser import re from functools import wraps from boxes import edges -from boxes import svgutil +from boxes import formats ### Helpers @@ -169,6 +169,7 @@ class Boxes: """Main class -- Generator should sub class this """ def __init__(self): + self.formats = formats.Formats() self.argparser = ArgumentParser(description=self.__doc__) self.argparser.add_argument( "--fingerjointfinger", action="store", type=float, default=1.0, @@ -185,6 +186,10 @@ class Boxes: self.argparser.add_argument( "--output", action="store", type=str, default="box.svg", help="name of resulting file") + self.argparser.add_argument( + "--format", action="store", type=str, default="svg", + choices=self.formats.getFormats(), + help="format of resulting file") self.argparser.add_argument( "--debug", action="store", type=bool, default=False, help="print surrounding boxes for some structures") @@ -203,7 +208,8 @@ class Boxes: self.fingerHoleEdgeWidth = 1.0 # multitudes of self.thickness self.bedBoltSettings = (3, 5.5, 2, 20, 15) #d, d_nut, h_nut, l, l1 self.hexHolesSettings = (5, 3, 'circle') # r, dist, style - self._init_surface(1000, 1000) + self.surface, self.ctx = self.formats.getSurface(self.format, self.output) + self.ctx.set_line_width(2*self.burn) self._buildObjects() def buildArgParser(self, *l): @@ -265,6 +271,10 @@ class Boxes: for key,value in vars(self.argparser.parse_args(args=args)).items(): setattr(self, key, value) + # Change file ending to format if not given explicitly + if getattr(self, 'output', None) == 'box.svg': + self.output = 'box.' + getattr(self, "format", "svg") + def addPart(self, part, name=None): """ Add Edge or other part instance to this one and add it as attribute @@ -317,30 +327,6 @@ class Boxes: # Nuts self.addPart(NutHole(self, None)) - def _init_surface(self, width, height): - """ - Initialize cairo canvas - - :param width: canvas size - :param height: canvas height - - """ - #mm2pt = 90 / 25.4 / 1.25 - mm2pt = 1 - #width *= mm2pt - #height *= mm2pt #3.543307 - self.surface = cairo.SVGSurface(self.output, width, height) - self.ctx = ctx = cairo.Context(self.surface) - ctx.translate(0, height) - ctx.scale(mm2pt, -mm2pt) - - #ctx.set_source_rgb(1.0, 1.0, 1.0) - #ctx.rectangle(0, 0, width, height) - #ctx.fill() - - ctx.set_source_rgb(0.0, 0.0, 0.0) - ctx.set_line_width(2*self.burn) - def render(self): """Implement this method in your sub class. @@ -401,9 +387,7 @@ class Boxes: self.surface.flush() self.surface.finish() - svg = svgutil.SVGFile(self.output) - svg.getEnvelope() - svg.rewriteViewPort() + self.formats.convert(self.output, self.format) ############################################################ ### Turtle graphics commands diff --git a/boxes/formats.py b/boxes/formats.py new file mode 100644 index 0000000..06014a9 --- /dev/null +++ b/boxes/formats.py @@ -0,0 +1,76 @@ + +import subprocess +import tempfile +import os +import cairo +from boxes import svgutil + +class Formats: + + pstoedit = "/usr/bin/pstoedit" + + formats = { + "svg" : None, + "ps" : None, + "dxf" : "-f dxf -mm".split(), + "gcode" : "-f gcode".split(), + "plt" : "-f hpgl".split(), + } + + http_headers = { + "svg" : [('Content-type', 'image/svg+xml; charset=utf-8')], + "ps" : [('Content-type', 'application/postscript')], + "dxf" : [('Content-type', 'image/vnd.dxf')], + "plt" : [('Content-type', ' application/vnd.hp-hpgl')], + "gcode" : [('Content-type', 'text/plain; charset=utf-8')], + + # "" : [('Content-type', '')], + } + + def __init__(self): + pass + + def getFormats(self): + if os.path.isfile(self.pstoedit): + return sorted(self.formats.keys()) + else: + return ['svg', 'ps'] + + def getSurface(self, fmt, filename): + + width = height = 1000 # mm + + if fmt == "svg": + surface = cairo.SVGSurface(filename, width, height) + mm2pt = 1.0 + else: + mm2pt = 72 / 25.4 + width *= mm2pt + height *= mm2pt #3.543307 + surface = cairo.PSSurface(filename, width, height) + + ctx = cairo.Context(surface) + ctx.translate(0, height) + ctx.scale(mm2pt, -mm2pt) + + ctx.set_source_rgb(0.0, 0.0, 0.0) + + return surface, ctx + + def convert(self, filename, fmt): + + if fmt == 'svg': + svg = svgutil.SVGFile(filename) + svg.getEnvelope() + svg.rewriteViewPort() + elif fmt == "ps": + pass + else: + fd, tmpfile = tempfile.mkstemp() + cmd = [self.pstoedit] + self.formats[fmt] + [filename, tmpfile] + print(cmd) + err = subprocess.call(cmd) + if err: + # XXX show stderr output + raise ValueError("Conversion failed. pstoedit returned %i" % err) + os.rename(tmpfile, filename) diff --git a/scripts/boxesserver b/scripts/boxesserver index f49ddf3..e8aba3b 100755 --- a/scripts/boxesserver +++ b/scripts/boxesserver @@ -225,7 +225,9 @@ flex cuts, holes and slots for screws and more high level functions. return self.errorMessage(name, e) start_response(status, - [('Content-type', 'image/svg+xml; charset=utf-8')]) + box.formats.http_headers.get( + box.format, + [('Content-type', 'application/unknown; charset=utf-8')])) fd, box.output = tempfile.mkstemp() box.render() result = open(box.output).readlines()