diff --git a/2014/artwork/abspann.svg b/2014/artwork/abspann.svg
index d905f2a..51f47d6 100644
--- a/2014/artwork/abspann.svg
+++ b/2014/artwork/abspann.svg
@@ -148,14 +148,14 @@
id="g_background"
transform="translate(3.2142857,-29.821429)">
+ xlink:href="by-sa.svg" />
diff --git a/2014/artwork/pause.svg b/2014/artwork/pause.svg
index 7a75754..960e391 100644
--- a/2014/artwork/pause.svg
+++ b/2014/artwork/pause.svg
@@ -148,14 +148,14 @@
id="g_background"
transform="translate(3.2142857,-29.821429)">
+ style="opacity:1"
+ id="text1">
+ style="opacity:0"
+ id="text2">
+ style="opacity:1"
+ id="box">
+ style="opacity:0"
+ id="text1">
2014
%personnames
+ id="personnames"
+ style="font-size:48px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:80.00000119%;fill:#7b9199;fill-opacity:1;stroke:none;font-family:Droid Sans;-inkscape-font-specification:Droid Sans Bold">$personnames
%title
+ id="title">$title
fossgis.de/konferenz/2014/programm/events/%id.de.html
+ id="url"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:80.00000119%;fill:#f2f4f5;fill-opacity:1;stroke:none;font-family:Droid Sans;-inkscape-font-specification:Droid Sans Bold">fossgis.de/konferenz/2014/programm/events/$id.de.html
diff --git a/2014/make.py b/2014/make.py
index 3da35d4..65b759c 100755
--- a/2014/make.py
+++ b/2014/make.py
@@ -9,7 +9,9 @@ import shutil
import errno
import unicodedata
import urllib2
-import xml.etree.ElementTree as ET
+#import xml.etree.ElementTree as etree
+from lxml import etree
+import cssutils
import textwrap
import tempfile
import threading
@@ -67,6 +69,8 @@ def vorspannFilename(id, title):
def vorspannTitle(title):
return ''.join(textwrap.wrap(title, 35))
+def vorspannUrl(id):
+ return 'fossgis.de/konferenz/2014/programm/events/'+str(id)+'.de.html'
def abspannFrames():
@@ -76,24 +80,24 @@ def abspannFrames():
frames = 2*fps
for i in range(0, frames):
yield {
- '%opacity': easeOutCubic(i, 0, 1, frames),
- '%opacityLizenz': 0
+ ('banderole', 'opacity', "%.2f" % easeOutCubic(i, 0, 1, frames) ),
+ ('license', 'opacity', 0)
}
# 2 Sekunde Fadein Lizenz-Logo
frames = 2*fps
for i in range(0, frames):
yield {
- '%opacity': 1,
- '%opacityLizenz': float(i)/frames
+ ('banderole', 'opacity', 1),
+ ('license', 'opacity', "%.2f" % (float(i)/frames))
}
# 1 Sekunde stehen bleiben
frames = 1*fps
for i in range(0, frames):
yield {
- '%opacity': 1,
- '%opacityLizenz': 1
+ ('banderole', 'opacity', 1),
+ ('license', 'opacity', 1)
}
def vorspannFrames():
@@ -102,37 +106,37 @@ def vorspannFrames():
# 2 Sekunden Text 1
frames = 2*fps
for i in range(0, frames):
- yield {
- '%opacityBox': easeOutCubic(i, 0, 1, frames),
- '%opacity1': easeOutCubic(i, 0, 1, frames),
- '%opacity2': 0
- }
+ yield (
+ ('box', 'opacity', "%.2f" % easeOutCubic(i, 0, 1, frames)),
+ ('text1', 'opacity', "%.2f" % easeOutCubic(i, 0, 1, frames)),
+ ('text2', 'opacity', 0)
+ )
# 1 Sekunde Fadeout Text 1
frames = 1*fps
for i in range(0, frames):
yield {
- '%opacityBox': 1,
- '%opacity1': 1-(float(i)/frames),
- '%opacity2': 0
+ ('box', 'opacity', 1),
+ ('text1', 'opacity', "%.2f" % (1-(float(i)/frames))),
+ ('text2', 'opacity', 0)
}
# 2 Sekunden Text 2
frames = 2*fps
for i in range(0, frames):
yield {
- '%opacityBox': 1,
- '%opacity1': 0,
- '%opacity2': easeOutCubic(i, 0, 1, frames)
+ ('box', 'opacity', 1),
+ ('text1', 'opacity', 0),
+ ('text2', 'opacity', "%.2f" % easeOutCubic(i, 0, 1, frames))
}
# 2 Sekunden stehen bleiben
frames = 2*fps
for i in range(0, frames):
yield {
- '%opacityBox': 1,
- '%opacity1': 0,
- '%opacity2': 1
+ ('box', 'opacity', 1),
+ ('text1', 'opacity', 0),
+ ('text2', 'opacity', 1)
}
def pauseFrames():
@@ -142,50 +146,51 @@ def pauseFrames():
frames = 2*fps
for i in range(0, frames):
yield {
- '%opacity1': 1,
- '%opacity2': 0
+ ('text1', 'opacity', 1),
+ ('text2', 'opacity', 0)
}
# 2 Sekunden Fadeout Text1
frames = 2*fps
for i in range(0, frames):
yield {
- '%opacity1': 1-easeOutCubic(i, 0, 1, frames),
- '%opacity2': 0
+ ('text1', 'opacity', "%.2f" % (1-easeOutCubic(i, 0, 1, frames))),
+ ('text2', 'opacity', 0)
}
# 2 Sekunden Fadein Text2
frames = 2*fps
for i in range(0, frames):
yield {
- '%opacity1': 0,
- '%opacity2': easeOutCubic(i, 0, 1, frames)
+ ('text1', 'opacity', 0),
+ ('text2', 'opacity', "%.2f" % easeOutCubic(i, 0, 1, frames))
}
# 2 Sekunden Text2 stehen
frames = 2*fps
for i in range(0, frames):
yield {
- '%opacity1': 0,
- '%opacity2': 1
+ ('text1', 'opacity', 0),
+ ('text2', 'opacity', 1)
}
# 2 Sekunden Fadeout Text2
frames = 2*fps
for i in range(0, frames):
yield {
- '%opacity1': 0,
- '%opacity2': 1-easeOutCubic(i, 0, 1, frames)
+ ('text1', 'opacity', 0),
+ ('text2', 'opacity', "%.2f" % (1-easeOutCubic(i, 0, 1, frames)))
}
# 2 Sekunden Fadein Text1
frames = 2*fps
for i in range(0, frames):
yield {
- '%opacity1': easeOutCubic(i, 0, 1, frames),
- '%opacity2': 0
+ ('text1', 'opacity', "%.2f" % (easeOutCubic(i, 0, 1, frames))),
+ ('text2', 'opacity', 0)
}
+cssutils.ser.prefs.lineSeparator = ' '
def render(infile, outfile, sequence, parameters={}, workdir='artwork'):
# in debug mode we have no thread-worker which prints its progress
@@ -197,33 +202,41 @@ def render(infile, outfile, sequence, parameters={}, workdir='artwork'):
# open and parse the input file
with open(os.path.join(workdir, infile), 'r') as fp:
- svg = fp.read()
+ svgstr = fp.read()
+ for key in parameters.keys():
+ svgstr = svgstr.replace(key, str(parameters[key]))
+
+ svg = etree.fromstring(svgstr)
+
+ # find all images and force them to absolute file-urls
+ namespaces = {'xlink': 'http://www.w3.org/1999/xlink', 'svg': 'http://www.w3.org/2000/svg'}
+ for el in svg.findall(".//svg:image[@xlink:href]", namespaces=namespaces):
+ el.attrib['{http://www.w3.org/1999/xlink}href'] = 'file:///' + os.path.realpath(workdir) + '/' + el.attrib['{http://www.w3.org/1999/xlink}href']
+
# frame-number counter
frameNr = 0
# iterate through the animation seqence frame by frame
- # frame is a dictionary with key/value-pairs ("replace-pairs"), where the key
- # is searched for in the source svg-file and every occurence is replaced by
- # its companion the value
+ # frame is a ... tbd
for frame in sequence():
# print a line for each and every frame generated
if debug:
print "frameNr {0:2d} => {1}".format(frameNr, frame)
- # extend the frame-dictionary with additional replace-pairs from the arguments
- frame.update(parameters)
-
- # add some more useful replace-pairs
- frame['%workdir'] = os.path.realpath(workdir)
-
# open the output-file (named ".gen.svg" in the workdir)
with open(os.path.join(workdir, '.gen.svg'), 'w') as fp:
- # apply the replace-pairs to the input text, by replacing each key with its companion value
- gen_svg = reduce(lambda x, y: x.replace(y, str(frame[y])), frame, svg)
+ # apply the replace-pairs to the input text, by finding the specified xml-elements by thier id and modify thier css-parameter the correct value
+ for replaceinfo in frame:
+ (id, key, value) = replaceinfo
+
+ for el in svg.findall(".//*[@id='"+id.replace("'", "\\'")+"']"):
+ style = cssutils.parseStyle( el.attrib['style'] )
+ style[key] = unicode(value)
+ el.attrib['style'] = style.cssText
# write the generated svg-text into the output-file
- fp.write( gen_svg )
+ fp.write( etree.tostring(svg) )
# invoke rsvg to convert the generated svg-file into a png inside the .frames-directory
os.system('cd {0} && rsvg-convert .gen.svg > .frames/{1:04d}.png'.format(workdir, frameNr))
@@ -236,7 +249,7 @@ def render(infile, outfile, sequence, parameters={}, workdir='artwork'):
# invoke avconv aka ffmpeg and renerate a lossles-dv from the frames
# if we're not in debug-mode, suppress all output
- os.system('cd {0} && avconv -ar 48000 -ac 2 -f s16le -i /dev/zero -f image2 -i .frames/%04d.png -target pal-dv "{1}"'.format(workdir, outfile) + ('' if debug else '>/dev/null 2>&1'))
+ os.system('cd {0} && avconv -ar 48000 -ac 2 -f s16le -i /dev/zero -f image2 -i .frames/%04d.png -target pal-dv -shortest "{1}"'.format(workdir, outfile) + ('' if debug else '>/dev/null 2>&1'))
# as before, in non-debug-mode the thread-worker does all progress messages
if debug:
@@ -257,7 +270,7 @@ def events():
# use --offline to skip networking
if offline:
# parse the offline-version
- schedule = ET.parse('schedule.de.xml').getroot()
+ schedule = etree.parse('schedule.de.xml').getroot()
else:
# download the schedule
@@ -267,7 +280,7 @@ def events():
xml = response.read()
# parse into ElementTree
- schedule = ET.fromstring(xml)
+ schedule = etree.fromstring(xml)
# iterate all days
for day in schedule.iter('day'):
@@ -291,16 +304,19 @@ if debug:
render(
'vorspann.svg',
- os.path.join('..', vorspannFilename(667, title)),
+ os.path.join('..', str(667)+".dv"),
vorspannFrames,
- {'%id': 664, '%title': vorspannTitle(title), '%personnames': 'Matthias Scholz' }
+ {
+ '$id': 667,
+ '$title': vorspannTitle(title),
+ '$personnames': 'Matthias Scholz'
+ }
)
render(
'abspann.svg',
- '../abspann-by-sa.dv',
- abspannFrames,
- {'%lizenz': 'by-sa'}
+ '../outro.dv',
+ abspannFrames
)
render('pause.svg',
@@ -327,19 +343,21 @@ for (id, title, personnames) in events():
# generate a task description and put them into the queue
tasks.put((
'vorspann.svg',
- vorspannFilename(id, title),
+ str(id)+".dv",
vorspannFrames,
- {'%id':id, '%title':vorspannTitle(title), '%personnames':personnames }
+ {
+ '$id': id,
+ '$title': vorspannTitle(title),
+ '$personnames': personnames
+ }
))
-# iterate over the licences and place a task into the queue
-for lizenz in ('by-sa', 'by-nc-sa', 'cc-zero'):
- tasks.put((
- 'abspann.svg',
- 'abspann-{0}.dv'.format(lizenz),
- abspannFrames,
- {'%lizenz':lizenz}
- ))
+# place a task for the outro into the queue
+tasks.put((
+ 'abspann.svg',
+ 'outro.dv',
+ abspannFrames
+))
# place the pause-sequence into the queue
tasks.put((