[gcompris/gcomprismusic] added convert to .wav song file feature



commit cc8152adeb8c8d0fd33ae42401ca54c3cab44145
Author: Karthik Subramanian <itskarthik s gmail com>
Date:   Tue Jul 12 11:51:25 2011 +0530

    added convert to .wav song file feature

 src/piano-activity/piano.py                        |   54 ++++-
 src/piano-activity/pysynth.py                      |  284 ++++++++++++++++++++
 .../resources/piano/convert_icon.svg               |  185 +++++++++++++
 3 files changed, 518 insertions(+), 5 deletions(-)
---
diff --git a/src/piano-activity/piano.py b/src/piano-activity/piano.py
index 8886295..e8e5208 100644
--- a/src/piano-activity/piano.py
+++ b/src/piano-activity/piano.py
@@ -24,6 +24,7 @@ import gcompris.skin
 import gcompris.bonus
 import gcompris.sound
 import goocanvas
+import pysynth
 import ConfigParser
 import pango
 import time
@@ -364,7 +365,7 @@ class Gcompris_piano:
     self.loadicon = goocanvas.Image(
         parent = self.rootitem,
         x = 650,
-        y = 270,
+        y = 300,
         width = 60,
         height = 60,
         pixbuf = gcompris.utils.load_pixmap("piano/loadicon.svg")
@@ -384,6 +385,18 @@ class Gcompris_piano:
     gcompris.utils.item_focus_init(self.labelicon, None)
     gcompris.utils.item_focus_init(self.pianosizeicon, None)
 
+
+    # Convert Icon
+    self.converticon = goocanvas.Image(
+        parent = self.rootitem,
+        x = 650,
+        y = 390,
+        width = 60,
+        height = 60,
+        pixbuf = gcompris.utils.load_pixmap("piano/convert_icon.svg")
+        )
+    gcompris.utils.item_focus_init(self.converticon, None)
+
     # Displays the status of whether notes are currently being saved or not
     self.savestatus = goocanvas.Text(
        parent = self.rootitem,
@@ -397,7 +410,7 @@ class Gcompris_piano:
        )
 
     self.pianosizeicon.connect("button-press-event", self.change_size)
-
+    self.converticon.connect("button-press-event", self.convert_notes)
     self.saveicon.connect("button-press-event", self.save_notes)
     self.labelicon.connect("button-press-event", self.show_label)
     self.loadicon.connect("button-press-event", self.load_file)
@@ -426,6 +439,32 @@ class Gcompris_piano:
                                 )
     self.pianobg2.translate(375, 200)
 
+  def convert_notes(self, item, event, attr):
+
+     gcompris.file_selector_load( self.gcomprisBoard,  self.selector_section, self.file_type, convert_load, self)
+
+     print 'Converting'
+
+  def convert_to_wav(self, filename):
+     file = open(filename, 'rb')
+     fname = filename.replace('.gcpiano','.wav')
+     try:
+       song = []
+       notes = file.read()
+       notesarray = notes.split(' ')
+       print notesarray
+       for note in notesarray: 
+            if len(note)==3:
+              note[1]='#'
+            elif note=='':
+              break
+            song.append((''+note+'',3))
+       song.append(('r',3))
+       pysynth.make_wav(song,fn=fname)
+       
+     except: 
+       file.close()
+
   def change_size(self, item, event, attr):
      if self.pianosize == 1 :
         self.setpiano(2)
@@ -456,13 +495,13 @@ class Gcompris_piano:
 
   def save_notes(self, item, event, attr):
     if self.save == False :
-       self.save = True
+       
        gcompris.file_selector_save( self.gcomprisBoard, self.selector_section,
                                     self.file_type,
                                    general_save, self)
 
 
-       self.savestatus.props.text = "Saving.."
+       
 
     else :
        if self.save is True:
@@ -630,7 +669,7 @@ class Gcompris_piano:
        self.setpiano(2)
        self.pianosize = 2
        self.currentsong = self.bday
-       self.titletext.props.text = 'Happy Birthday tune (Pentatonic Scale)'
+       self.titletext.props.text = 'Happy Birthday tune'
        self.notestext.props.text = 'G G A G C3 B G G A G D3 C3 G G  G3 E3 C3 B A F3 F3 E3 D3 C3'
     elif level == 6:
        self.noteslength = 41
@@ -663,8 +702,13 @@ class Gcompris_piano:
 def general_save( filename, filetype, fles):
 
      #print filename
+     fles.save = True
+     fles.savestatus.props.text = "Saving.."
      fles.piano_to_file(filename)
 def general_load( filename, filetype, fles):
 
      fles.file_to_piano(filename)
 
+def convert_load(filename, filetype, fles):
+
+     fles.convert_to_wav(filename)
diff --git a/src/piano-activity/pysynth.py b/src/piano-activity/pysynth.py
new file mode 100755
index 0000000..83ad648
--- /dev/null
+++ b/src/piano-activity/pysynth.py
@@ -0,0 +1,284 @@
+#!/usr/bin/env python
+# -*- coding: latin-1 -*-
+
+"""
+##########################################################################
+#                       * * *  PySynth  * * *
+#       A very basic audio synthesizer in Python (www.python.org)
+#
+#          Martin C. Doege, 2009-04-07 (mdoege compuserve com)
+##########################################################################
+# Based on a program by Tyler Eaves (tyler at tylereaves.com) found at
+#   http://mail.python.org/pipermail/python-list/2000-August/049968.html
+##########################################################################
+
+# 'song' is a Python list (or tuple) in which the song is defined,
+#   the format is [['note', value]]
+
+# Notes are 'a' through 'g' of course,
+# optionally with '#' or 'b' appended for sharps or flats.
+# Finally the octave number (defaults to octave 4 if not given).
+# An asterisk at the end makes the note a little louder (useful for the beat).
+# 'r' is a rest.
+
+# Note value is a number:
+# 1=Whole Note; 2=Half Note; 4=Quarter Note, etc.
+# Dotted notes can be written in two ways:
+# 1.33 = -2 = dotted half
+# 2.66 = -4 = dotted quarter
+# 5.33 = -8 = dotted eighth
+"""
+
+# Example 1: The C major scale
+song1 = [
+['c',4],['d',4],['e',4],['f',4],['g',4],['a',4],['b',4],['c5',2],['r',1],
+['c3',4],['d3',4],['e3',4],['f3',4],['g3',4],['a3',4],['b3',4],['c4',2],['r',1],
+['c1*', 1], ['c2*', 1], ['c3*', 1], ['c4*', 1], ['c5*', 1], ['c6*', 1], ['c7*', 1], ['c8*', 1],
+]
+
+# Example 2: Something a little more patriotic
+song2 = (
+  ('g', -8), ('e', 16),
+  ('c*', 4), ('e', 4), ('g', 4),
+  ('c5*', 2), ('e5', -8), ('d5', 16),
+  ('c5*', 4), ('e', 4), ('f#', 4),
+  ('g*', 2), ('g', 8), ('g', 8),
+  ('e5*', -4), ('d5', 8), ('c5', 4),
+  ('b*', 2), ('a', -8), ('b', 16),
+  ('c5*', 4), ('c5', 4), ('g', 4),
+  ('e*', 4), ('c', 4),
+)
+
+# Example 3: Beginning of Nocturne Op. 9 #2 by F. Chopin
+song3 = (
+  ('bb', 8),
+  ('g5*', 2), ('f5', 8), ('g5', 8), ('f5', -4), ('eb5', 4), ('bb', 8),
+  ('g5*', 4), ('c5', 8), ('c6', 4), ('g5', 8), ('bb5', -4), ('ab5', 4), ('g5', 8),
+  ('f5*', -4), ('g5', 4), ('d5', 8), ('eb5', -4), ('c5', -4),
+  ('bb*', 8), ('d6', 8), ('c6', 8), ('bb5', 16), ('ab5', 16), ('g5', 16), ('ab5', 16), ('c5', 16), ('d5', 16), ('eb5', -4),
+)
+
+# Example 4: J.S. Bach: Bourré(from BWV 996)
+song4_rh = (
+  ('e', 8), ('f#', 8),
+  ('g*', 4), ('f#', 8), ('e', 8), ('d#*', 4), ('e', 8), ('f#', 8),
+  ('b3*', 4), ('c#', 8), ('d#', 8), ('e*', 4), ('d', 8), ('c', 8),
+  ('b3*', 4), ('a3', 8), ('g3', 8), ('f#3*', 4), ('g3', 8), ('a3', 8),
+  ('b3*', 8), ('a3', 8), ('g3', 8), ('f#3', 8), ('e3*', 4), ('e', 8), ('f#', 8),
+  ('g*', 4), ('f#', 8), ('e', 8), ('d#*', 4), ('e', 8), ('f#', 8),
+  ('b3*', 4), ('c#', 8), ('d#', 8), ('e*', 4), ('d', 8), ('c', 8),
+  ('b3*', 4), ('a3', 8), ('g3', 8), ('g3*', 32), ('f#3*', 32), ('g3*', 32), ('f#3*', 32), ('g3*', 32), ('f#3*', 32), ('g3*', 32), ('f#3*', 6.4), ('g3', 8), ('g3*', -2),
+)
+# version without the trill:
+#  ('b3*', 4), ('a3', 8), ('g3', 8), ('f#3*', -4), ('g3', 8), ('g3*', -2),
+
+song4_lh = (
+  ('g2', 8), ('f#2', 8),
+  ('e2*', 4), ('a2', 4), ('b2', 4), ('a2', 4),
+  ('g2*', 4), ('f#2', 4), ('e2', 4), ('f#2', 4),
+  ('g2*', 4), ('a2', 4), ('b2', 4), ('a2', 4),
+  ('g2*', 4), ('b2', 4), ('e2', 8), ('f#2', 8), ('g2', 8), ('f#2', 8),
+  ('e2*', 4), ('a2', 4), ('b2', 4), ('a2', 4),
+  ('g2*', 4), ('f#2', 4), ('e2', 4), ('f#2', 4),
+  ('g2*', 4), ('c3', 4), ('d3', 4), ('d3', 4),
+  ('b2*', -2),
+)
+
+##########################################################################
+# Compute and print piano key frequency table
+##########################################################################
+pitchhz = {}
+keys_s = ('a', 'a#', 'b', 'c', 'c#', 'd', 'd#', 'e', 'f', 'f#', 'g', 'g#')
+keys_f = ('a', 'bb', 'b', 'c', 'db', 'd', 'eb', 'e', 'f', 'gb', 'g', 'ab')
+
+if __name__ == '__main__':
+    print "Piano key frequencies (for equal temperament):"
+    print "Key number\tScientific name\tFrequency (Hz)"
+for k in range(88):
+    freq = 27.5 * 2.**(k/12.)
+    oct = (k+9) // 12
+    note = '%s%u' % (keys_s[k%12], oct)
+    if __name__ == '__main__':
+        print "%10u\t%15s\t%14.2f" % (k+1, note.upper(), freq)
+    pitchhz[note] = freq
+    note = '%s%u' % (keys_f[k%12], oct)
+    pitchhz[note] = freq
+
+##########################################################################
+#### Main program starts below
+##########################################################################
+# Some parameters:
+
+# Beats (quarters) per minute
+# e.g. bpm = 95
+
+# Octave shift (neg. integer -> lower; pos. integer -> higher)
+# e.g. transpose = 0
+
+# Pause between notes as a fraction (0. = legato and e.g., 0.5 = staccato)
+# e.g. pause = 0.05
+
+# Volume boost for asterisk notes (1. = no boost)
+# e.g. boost = 1.2
+
+# Output file name
+#fn = 'pysynth_output.wav'
+
+# Other parameters:
+
+# Influences the decay of harmonics over frequency. Lowering the
+# value eliminates even more harmonics at high frequencies.
+# Suggested range: between 3. and 5., depending on the frequency response
+#  of speakers/headphones used
+harm_max = 4.
+##########################################################################
+
+import wave, math, struct
+
+def make_wav(song,bpm=120,transpose=0,pause=.05,boost=1.1,repeat=0,fn="out.wav"):
+	f=wave.open(fn,'w')
+
+	f.setnchannels(1)
+	f.setsampwidth(2)
+	f.setframerate(44100)
+	f.setcomptype('NONE','Not Compressed')
+
+	bpmfac = 120./bpm
+
+	def length(l):
+	    return 88200./l*bpmfac
+
+	def waves2(hz,l):
+	    a=44100./hz
+	    b=float(l)/44100.*hz
+	    return [a,round(b)]
+
+	def sixteenbit(x):
+	    return struct.pack('h', round(32000*x))
+
+	def asin(x):
+	    return math.sin(2.*math.pi*x)
+
+	def render2(a,b,vol):
+	    b2 = (1.-pause)*b
+	    l=waves2(a,b2)
+	    ow=""
+	    q=int(l[0]*l[1])
+
+	    # harmonics are frequency-dependent:
+	    lf = math.log(a)
+	    lf_fac = (lf-3.) / harm_max
+	    if lf_fac > 1: harm = 0
+	    else: harm = 2. * (1-lf_fac)
+	    decay = 2. / lf
+	    t = (lf-3.) / (8.5-3.)
+	    volfac = 1. + .8 * t * math.cos(math.pi/5.3*(lf-3.))
+
+	    for x in range(q):
+	         fac=1.
+	         if x<100: fac=x/80.
+	         if 100<=x<300: fac=1.25-(x-100)/800.
+	         if x>q-400: fac=1.-((x-q+400)/400.)
+	         s = float(x)/float(q)
+	         dfac =  1. - s + s * decay
+	         ow=ow+sixteenbit((asin(float(x)/l[0])
+	              +harm*asin(float(x)/(l[0]/2.))
+	              +.5*harm*asin(float(x)/(l[0]/4.)))/4.*fac*vol*dfac*volfac)
+	    fill = max(int(ex_pos - curpos - q), 0)
+	    f.writeframesraw((ow)+(sixteenbit(0)*fill))
+	    return q + fill
+
+	##########################################################################
+	# Write to output file (in WAV format)
+	##########################################################################
+
+	print "Writing to file", fn
+	curpos = 0
+	ex_pos = 0.
+	for rp in range(repeat+1):
+		for nn, x in enumerate(song):
+		    if not nn % 4:
+		        print "[%u/%u]\t" % (nn+1,len(song))
+		    if x[0]!='r':
+		        if x[0][-1] == '*':
+		            vol = boost
+		            note = x[0][:-1]
+		        else:
+		            vol = 1.
+		            note = x[0]
+			try:
+		            a=pitchhz[note]
+			except:
+		            a=pitchhz[note + '4']	# default to fourth octave
+		        a = a * 2**transpose
+		        if x[1] < 0:
+		            b=length(-2.*x[1]/3.)
+		        else:
+		            b=length(x[1])
+			ex_pos = ex_pos + b
+		        curpos = curpos + render2(a,b,vol)
+
+		    if x[0]=='r':
+		        b=length(x[1])
+			ex_pos = ex_pos + b
+		        f.writeframesraw(sixteenbit(0)*int(b))
+			curpos = curpos + int(b)
+
+	f.writeframes('')
+	f.close()
+	print
+
+def mix_files(a, b, c, chann = 2, phase = -1.):
+	f1 = wave.open(a,'r')
+	f2 = wave.open(b,'r')
+	f3 = wave.open(c,'w')
+	f3.setnchannels(chann)
+	f3.setsampwidth(2)
+	f3.setframerate(44100)
+	f3.setcomptype('NONE','Not Compressed')
+	frames = min(f1.getnframes(), f2.getnframes())
+
+	print "Mixing files, total length %.2f s..." % (frames / 44100.)
+	d1 = f1.readframes(frames)
+	d2 = f2.readframes(frames)
+	for n in range(frames):
+		if not n%(5*44100): print n // 44100, 's'
+		if chann < 2:
+			d3 = struct.pack('h',
+				.5 * (struct.unpack('h', d1[2*n:2*n+2])[0] +
+				struct.unpack('h', d2[2*n:2*n+2])[0]))
+		else:
+			d3 = ( struct.pack('h',
+				phase * .3 * struct.unpack('h', d1[2*n:2*n+2])[0] +
+				.7 * struct.unpack('h', d2[2*n:2*n+2])[0]) +
+				struct.pack('h',
+				.7 * struct.unpack('h', d1[2*n:2*n+2])[0] +
+				phase * .3 * struct.unpack('h', d2[2*n:2*n+2])[0]) )
+		f3.writeframesraw(d3)
+	f3.close()
+
+##########################################################################
+# Synthesize demo songs
+##########################################################################
+
+if __name__ == '__main__':
+	print
+	print "Creating Demo Songs... (this might take about a minute)"
+	print
+
+	# SONG 1
+	make_wav(song1, fn = "pysynth_scale.wav")
+
+	# SONG 2
+	make_wav(song2, bpm = 95, boost = 1.2, fn = "pysynth_anthem.wav")
+
+	# SONG 3
+	make_wav(song3, bpm = 132/2, pause = 0., boost = 1.1, fn = "pysynth_chopin.wav")
+
+	# SONG 4
+	#   right hand part
+	make_wav(song4_rh, bpm = 130, transpose = 1, pause = .1, boost = 1.15, repeat = 1, fn = "pysynth_bach_rh.wav")
+	#   left hand part
+	make_wav(song4_lh, bpm = 130, transpose = 1, pause = .1, boost = 1.15, repeat = 1, fn = "pysynth_bach_lh.wav")
+	#   mix both files together
+	mix_files("pysynth_bach_rh.wav", "pysynth_bach_lh.wav", "pysynth_bach.wav")
diff --git a/src/piano-activity/resources/piano/convert_icon.svg b/src/piano-activity/resources/piano/convert_icon.svg
new file mode 100644
index 0000000..8f492d3
--- /dev/null
+++ b/src/piano-activity/resources/piano/convert_icon.svg
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   xmlns:xlink="http://www.w3.org/1999/xlink";
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape";
+   width="218.16225"
+   height="217.35884"
+   id="svg3110"
+   version="1.1"
+   inkscape:version="0.48.1 "
+   sodipodi:docname="New document 2">
+  <defs
+     id="defs3112">
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3946">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3948" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop3950" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3693-7"
+       id="linearGradient2924"
+       gradientUnits="userSpaceOnUse"
+       x1="-495.71429"
+       y1="875.21936"
+       x2="-495.71429"
+       y2="209.50504" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3693-7">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3695-4" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop3697-0" />
+    </linearGradient>
+    <filter
+       inkscape:collect="always"
+       id="filter3932"
+       color-interpolation-filters="sRGB">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="2.1415432"
+         id="feGaussianBlur3934" />
+    </filter>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3946"
+       id="linearGradient3952"
+       x1="-1181.7566"
+       y1="-115.88824"
+       x2="-154.17836"
+       y2="883.38348"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3693-7"
+       id="linearGradient3962"
+       gradientUnits="userSpaceOnUse"
+       x1="-495.71429"
+       y1="875.21936"
+       x2="-495.71429"
+       y2="209.50504" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3946"
+       id="linearGradient3964"
+       gradientUnits="userSpaceOnUse"
+       x1="-1181.7566"
+       y1="-115.88824"
+       x2="-154.17836"
+       y2="883.38348" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.24748737"
+     inkscape:cx="187.55357"
+     inkscape:cy="100.1766"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:window-width="1280"
+     inkscape:window-height="744"
+     inkscape:window-x="-4"
+     inkscape:window-y="-4"
+     inkscape:window-maximized="1" />
+  <metadata
+     id="metadata3115">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-29.86263,-37.103949)">
+    <g
+       id="g3954"
+       transform="matrix(0.49056853,0,0,0.49056853,-2.6238144,-8.8524339)">
+      <path
+         sodipodi:type="arc"
+         style="fill:none;stroke:#008000;stroke-width:30;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+         id="path2930"
+         sodipodi:cx="-495.71429"
+         sodipodi:cy="542.36218"
+         sodipodi:rx="332.85715"
+         sodipodi:ry="332.85715"
+         d="m -162.85715,542.36218 c 0,183.83193 -149.02522,332.85715 -332.85714,332.85715 -183.83193,0 -332.85715,-149.02522 -332.85715,-332.85715 0,-183.83192 149.02522,-332.85714 332.85715,-332.85714 183.83192,0 332.85714,149.02522 332.85714,332.85714 z"
+         transform="matrix(0.63921388,0,0,0.63685992,605.43889,-30.189412)" />
+      <path
+         d="m -162.85715,542.36218 c 0,183.83193 -149.02522,332.85715 -332.85714,332.85715 -183.83193,0 -332.85715,-149.02522 -332.85715,-332.85715 0,-183.83192 149.02522,-332.85714 332.85715,-332.85714 183.83192,0 332.85714,149.02522 332.85714,332.85714 z"
+         sodipodi:ry="332.85715"
+         sodipodi:rx="332.85715"
+         sodipodi:cy="542.36218"
+         sodipodi:cx="-495.71429"
+         id="path3790"
+         style="fill:#ccff00;fill-opacity:1;stroke:none"
+         sodipodi:type="arc"
+         transform="matrix(0.55942056,0,0,0.55736044,565.8842,12.928098)" />
+      <path
+         id="path2999"
+         d="m 288.55771,129.68947 c -102.83936,0 -186.19265,83.06921 -186.19265,185.52986 0,102.46065 83.35329,185.52986 186.19265,185.52986 102.83936,0 186.22009,-83.06921 186.22009,-185.52986 0,-102.46065 -83.38073,-185.52986 -186.22009,-185.52986 z m 47.03412,56.94228 c 2.78767,-0.39886 3.99568,4.54503 5.69447,6.11917 13.26093,23.48705 27.48896,46.85193 38.73882,71.33368 15.16784,32.80939 2.76333,80.09864 -30.6899,94.47886 -19.11489,6.05745 -23.58517,-23.40079 -8.21318,-30.90748 24.63895,-20.46337 11.39616,-55.9327 2.08067,-81.13568 l -27.24037,93.45901 c -12.56062,33.90618 -13.5354,79.84903 -48.34823,98.78494 -36.90266,18.94012 -83.6128,-18.47057 -76.13614,-59.80355 3.48816,-44.01304 63.65585,-64.42389 91.65904,-31.5024 l 30.38875,-99.46487 c 7.6151,-19.78493 10.13275,-43.11266 20.77934,-60.82342 0.46945,-0.29986 0.88849,-0.48129 1.28673,-0.53826 z"
+         style="fill:#008000;fill-opacity:1;stroke:none"
+         inkscape:connector-curvature="0" />
+      <path
+         transform="matrix(0.55942056,0,0,0.55736044,565.8842,12.928098)"
+         sodipodi:type="arc"
+         style="opacity:0.6419214;fill:url(#linearGradient3962);fill-opacity:1;stroke:none"
+         id="path2936"
+         sodipodi:cx="-495.71429"
+         sodipodi:cy="542.36218"
+         sodipodi:rx="332.85715"
+         sodipodi:ry="332.85715"
+         d="m -162.85715,542.36218 c 0,183.83193 -149.02522,332.85715 -332.85714,332.85715 -183.83193,0 -332.85715,-149.02522 -332.85715,-332.85715 0,-183.83192 149.02522,-332.85714 332.85715,-332.85714 183.83192,0 332.85714,149.02522 332.85714,332.85714 z" />
+      <path
+         style="opacity:0.23451329;fill:#ffffff;fill-opacity:0.96446701;stroke:none;filter:url(#filter3932)"
+         d="m 288.88587,127.45467 c -102.83935,0 -186.21065,83.04378 -186.21065,185.50441 0,59.85955 28.47349,113.09986 72.64148,147.02245 -29.94442,-32.9227 -48.18773,-76.59435 -48.18773,-124.52341 0,-102.46063 83.37129,-185.52491 186.21064,-185.52491 42.74474,0 82.12002,14.35399 113.54866,38.48197 -34.06874,-37.44551 -83.27972,-60.96051 -138.0024,-60.96051 z"
+         id="path2934"
+         inkscape:connector-curvature="0" />
+      <path
+         transform="matrix(0.63921388,0,0,0.63685992,605.43889,-30.189412)"
+         d="m -162.85715,542.36218 c 0,183.83193 -149.02522,332.85715 -332.85714,332.85715 -183.83193,0 -332.85715,-149.02522 -332.85715,-332.85715 0,-183.83192 149.02522,-332.85714 332.85715,-332.85714 183.83192,0 332.85714,149.02522 332.85714,332.85714 z"
+         sodipodi:ry="332.85715"
+         sodipodi:rx="332.85715"
+         sodipodi:cy="542.36218"
+         sodipodi:cx="-495.71429"
+         id="path3936"
+         style="fill:none;stroke:url(#linearGradient3964);stroke-width:30;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+         sodipodi:type="arc" />
+    </g>
+  </g>
+</svg>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]