#!/usr/bin/env python # -*- coding: utf-8 -*- __version__ = '0.0.1' __author__ = 'Michael Stangl (mistangl[-a-]syntops.de)' __copyright__ = 'Copyright 2010, Michael Stangl' __license__ = 'BSD' import optparse import os import ConfigParser from utils import CSVImport, CompleteEnding, get_translation #from django.utils.encoding import smart_unicode, smart_str from string import Template class PicError(Exception): """class for Picture createion exceptions in this module.""" pass def create_picture_frame( config ): params = dict() params['width'] = config.get('globals', 'width') params['height'] = config.get('globals', 'height') #echo '' begintpl = ''' ''' svgbegin = Template( begintpl ).substitute(params) svgend = '' return svgbegin, svgend def write_font_line( content, font, params ): ''' erzeugt den SVG Teil des Bildes aus Einzelkomponenten ''' w = Word(content, font, params) return w.GetSVG() def write_random_font_line( config, fontinfos, data ): ''' erzeugt den SVG Teil des Bildes aus einem Hintergrundbild und mehreren in Einzelbereichen zufällig platzierten Einzelbildern ''' # TODO Bild aus Zufallspositionen von Einzelkomponenten pass class Word: """Berechnet die x/y Daten jedes Buchstabn zu einem Wort bzw. mehreren Wörtern einer Zeile nach den Vorgaben """ def __init__(self, line, font, params ): self.line = line self.font = font self.params = params def __repr__(self): return self.line def calc_length(self): deltax= 0.0 for c in self.line: g = self.font.GlyphGet(c) deltax = g.GetLength() + deltax return deltax def GetSVG(self): params = self.params content = dict() content['posy'] = params['y'] # berechne immer den richtigen Startpunkt, je nach Bündigkeit if params['align'] == 'left': x = float(params['x']) elif params['align'] == 'center': word_length = self.calc_length() x = float(params['x'] + (params['length'] - word_length)/2.0) else: word_length = self.calc_length() x = float(params['x'] + word_length - params['length']) svgstr = '' for c in self.line: g = self.font.GlyphGet(c) x = g.GetLength() + x content['posx'] = str(x) svgstr = svgstr + g.GetSVG(content) return svgstr class Glyph: """enthaelt alle Daten zu einem Buchstaben """ def __init__(self, glyphname, attributes, template): self.glyphname = glyphname self.attributes = attributes self.template = template def __repr__(self): return self.glyphname def GetAttribute(self, att): return self.attributes[att] def GetLength(self): return float(self.GetAttribute('xstep')) def GetHeight(self): return float(self.GetAttribute('ystep')) def GetSVG(self, content): t = Template(self.template) return t.substitute(content) class Font: """enthaelt alle Daten zu einem Font """ def __init__(self, fontname, font_path ): self.name = fontname self.path = font_path self.glyphs = dict() fontconfig = ConfigParser.RawConfigParser() config_path = os.path.join(font_path, fontname+'.cfg') fontconfig.read(config_path) # lies alle Zeichen des Fonts ein for letter in fontconfig.sections(): # hol die Fontattribute wie Ausdehnung usw. content = dict(fontconfig.items(letter)) # lade das svg template dazu ein glyph_path = os.path.join( font_path, letter+'.svg') f = open(glyph_path, 'r') svgstr = f.read() f.close() # und bau das Zeichen auf g = Glyph(letter, content, svgstr) self.glyphs[letter] = g def __repr__(self): return repr(self.glyphs) def GlyphGet(self, glyphname): return self.glyphs[glyphname] def init_fonts( config ): ''' lädt alle benötigten Fonts für den Auftrag in den Speicher ''' fontinfos = dict() #[globals] ## was soll wohin geschrieben werden: #lines=MeineZeile, bla ## das ist die TextZeile die auf das Bild kommt #[MeineZeile] #..inhalte und wohin es kommt ## Fontname und Fonttyp #font=ausgangsschrift #fonttype=replace_strings # #[bla] # ... lines = config.get('globals', 'lines').split(',') for linename in lines: fontname = config.get(linename, 'fontname') font_path = os.path.expandvars(os.path.join('$PICCREATE_FONTS', fontname )) f = Font(fontname, font_path) fontinfos[fontname] = f return fontinfos def create_picture(config, fontinfos, data, pic_path): ''' schreibt den svg String des Bildes ''' svgstr = '' begin, end = create_picture_frame( config ) svgstr = svgstr + begin # gehe alle Zeilen die im Bild enthalten sein müssen durch lines = config.get('globals', 'lines').split(',') for linename in lines: #[ZeilenBezeichner] #content=${name} ## Ab dem Punkt wird zu schreiben begonnen #x=10 #y=20 #lenght=2000 # hol den Inhalt der Zeile die ausgeben werden muss content_template = config.get(linename, 'content') t = Template( content_template ) content = t.substitute(data) # hol dir dazu den Passenden Font für diese Zeile fontname = config.get(linename, 'fontname') font = fontinfos[fontname] # hol dir die Eckdaten für die Zeile params = dict() params['x'] = config.get(linename, 'x') params['y'] = config.get(linename, 'y') params['length']= config.get(linename, 'length') params['align']= config.get(linename, 'align') picstr = write_font_line( content, font, params ) if picstr: svgstr = svgstr + picstr randstr = write_random_font_line( content, font, params) if randstr: svgstr = svgstr + randstr svgstr = svgstr + end if options.dry: print svgstr else: f = open(pic_path, 'w') f.write( svgstr ) f.close() def main( config ): infile = options.infile config = options.config config_path = os.path.expandvars(os.path.join('$PICCREATE_CFG', config+'.cfg' )) in_path = os.path.expandvars(os.path.join('$PICCREATE_IN', infile+'.csv' )) if not config: config = 'default' if not infile: infile = 'default' out_path = options.outdir config_path = os.path.expandvars(os.path.join('$PICCREATE_CFG', CompleteEnding( config, 'cfg'))) in_path = os.path.expandvars(os.path.join('$PICCREATE_IN', CompleteEnding( infile, 'csv'))) if not os.path.exists(config_path): print '\"'+ config_path +'\" does not exist. Please give the name of a config file!' return None if not os.path.exists(in_path): print '\"'+ in_path +'\" does not exist. Please give the name to a input file!' return None if not os.path.exists(out_path): print '\"'+ out_path +'\" does not exist. Please give the path to the directory for the pictures!' return None config = ConfigParser.RawConfigParser() config.read(config_path) Trans = get_translation(config_path, 'translation') Rows = CSVImport(in_path, translate=Trans) fontinfos = init_fonts( config ) for row in Rows: filename = row.customerid print filename content = row.__dict__ del content['firstrow'] del content['row'] pic_path = os.path.join(out_path, filename+'.svg') create_picture(config, fontinfos, content, pic_path) if __name__ == '__main__': parser = optparse.OptionParser(usage="""%prog [options] Example usage ------------- Full help: $ %prog -h (or --help for possible options) Read Confg, create wakeup and scale this kind of jiffy box $ %prog -c test -i test """, version='%prog ' + __version__) parser.add_option("-c", "--cfg", dest="config", default="test", help="name of the config file with the Name of the rows to be used.", metavar="CONFIG_FILE") parser.add_option("-i", "--infile", dest="infile", help="csv file with input of names/content", action='store') parser.add_option("-o", "--outdir", dest="outdir", default=os.path.expandvars('$PICCREATE_OUT'), help="path to the directory where the maps will be generated", action='store') parser.add_option("-y", "--dry", dest="dry", help="dont generate images. Just ask the coordinates and fill database.", action='store_true' ) (options, args) = parser.parse_args() main(options.config) else: pass # vim: set tw=75 ft=python ts=4 sw=4 tw=80: