Revision 109
org.gvsig.educa.batovi/trunk/org.gvsig.educa.batovi.activity/skeleton/GvSIGActivity.py | ||
---|---|---|
1 |
import os, shutil, stat |
|
2 |
import gtk, gobject |
|
3 |
import popen2 |
|
4 |
from os import path as Path |
|
5 |
|
|
6 |
import logging |
|
7 |
import sugar.activity.activity as activity |
|
8 |
from sugar.activity.activity import Activity |
|
9 |
from sugar.datastore import datastore |
|
10 |
|
|
11 |
""" |
|
12 |
Alternative paths to locate JRE |
|
13 |
""" |
|
14 |
JAVA_HOME_PATHS=( |
|
15 |
#"/usr/lib/jvm/jre", # gcj path DOESN'T WORK!!! |
|
16 |
str(Path.join(Path.expanduser("~"),"Activities/Java.activity/jre")), # Java activity path |
|
17 |
) |
|
18 |
|
|
19 |
# LOG level config |
|
20 |
logging.basicConfig(level=logging.DEBUG) |
|
21 |
#logging.basicConfig(level=logging.INFO) |
|
22 |
|
|
23 |
|
|
24 |
""" |
|
25 |
gvSIG batovi activity |
|
26 |
|
|
27 |
Requires: |
|
28 |
|
|
29 |
* Sugar builds > 706 |
|
30 |
|
|
31 |
* A java installed or the Java activity installed |
|
32 |
|
|
33 |
For more information see: http://www.mediagala.com/rap/foro/viewtopic.php?f=8&t=166 |
|
34 |
|
|
35 |
On first _run_ executes son post-install actions. |
|
36 |
|
|
37 |
""" |
|
38 |
class GvSIGActivity(Activity): |
|
39 |
# gvSIG Home path (where is gvSIG activity) |
|
40 |
gvsig_activity=None |
|
41 |
|
|
42 |
# gvSIG Home path (where is gvSIG installation) |
|
43 |
gvsig_home=None |
|
44 |
|
|
45 |
|
|
46 |
#Java Home |
|
47 |
java_home=None |
|
48 |
|
|
49 |
|
|
50 |
def __init__(self, handle): |
|
51 |
logging.debug('Creating GvSIG handler.') |
|
52 |
|
|
53 |
Activity.__init__(self, handle) |
|
54 |
self.handle = handle |
|
55 |
|
|
56 |
# Register run() to run from gtk_main_loop |
|
57 |
# as soon as it gets idle. |
|
58 |
# Which is kludge to make it run after the loop has begun |
|
59 |
self.idleFunc = gobject.idle_add(self.run) |
|
60 |
|
|
61 |
def run(self): |
|
62 |
# Remove run() because we want it to run only once |
|
63 |
gobject.source_remove(self.idleFunc) |
|
64 |
|
|
65 |
# locate and check jre |
|
66 |
if not self.initializeJavaHome(): |
|
67 |
# Exiting with a error |
|
68 |
self.showMessageError("Can't found any JRE to run gvSIG:\nSee http://www.mediagala.com/rap/foro/viewtopic.php?f=8&t=166\nfor more information") |
|
69 |
logging.error("No JRE found!!!") |
|
70 |
logging.debug("Closing activity"); |
|
71 |
self.close(True) |
|
72 |
return |
|
73 |
|
|
74 |
# setup environ properties |
|
75 |
self.gvsig_activity=activity.get_bundle_path() |
|
76 |
self.gvsig_home=Path.join(self.gvsig_activity, 'gvSIG') |
|
77 |
|
|
78 |
os.environ['GVSIG_HOME']=self.gvsig_home |
|
79 |
os.environ['GVSIG_ACTIVITY']=self.gvsig_activity |
|
80 |
os.environ['JAVA_HOME']=self.java_home |
|
81 |
|
|
82 |
# do post-install actions |
|
83 |
self.postInstall() |
|
84 |
|
|
85 |
# identify gvSIG launcher |
|
86 |
gvSIG_sh = Path.join(activity.get_bundle_path(), 'gvSIG', 'gvSIG.sh') |
|
87 |
|
|
88 |
if not Path.exists(gvSIG_sh): |
|
89 |
raise Exception("Missing gvSIG launcher: %s" % gvSIG_sh) |
|
90 |
|
|
91 |
# check execution permission |
|
92 |
self.fixExcecutionFilePermission(gvSIG_sh) |
|
93 |
|
|
94 |
try: |
|
95 |
logging.info("Executing '%s'" % gvSIG_sh); |
|
96 |
|
|
97 |
# execute gvSIG.sh |
|
98 |
gvSIG_process = popen2.Popen4('%s' % gvSIG_sh, 16) |
|
99 |
|
|
100 |
# writing stout in log file |
|
101 |
logging.info(gvSIG_process.fromchild.read()) |
|
102 |
|
|
103 |
# wait until gvSIG exit |
|
104 |
rcode = gvSIG_process.wait() |
|
105 |
|
|
106 |
logging.info('gvSIG.sh returned with code=%d' % rcode) |
|
107 |
|
|
108 |
finally: |
|
109 |
logging.debug("Closing activity"); |
|
110 |
self.close(True) |
|
111 |
|
|
112 |
def showMessageError(self, message): |
|
113 |
md = gtk.MessageDialog(self, |
|
114 |
gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, |
|
115 |
gtk.BUTTONS_CLOSE, message) |
|
116 |
md.run() |
|
117 |
md.destroy() |
|
118 |
|
|
119 |
""" |
|
120 |
Initialize property ``java_home`` |
|
121 |
|
|
122 |
Try to locate a valid java in ``JAVA_HOME_PATHS`` list |
|
123 |
|
|
124 |
Check that existe a *bin/java* executable file inside of it. |
|
125 |
|
|
126 |
If not JRE found returns False. Otherwise returns True |
|
127 |
""" |
|
128 |
def initializeJavaHome(self): |
|
129 |
for jhome in JAVA_HOME_PATHS: |
|
130 |
logging.debug("check jre in %s" % jhome) |
|
131 |
if not Path.exists(jhome): |
|
132 |
logging.debug("%s not found" % jhome) |
|
133 |
continue |
|
134 |
if self.checkJavaExecutable(jhome): |
|
135 |
self.java_home=jhome |
|
136 |
logging.debug("ussing '%s' for JAVA_HOME" % jhome) |
|
137 |
return True |
|
138 |
else: |
|
139 |
logging.debug("No Java available in register paths: %s" % repr(JAVA_HOME_PATHS)) |
|
140 |
return False |
|
141 |
|
|
142 |
|
|
143 |
|
|
144 |
|
|
145 |
""" |
|
146 |
Check ``javaHome`` folder: check that exist a *bin/java* executable file |
|
147 |
|
|
148 |
Returns True/False |
|
149 |
""" |
|
150 |
def checkJavaExecutable(self, javaHome): |
|
151 |
javaExe=Path.join(javaHome,"bin","java") |
|
152 |
if not Path.exists(javaExe): |
|
153 |
return False |
|
154 |
return os.access(javaExe, os.X_OK) |
|
155 |
|
|
156 |
""" |
|
157 |
Run post install actions. |
|
158 |
|
|
159 |
This actions usually will be execute just once, in first activity run |
|
160 |
""" |
|
161 |
def postInstall(self): |
|
162 |
self.installInGvSIGUserHome() |
|
163 |
self.installInUserHome() |
|
164 |
self.execScripts() |
|
165 |
|
|
166 |
""" |
|
167 |
*Post Intall process:* Excecutes install scripts |
|
168 |
|
|
169 |
This actions usually will be execute just once, in first activity run. |
|
170 |
""" |
|
171 |
def execScripts(self): |
|
172 |
# check if ther is any file to copy to |
|
173 |
sourceFolder = Path.join(activity.get_bundle_path(), 'post-install', 'scripts') |
|
174 |
|
|
175 |
if not Path.exists(sourceFolder): |
|
176 |
# No files to execute |
|
177 |
return |
|
178 |
|
|
179 |
everyScriptOk = True |
|
180 |
|
|
181 |
# for all file/dir in souceFolder |
|
182 |
scriptFiles = os.listdir(sourceFolder) |
|
183 |
|
|
184 |
for aFile in scriptFiles: |
|
185 |
fext = Path.splitext(aFile)[1] |
|
186 |
aFilePath = Path.join(sourceFolder,aFile) |
|
187 |
if fext == "py": |
|
188 |
# Exec python script |
|
189 |
execOk = self.execPython(aFilePath) |
|
190 |
if execOk: |
|
191 |
shutil.move(aFilePath,aFilePath+".done") |
|
192 |
else: |
|
193 |
everyScriptOk=False |
|
194 |
|
|
195 |
|
|
196 |
elif fext == "sh": |
|
197 |
# Exec Shell script |
|
198 |
execOk = self.execShell(aFilePath) |
|
199 |
if execOk: |
|
200 |
shutil.move(aFilePath,aFilePath+".done") |
|
201 |
else: |
|
202 |
everyScriptOk=False |
|
203 |
|
|
204 |
elif fext == "done": |
|
205 |
# Nothing to do |
|
206 |
pass |
|
207 |
|
|
208 |
else: |
|
209 |
# Ignoring file |
|
210 |
logging.debug("Ignoring post-install script: " + aFilePath) |
|
211 |
|
|
212 |
|
|
213 |
if everyScriptOk: |
|
214 |
# rename folder to avoid execution on next application open |
|
215 |
shutil.move(sourceFolder, sourceFolder+".done") |
|
216 |
|
|
217 |
""" |
|
218 |
Excecutes a python script file |
|
219 |
""" |
|
220 |
def execPython(self,aFile): |
|
221 |
logging.debug("Executing python script '%s'" % aFile); |
|
222 |
try: |
|
223 |
# open file in read-only mode |
|
224 |
f = file(aFile,"r") |
|
225 |
|
|
226 |
# exec script |
|
227 |
try: |
|
228 |
exec f |
|
229 |
finally: |
|
230 |
f.close() |
|
231 |
|
|
232 |
return True |
|
233 |
except Exception, exc: |
|
234 |
logging.error("Excecuting file %s: %s" % (aFile,exc)); |
|
235 |
return False |
|
236 |
|
|
237 |
""" |
|
238 |
Fix (set) execution permission of a file |
|
239 |
""" |
|
240 |
def fixExcecutionFilePermission(self, aFile): |
|
241 |
# check execution permission |
|
242 |
if not os.access(aFile, os.X_OK): |
|
243 |
# set excecution permission |
|
244 |
os.chmod(aFile,os.stat(aFile)+stat.S_IEXEC) |
|
245 |
|
|
246 |
""" |
|
247 |
Excecutes a shell script file |
|
248 |
""" |
|
249 |
def execShell(self,aFile): |
|
250 |
logging.debug("Executing '%s'" % aFile); |
|
251 |
try: |
|
252 |
mProcess = popen2.Popen4('%s' % aFile, 16) |
|
253 |
logging.debug(mProcess.fromchild.read()) |
|
254 |
rcode = mProcess.wait() |
|
255 |
return rcode == 0 |
|
256 |
except Exception, exc: |
|
257 |
logging.error("Excecuting file %s: %s" % (aFile,exc)); |
|
258 |
return False |
|
259 |
|
|
260 |
|
|
261 |
""" |
|
262 |
*Post Intall process:* Install files in user home |
|
263 |
|
|
264 |
Move files from ``{activity_folder}/post-install/user-home`` to ``$HOME`` |
|
265 |
|
|
266 |
**NOTE**: if a file/dir already exist **will be ignored** (Keeping untouched original files) |
|
267 |
""" |
|
268 |
def installInUserHome(self): |
|
269 |
# check if ther is any file to copy to |
|
270 |
sourceFolder = Path.join(activity.get_bundle_path(), 'post-install', 'user-home') |
|
271 |
|
|
272 |
if not Path.exists(sourceFolder): |
|
273 |
# No files to copy |
|
274 |
return |
|
275 |
|
|
276 |
homeUserFolder = Path.expanduser("~") |
|
277 |
|
|
278 |
#merge folder |
|
279 |
self.mergeFolder(sourceFolder,homeUserFolder) |
|
280 |
|
|
281 |
#rename source folder to prevent rerun of this step |
|
282 |
os.rename(sourceFolder,sourceFolder+".done") |
|
283 |
|
|
284 |
#done |
|
285 |
return |
|
286 |
|
|
287 |
""" |
|
288 |
*Post Intall process:* Install files in the gvSIG user home folder |
|
289 |
|
|
290 |
Move files from ``{activity_folder}/post-install/user-gvsig-home`` to ``$HOME/gvSIG`` |
|
291 |
""" |
|
292 |
def installInGvSIGUserHome(self): |
|
293 |
# check if ther is any file to copy to |
|
294 |
sourceFolder = Path.join(activity.get_bundle_path(), 'post-install', 'user-gvsig-home') |
|
295 |
|
|
296 |
if not Path.exists(sourceFolder): |
|
297 |
# No files to copy |
|
298 |
return |
|
299 |
|
|
300 |
homeGvsigUserFolder = Path.expanduser("~/gvSIG") |
|
301 |
|
|
302 |
if not Path.exists(homeGvsigUserFolder): |
|
303 |
# Create gvSIG user home folder |
|
304 |
os.mkdir(homeGvsigUserFolder) |
|
305 |
|
|
306 |
|
|
307 |
#move files |
|
308 |
self.mergeFolder(sourceFolder,homeGvsigUserFolder) |
|
309 |
|
|
310 |
#rename source folder to prevent rerun of this step |
|
311 |
os.rename(sourceFolder,sourceFolder+".done") |
|
312 |
|
|
313 |
#done |
|
314 |
return |
|
315 |
|
|
316 |
""" |
|
317 |
Move files from ``sourceFolder`` into ``targetFolder`` |
|
318 |
|
|
319 |
``sourceFolder`` must be a folder |
|
320 |
``targetFolder`` must be a folder or not exists (so it will be created) |
|
321 |
``overrideTarget`` if it's ``False`` raise an exception when target already contains the file/dir to move. if ``ignoreExisting`` |
|
322 |
``ignoreExisting`` modifies ``overrideTarget`` option (when it's ``False``) to don't raise an exception, just skip file/folder |
|
323 |
""" |
|
324 |
def moveFiles(self,sourceFolder,targetFolder,overrideTarget=True,ignoreExisting=True): |
|
325 |
if not Path.exists(targetFolder): |
|
326 |
# Create target folder |
|
327 |
os.makedirs(targetFolder) |
|
328 |
# set overrideTarget to True because target is new |
|
329 |
overrideTarget=True |
|
330 |
elif not Path.isdir(targetFolder): |
|
331 |
raise Exception("%s must be a dir" % targetFolder) |
|
332 |
|
|
333 |
# for all file/dir in souceFolder |
|
334 |
toMoveList = os.listdir(sourceFolder) |
|
335 |
for toMove in toMoveList: |
|
336 |
|
|
337 |
target = Path.join(targetFolder,toMove) |
|
338 |
# check if exists target |
|
339 |
if Path.exists(target): |
|
340 |
if overrideTarget: |
|
341 |
if ignoreExisting: |
|
342 |
continue |
|
343 |
|
|
344 |
else: |
|
345 |
if ignoreExisting: |
|
346 |
continue |
|
347 |
else: |
|
348 |
raise Exception("%s alredy exists in target folder %s" % (toMove, targetFolder)) |
|
349 |
|
|
350 |
|
|
351 |
# move file/dir |
|
352 |
shutil.move(Path.join(sourceFolder, toMove), targetFolder) |
|
353 |
|
|
354 |
|
|
355 |
""" |
|
356 |
Merge folder content: Copy all missing folders and files from |
|
357 |
``sourceFolder`` to ``targetFolder``. |
|
358 |
|
|
359 |
Process doesn't override existing files in ``targetFolder`` |
|
360 |
""" |
|
361 |
def mergeFolder(self,sourceFolder,targetFolder): |
|
362 |
# get folder contents |
|
363 |
names = os.listdir(sourceFolder) |
|
364 |
|
|
365 |
if not Path.exists(targetFolder): |
|
366 |
# Create target folder if not exists |
|
367 |
os.makedirs(targetFolder) |
|
368 |
|
|
369 |
for name in names: |
|
370 |
srcname = Path.join(sourceFolder, name) |
|
371 |
dstname = Path.join(targetFolder, name) |
|
372 |
if Path.isdir(srcname): |
|
373 |
# Recursive call to mergeFolder |
|
374 |
self.mergeFolder(srcname,dstname) |
|
375 |
else: |
|
376 |
if not Path.exists(dstname): |
|
377 |
# Copy new file |
|
378 |
shutil.copy(srcname,dstname) |
|
379 |
else: |
|
380 |
# skip existing file |
|
381 |
continue |
|
382 |
|
|
383 |
|
|
384 |
|
|
385 |
|
|
386 |
|
org.gvsig.educa.batovi/trunk/org.gvsig.educa.batovi.activity/skeleton/post-install/README.rst | ||
---|---|---|
1 |
=========================================== |
|
2 |
gvSIG batovi Activity Post-intall process |
|
3 |
=========================================== |
|
4 |
|
|
5 |
|
|
6 |
This folder contains all supported *post-intall* actions implemented in gvSIG activity. |
|
7 |
|
|
8 |
|
|
9 |
user-gvsig-home |
|
10 |
================ |
|
11 |
|
|
12 |
Files of this folder will be **merged** (copy only files than no exists on target folder) with *~/gvSIG* folder of user intallation in first gvSIG activity execution. |
|
13 |
|
|
14 |
|
|
15 |
After that this folder will be renamed to *user-gvsig-home.done*. |
|
16 |
|
|
17 |
|
|
18 |
user-home |
|
19 |
=========== |
|
20 |
|
|
21 |
Files of this folder will be **merged** (copy only files than no exists on target folder) to *user home* folder. |
|
22 |
|
|
23 |
After that this folder will be removed. |
|
24 |
|
|
25 |
scripts |
|
26 |
======== |
|
27 |
|
|
28 |
Excecutes contained scripts in first gvSIG activity execution. Only *Pyhon* (files ``.py``) and *Shell* (files ``.sh``) are allowed (other files will be ignored). |
|
29 |
|
|
30 |
Before all execution this environ variables will be set: |
|
31 |
|
|
32 |
* ``GVSIG_ACTIVITY``: root folder of gvSIG activity (usually ``~/Activities/org.gvsig.batovi.activity``) |
|
33 |
|
|
34 |
* ``GVSIG_HOME``: root folder of gvSIG installation (usually ``$GVSIG_ACTIVITY/gvSIG``) |
|
35 |
|
|
36 |
After the script excution will be renamed (adds ``.done``) to prevent future executions. |
|
37 |
|
|
38 |
When all script were executed, this folder will be renamed (adds ``.done``). |
|
39 |
|
|
40 |
See log file for problems in script executions. |
org.gvsig.educa.batovi/trunk/org.gvsig.educa.batovi.activity/skeleton/activity/activity.info | ||
---|---|---|
1 |
[Activity] |
|
2 |
name = gvSIG Batovi |
|
3 |
bundle_id = org.gvsig.batovi.GvSIGActivity |
|
4 |
class = GvSIGActivity.GvSIGActivity |
|
5 |
icon = activity-gvsig |
|
6 |
activity_version = ${version} |
|
7 |
host_version = 1 |
|
8 |
show_launcher = yes |
|
9 |
|
org.gvsig.educa.batovi/trunk/org.gvsig.educa.batovi.activity/skeleton/activity/activity-gvsig.svg | ||
---|---|---|
1 |
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|
2 |
<!-- Created with Inkscape (http://www.inkscape.org/) --> |
|
3 |
|
|
4 |
<svg |
|
5 |
xmlns:dc="http://purl.org/dc/elements/1.1/" |
|
6 |
xmlns:cc="http://creativecommons.org/ns#" |
|
7 |
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
|
8 |
xmlns:svg="http://www.w3.org/2000/svg" |
|
9 |
xmlns="http://www.w3.org/2000/svg" |
|
10 |
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
|
11 |
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
|
12 |
width="55" |
|
13 |
height="55" |
|
14 |
id="svg4502" |
|
15 |
sodipodi:version="0.32" |
|
16 |
inkscape:version="0.48.2 r9819" |
|
17 |
version="1.0" |
|
18 |
sodipodi:docname="logo_gvsig.svg" |
|
19 |
inkscape:output_extension="org.inkscape.output.svg.inkscape"> |
|
20 |
<defs |
|
21 |
id="defs4504" /> |
|
22 |
<sodipodi:namedview |
|
23 |
id="base" |
|
24 |
pagecolor="#ffffff" |
|
25 |
bordercolor="#666666" |
|
26 |
borderopacity="1.0" |
|
27 |
gridtolerance="10000" |
|
28 |
guidetolerance="10" |
|
29 |
objecttolerance="10" |
|
30 |
inkscape:pageopacity="0.0" |
|
31 |
inkscape:pageshadow="2" |
|
32 |
inkscape:zoom="1" |
|
33 |
inkscape:cx="32.531924" |
|
34 |
inkscape:cy="23.680342" |
|
35 |
inkscape:document-units="px" |
|
36 |
inkscape:current-layer="layer3" |
|
37 |
width="55px" |
|
38 |
height="55px" |
|
39 |
inkscape:window-width="1440" |
|
40 |
inkscape:window-height="876" |
|
41 |
inkscape:window-x="0" |
|
42 |
inkscape:window-y="24" |
|
43 |
showgrid="false" |
|
44 |
inkscape:window-maximized="1"> |
|
45 |
<inkscape:grid |
|
46 |
id="GridFromPre046Settings" |
|
47 |
type="xygrid" |
|
48 |
originx="0px" |
|
49 |
originy="0px" |
|
50 |
spacingx="15px" |
|
51 |
spacingy="15px" |
|
52 |
color="#0000ff" |
|
53 |
empcolor="#0000ff" |
|
54 |
opacity="0.2" |
|
55 |
empopacity="0.4" |
|
56 |
empspacing="5" /> |
|
57 |
</sodipodi:namedview> |
|
58 |
<metadata |
|
59 |
id="metadata4507"> |
|
60 |
<rdf:RDF> |
|
61 |
<cc:Work |
|
62 |
rdf:about=""> |
|
63 |
<dc:format>image/svg+xml</dc:format> |
|
64 |
<dc:type |
|
65 |
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
|
66 |
<dc:title></dc:title> |
|
67 |
</cc:Work> |
|
68 |
</rdf:RDF> |
|
69 |
</metadata> |
|
70 |
<g |
|
71 |
inkscape:groupmode="layer" |
|
72 |
id="layer3" |
|
73 |
inkscape:label="gvSIG" |
|
74 |
style="display:inline"> |
|
75 |
<path |
|
76 |
inkscape:connector-curvature="0" |
|
77 |
d="m 39.045533,15.464691 5.008004,0.01002 -2.83453,2.78445 -2.173474,-2.794466 z" |
|
78 |
id="path3167" |
|
79 |
style="opacity:0.9;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" /> |
|
80 |
<path |
|
81 |
inkscape:connector-curvature="0" |
|
82 |
d="m 31.753879,43.809995 2.914658,-1.171873 -0.691105,1.582529 -0.470752,1.021633 -1.752801,-1.432289 z" |
|
83 |
id="path3169" |
|
84 |
style="opacity:0.9;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" /> |
|
85 |
<path |
|
86 |
inkscape:connector-curvature="0" |
|
87 |
d="m 32.754444,44.199731 c -1.006043,-0.811367 -0.942467,-0.909284 -0.900076,-0.946376 1.029815,0.665011 1.157454,2.59338 3.343757,-1.369367 0.04861,0 -0.19716,0.182445 -0.489271,0.808227 -0.749217,1.4631 -0.57733,2.576404 -1.95441,1.507516 z M 39.015523,14.29865 c 0.02911,0.04721 0.0029,0.113605 -0.10325,0.262168 m 0,0 c -0.235226,0.329008 -0.783149,1.239702 -1.246618,2.071982 l -0.436597,0.784028 -0.99873,2.172872 c -0.211322,0.662323 -0.149824,0.340818 -0.283311,0.695752 -0.851761,2.264795 -1.136771,4.0885 -0.876162,5.606343 0.15208,0.885747 1.103754,3.671021 0.740732,2.525289 -1.055611,-3.331599 -0.374263,-0.110081 0.46825,1.548953 l 0.506476,1.676798 c -0.376992,-1.104849 -0.0094,-0.01827 0.322667,0.546688 0.144246,0.245467 -0.251526,1.103205 -0.251526,1.252601 l -2.600479,3.843859 -1.904781,2.400568 c -1.047629,1.320312 -1.898975,2.425595 -1.89188,2.456183 0.0071,0.03059 0.299529,0.287225 0.649852,0.570303 0.414154,0.334657 0.623184,0.528457 0.59759,0.55405 -0.05919,0.05919 -1.073573,0.295913 -1.758876,0.410463 -1.214277,0.20297 -2.627521,0.284616 -3.851841,0.222524 -2.343425,-0.118842 -4.647166,-0.729425 -6.776012,-1.79591 -1.783328,-0.893392 -3.089809,-1.848315 -4.586564,-3.352376 -1.624587,-1.97553 -0.953207,-1.093241 -1.961815,-2.364074 C 11.22125,34.11736 10.268777,31.576881 9.8960536,28.715131 9.7899424,27.900417 9.7903578,25.45811 9.8967473,24.641457 10.300998,21.538365 11.386492,18.82179 13.193665,16.390529 c 0.771959,-1.072328 -0.136037,0.15859 1.024592,-1.249459 0.611433,-0.701827 1.638575,-1.638054 2.499035,-2.277838 2.419486,-1.798975 5.106641,-2.880747 8.169743,-3.2889027 0.805568,-0.1073415 2.589827,-0.1495905 3.451273,-0.081722 3.420086,0.2694485 6.629524,1.5090367 9.294084,3.5896747 0.491753,0.383988 1.317771,1.110414 1.383131,1.216368 m -1.560959,22.110078 c 0.743443,-1.368642 1.546847,-2.477745 2.43279,-3.358479 0.543554,-0.540358 0.946412,-0.86191 1.492751,-1.191485 0.187925,-0.113364 0.347133,-0.222732 0.353795,-0.243039 0.0067,-0.02031 -0.194006,-0.141267 -0.445928,-0.2688 -2.012917,-1.019018 -3.59431,-2.706785 -3.912617,-4.584878 -0.0568,-0.207256 0.04596,0.280857 -0.124777,-0.398347 l -0.05745,-1.255803 0.196786,-1.446482 c 1.076898,-2.372767 1.206196,-2.516959 2.617915,-4.202801 0.407242,-0.48632 1.36236,-1.555087 1.565091,-1.745254 0.143999,-0.135075 0.142508,-0.136329 0.444611,0.373919 1.765305,2.981576 2.429605,5.568978 2.273216,8.853986 -0.09665,2.030145 -0.366432,3.61138 -0.896776,5.25613 -0.995198,3.086407 -2.835522,5.77324 -5.317913,7.764032 -0.899273,0.721188 -2.663277,1.856756 -2.749838,1.770195 -0.08036,-0.08036 0.661546,-2.174539 1.24226,-3.506548 0.185851,-0.426293 0.337909,-0.81198 0.337909,-0.857085 z m 1.398,-22.009444 c 2.8125,-0.07498 0.209333,-0.147678 2.513796,-0.272677 0.851564,-0.223161 1.96777,-0.04869 2.50391,-0.12385 -0.7399,2.071371 -0.168365,1.140579 -0.854924,1.827405 -0.686559,0.686823 -2.221305,2.710631 -2.245305,2.710631" |
|
88 |
id="path2412" |
|
89 |
style="opacity:0.9;fill:none;stroke:#eebe0e;stroke-width:1.01694441;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" |
|
90 |
sodipodi:nodetypes="ccccccccsccsssccsccscsssssccssccssssccsscsccccsssssssscccccsc" /> |
|
91 |
<path |
|
92 |
inkscape:connector-curvature="0" |
|
93 |
d="m 37.454564,36.40872 c 0.743443,-1.368643 1.546847,-2.477746 2.43279,-3.358479 0.543554,-0.540358 0.946412,-0.861911 1.492751,-1.191485 0.187925,-0.113364 0.347133,-0.222732 0.353795,-0.24304 0.0067,-0.02031 -0.194006,-0.141266 -0.445928,-0.268799 -2.012917,-1.019018 -3.212956,-2.611446 -3.912617,-4.584878 l -0.211641,-0.959123 c 0,0 -0.184842,-0.408725 0.226167,-2.141464 0.419943,-1.199861 1.309327,-2.627679 2.617915,-4.2028 0.405343,-0.487905 1.362361,-1.555088 1.565092,-1.745255 0.143998,-0.135076 0.142507,-0.136329 0.44461,0.373918 1.765306,2.981577 2.429605,5.56898 2.273216,8.853987 -0.09665,2.030145 -0.366432,3.61138 -0.896776,5.256131 -0.995198,3.086406 -2.835521,5.773238 -5.317912,7.764032 -0.587931,0.471501 -1.676121,1.213824 -2.310514,1.576147 -0.4333,0.247472 -0.417775,0.240983 -0.450374,0.188235 l 3.5e-5,-3.7e-5 c -0.06146,-0.09945 0.710462,-2.255581 1.253311,-3.500737 0.18585,-0.426292 0.337909,-0.809016 0.337909,-0.850498" |
|
94 |
id="path2410" |
|
95 |
style="opacity:0.9;fill:#3e83c3;stroke-width:25.21345139;stroke-miterlimit:4;stroke-dasharray:none" |
|
96 |
sodipodi:nodetypes="csscscccsssssssccsc" /> |
|
97 |
<path |
|
98 |
inkscape:connector-curvature="0" |
|
99 |
d="m 38.532721,14.407793 c 0.02821,0.04693 0.0028,0.112922 -0.100075,0.260591 m 0,0 c -0.227984,0.327031 -0.759034,1.232252 -1.208229,2.059531 l -0.423152,0.779316 -0.967975,2.159815 c -0.204814,0.658339 -0.145209,0.338769 -0.274585,0.691571 -0.825532,2.251184 -1.101765,4.063927 -0.84918,5.57265 0.147397,0.880422 0.207888,0.829618 0.65437,1.933026 0.270532,0.668576 -0.05279,0.341313 0.763786,1.990376 l 0.675684,1.287657 c -0.36538,-1.098208 0.237371,0.803143 0.374334,1.048822 0.136967,0.245677 0.187432,0.843867 0.187432,0.992362 l -3.444425,4.073469 -1.846122,2.386141 c -1.015368,1.312379 -1.840495,2.411021 -1.83362,2.441424 0.0071,0.03039 0.290304,0.285499 0.62984,0.566875 0.401399,0.332643 0.603993,0.525281 0.579186,0.550718 -0.05738,0.05884 -1.040514,0.294133 -1.70471,0.407995 -1.176884,0.201755 -2.546606,0.282908 -3.733226,0.221191 -2.271253,-0.118132 -4.504052,-0.725046 -6.567338,-1.785119 -1.728412,-0.888022 -2.994658,-1.837211 -4.445323,-3.332227 -1.574555,-1.963658 -0.923851,-1.086672 -1.9014,-2.349867 -1.503627,-2.256711 -2.426764,-4.781923 -2.788011,-7.626475 -0.102841,-0.809818 -0.102439,-3.237448 6.73e-4,-4.049193 0.391801,-3.084444 1.443869,-5.784691 3.195389,-8.201343 0.748189,-1.065882 -0.131846,0.157639 0.99304,-1.241949 0.592603,-0.697611 1.588114,-1.628211 2.422078,-2.264149 2.344977,-1.788164 4.949384,-2.863436 7.918155,-3.269138 0.780762,-0.1066957 2.510073,-0.1486915 3.344992,-0.08123 3.314765,0.2678291 6.425367,1.4999688 9.007873,3.5681018 0.476609,0.381681 1.494986,0.96972 1.340537,1.209059" |
|
100 |
id="path2412-0" |
|
101 |
style="opacity:0.9;fill:#eebe0e;fill-opacity:1;stroke:none" |
|
102 |
sodipodi:nodetypes="cccsccsssccsccscsssssccssccssssc" /> |
|
103 |
<path |
|
104 |
style="fill:#ffffff;fill-opacity:1;stroke:none" |
|
105 |
d="m 43.5746,14.52427 -4.065864,-0.08839 c -1.473139,3.240906 -7.080337,8.589903 -1.90035,18.163806 -2.268556,3.962783 -4.435019,6.09836 -6.584932,9.501746 l 2.253903,1.811963 c 1.753035,-2.268634 1.569667,-2.495936 3.623922,-7.689787 1.459857,-2.14221 1.900097,-3.277945 4.154252,-4.419418 -1.656469,-0.763306 -3.061836,-2.341526 -3.800698,-3.668116 -0.525075,-1.592748 -0.796986,-3.819661 0.08838,-5.61266 0.99004,-1.454308 2.187197,-3.412551 2.96101,-4.110059 0.966867,-1.027473 2.165514,-2.681112 3.270373,-3.889085 z" |
|
106 |
id="path4065" |
|
107 |
inkscape:connector-curvature="0" |
|
108 |
sodipodi:nodetypes="ccccccccccc" /> |
|
109 |
</g> |
|
110 |
</svg> |
Also available in: Unified diff