Compare commits

...

No commits in common. "81b9a25d7170e1f57ac1ec78544ef8e3c42b08ec" and "6c079839c2bf5fd4a7555d6316666374ee561c06" have entirely different histories.

1693 changed files with 547574 additions and 111 deletions

26
.gitignore vendored Normal file
View file

@ -0,0 +1,26 @@
/wiki/backups/*
*~
*.tar.*
.[^.]*
*.o
*.os
*.gch
,valgrind.log*
*.pyc
/.sconf_temp
/.settings
optcache
Makefile.in
build/*
target/*
autom4te.cache/*
scripts/*
configure
config.log
aclocal.m4
autom4te.cache
semantic.cache
wiki/backups/*
doc/devel/draw/*.png
doc/devel/uml/fig128309.png
m4/*

83
AUTHORS Normal file
View file

@ -0,0 +1,83 @@
Lumiera Authors and Credits
===========================
Version: 0.pre.03
:Date: 11/2015
|==========================================
|*Architecture and Design*|
|graphical
user interface | JOEL HOLDSWORTH
| | HERMANN VOSSELER
| | BRIAN RYTEL
|processing layer | HERMANN VOSSELER
|backend | CHRISTIAN THÄTER
| |
| |
|*Workflow design* |
|concept | BRIAN RYTEL
| | MIKE PROVOST
| | NIKOLA DUPER
| | CHRISTOPH VARGA
| |
| |
|*Programming*|
|session and engine| HERMANN VOSSELER
|backend | CHRISTIAN THÄTER
| | MICHAEL PLOUJNIKOV
|graphical
user interface| JOEL HOLDSWORTH
| | STEFAN KANGAS
| | MICHAEL FISHER
|library | HERMANN VOSSELER
| | CHRISTIAN THÄTER
| | ANTON YAKOVLEV
| | STEFAN KANGAS
|testsuite | CHRISTIAN THÄTER
| | NICHOLAS SINNOTT-ARMSTRONG
| | HERMANN VOSSELER
| |
| |
|*Programming Documentation*|
| | CHRISTIAN THÄTER
| | HERMANN VOSSELER
| | MICHAEL PLOUJNIKOV
| | ODIN HØRTHE OMDAL
| | SIMEON VÖLKEL
| | MANO STIENEN
| | HENDRIK BOOM
| | BENNY LYONS
| |
| |
|*Server Administration*|
| | CHRISTIAN THÄTER
|==========================================
Cinelerra
---------
Lumiera is an offspring of the Cinelerra video editor. +
It started out as a partial rewrite of Cinelerra in 2007
and turned into a complete rewrite and redesign in Spring 2008
The Lumiera project feels especially obliged to::
* Cinelerra's original Author, *Adam Williams* (aka.``Jack Crossfire''/ ``HV'')
* Cinelerra-CV and all the numerous contributors to the ``Community Version''
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Further Credits
---------------
- inspirations and some UI components were taken from http://Ardour.org[Ardour]
- Parts of the Implementation are heavily inspired by +
*The Loki Library* (c) 2001 by *Andrei Alexandrescu*

340
COPYING Normal file
View file

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

1
DIR_INFO Normal file
View file

@ -0,0 +1 @@
Root of the main Lumiera project tree

1
INSTALL Symbolic link
View file

@ -0,0 +1 @@
doc/user/tutorials/building.txt

138
LICENSE
View file

@ -1,117 +1,39 @@
GNU GENERAL PUBLIC LICENSE - the *Lumiera* source code is (C) by the original authors (see `AUTHORS`)
Version 2, June 1991 +
-----------------------------------------------------------------------------
Lumiera is free software -- you may use and redistribute it under the
Terms and conditions of the GNU GENERAL PUBLIC LICENSE (GPL);
either version 2 of the License, or (at your option) any later version.
Copyright (C) 1989, 1991 Free Software Foundation, Inc. For a copy of the GPL Version 2 see the file COPYING
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -----------------------------------------------------------------------------
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. - Website, design documents and accompanying materials are covered by
the same license as the source code, +
in addition they are also dual-licensed under *CC-By-SA 3*
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. - at various places, the implementation draws on solutions
and comments published at http://Stackoverflow.com[Stackoverflow] --
according to the http://stackexchange.com/legal[License Agreement] page,
any ``subscriber content'' on that site is provided under *CC-By-SA 3*..
We attribute significant usages of solutions published this way
in the doxygen comments of the relevant source code entities.
For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. - Parts of the Implementation are heavily inspired by +
*The Loki Library* (C) 2001 by *Andrei Alexandrescu*
+
-----------------------------------------------------------------------------
Loki is governed by a MIT-License. See: http://loki-lib.sourceforge.net
Permission to use, copy, modify, distribute and sell this software for any
purpose is hereby granted without fee, provided that the above copyright
notice appear in all copies and that both that copyright notice and this
permission notice appear in supporting documentation.
The author makes no representations about the suitability of this software
for any purpose. It is provided "as is" without express or implied warranty.
-----------------------------------------------------------------------------
Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.
Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and modification follow.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.
You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.
In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
one line to give the program's name and an idea of what it does. Copyright (C) yyyy name of author
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker.
signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice

107
README Normal file
View file

@ -0,0 +1,107 @@
Lumiera -- the video NLE for Linux
====================================
Version: 0.pre.04~rc.1
:Date: 11/2015
*************************************************************
Lumiera is a non-linear video editing and compositing tool.
The Application will allow to edit footage in the common
multimedia formats (quicktime, ogg, mkv, avi) and audio/video
stream codecs (dv, mpeg1/2/4, h264 ...)
Lumiera features non-destructive editing, compositing tools,
a selection of effects plugins, processing in RGB, YUV and
RGB-float colour models and the ability to mix media with
differing sizes and framerates. Lumiera is especially well
suited for large and elaborate professional editing tasks
with lots of material, several scenes, nested sequences,
colour grading, 3D support, full fledged sound montage
and multiple edit versions prepared in parallel.
NOTE: as of 11/2015, Lumiera is in early development stage;
it is not usable yet. The above describes the Lumiera project
vision, which will need years to implement. This preview Release
installs a current development snapshot in pre-alpha stage.
Visit http://Lumiera.org and join the mailing list
when interested in Lumiera planning and development.
****************************************************************
Lumiera pre-Alpha Versions
--------------------------
**This source tree doesn't yet contain a working video editing application** +
Rather, it contains the framework and technology core
of the envisioned Application ``Lumiera''.
See http://issues.lumiera.org/roadmap[Project roadmap]
As of _11/2015_ (0.pre.03)::
a lot of long standing maintennance work has been done. The Project switched
to C++11 and in the end even to C++14 and Debian/Jessie as reference platform,
followed by clean-up of now obsolete workarounds. On the GUI side, we largely
made the transition to GTK-3, which lead to rework of our timeline widget, not
finished yet. This work also spured an effort the connection and communication
between Proc and the UI, which is expected to be asynchroneous. Due to the
limited developer resources, work on the Engine and Player part is stalled.
As of _10/2013_ (0.pre.02)::
the data models have been elaborated and some significant parts of the session
are finished. Work has continued with time handling, a draft of the output
connection framework, a draft of the player subsystem and interfaces to the
engine and processing network. Unfortunately there was a considerable slowdown
and decrease in team size, yet still the code base is growing towards 90k LOC.
No tangible progress regarding the GUI and the backend.
As of _1/2011_ (0.pre.01)::
the project has created and documented a fairly consistent design,
partially coded up -- starting from the technical foundations and working up.
The code base is approaching 65k LOC. Roughly half of this is test code.
The Application can be installed and started to bring up a GTK GUI framework,
but the GUI is very preliminary and not connected to core functionality.
The video processing pipeline exists only in the blueprints.
As of _2/2008_::
the project has been separated completely from ``Cinelerra'', the parent project.
The Community, which at that time was largely identical to the Cinelerra-CV community,
choose the new project name ``Lumiera'' through a collaborative selection and vote.
The basic project infrastructure is up and running, and work on the new codebase
has started. We can show nothing beyond a test suite for some time to come.
As of _7/2007_::
we started with the backend and render engine draft, some example code
complemented by several unit tests. There is a TiddlyWiki with detailed
design considerations and developer documentation and a UML model
Build Requirements
------------------
For building Lumiera, you'll need:
* C99 / C++14 compiler GCC `>=4.9` or Clang `>=3.5`
* Git Version management system
* http://www.scons.org/[SCons build system]
* http://www.boost.org/[Boost libraries]
* http://gmerlin.sourceforge.net/[GAVL library]
* http://nobug.pipapo.org/[NoBug library]
* http://www.gtkmm.org/en/[GTKmm]
* http://alsa-project.org[ALSA libasound2-dev]
* http://cgit.freedesktop.org/xorg/lib/libXv[libXv]
* https://wiki.gnome.org/LibRsvg[lib rSVG]
* https://git.gnome.org/browse/gdl[lib GDL]
See the online documentation at http://Lumiera.org/download.html
Debian Package
--------------
Hermann Vosseler (aka Ichthyo) maintains a *Debian* packaging of the source tree
- the package definition can be pulled from `git://git.lumiera.org/debian/lumiera/`
- the package can be built by `git-buildpackage`

View file

@ -1,3 +0,0 @@
# lumiera_
NLE Video Editor

78
SConstruct Normal file
View file

@ -0,0 +1,78 @@
# coding: utf-8
##
## SConstruct - SCons based build-system for Lumiera
##
# Copyright (C)
# 2008, Hermann Vosseler <Ichthyostega@web.de>
#
# **Lumiera** is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version. See the file COPYING for further details.
#####################################################################
# NOTE: scons -h for help.
# This script /defines/ the components and how they fit together.
# SCons will derive dependencies and the necessary build steps.
# Read more about the SCons build system at: http://www.scons.org
# NOTE: Lumiera SCons extension modules and plugins
#--------------------------------------------------
import sys
sys.path.append('./admin/scons')
#--------------------------------------------------
import Setup
import Options
import Platform
from Buildhelper import *
from LumieraEnvironment import *
#####################################################################
env = Setup.defineBuildEnvironment() # dirs & compiler flags
env = Platform.configure(env) # library dependencies
### === MAIN BUILD === ##############################################
# call subdir SConscript(s) to define the actual build targets...
SConscript(dirs=['data','src','src/tool','research','tests','doc'], exports='env')
# additional files to be cleaned when cleaning 'build'
env.Clean ('build', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log' ])
env.Clean ('build', [ 'src/pre.gch' ])
### === Alias Targets === ###########################################
# pick up the targets defined by the sub SConscripts
#Import('lumiera plugins tools gui testsuite doxydoc')
Import('lumiera plugins tools gui testsuite')
build = env.Alias('build', lumiera + plugins + tools + gui)
env.Default('build')
# SCons default target
#env.Alias ('all', build + testsuite + doxydoc)
env.Alias ('all', build + testsuite)
#env.Alias ('doc', doxydoc)
env.Alias ('none')
env.Alias('install', gui)
env.Alias('install', '$DESTDIR')
#####################################################################

1
admin/DIR_INFO Normal file
View file

@ -0,0 +1 @@
administrative scripts

View file

@ -0,0 +1,5 @@
This is the Public Key of the Package signing GPG key
used for building of Debian DEB packages on Lumiera.org
Fingerprint: 11FD F5D2 DBD7 BBD7 F4D9 D9C4 2CF2 5392 6238 2557
UID: Ichthyo (DEB-Package) <deb@ichthyostega.de>

145
admin/buildVersion.py Executable file
View file

@ -0,0 +1,145 @@
#!/usr/bin/python3
# coding: utf-8
##
## buildVersion.py - extract and possibly bump current version from Git
##
# Copyright (C)
# 2025, Hermann Vosseler <Ichthyostega@web.de>
#
# **Lumiera** is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version. See the file COPYING for further details.
#####################################################################
'''
Build and possibly bump a current project version spec,
based on the nearest Git tag.
'''
import re
import os
import sys
import datetime
import argparse
import subprocess
#------------CONFIGURATION----------------------------
CMDNAME = os.path.basename(__file__)
TAG_PAT = 'v*.*'
VER_SEP = r'(?:^v?|\.)'
VER_NUM = r'(\w[\w\+]*)'
VER_SUB = r'(?:'+VER_SEP+VER_NUM+')'
VER_SUF = r'(?:~('+VER_NUM+VER_SUB+'?'+'))'
VER_SYNTAX = VER_SUB +VER_SUB+'?' +VER_SUB+'?' +VER_SUF+'?'
GIT = 'git'
#------------CONFIGURATION----------------------------
def parseAndBuild():
''' main: parse cmdline and generate version string '''
parser = argparse.ArgumentParser (prog=CMDNAME, description='%s: %s' % (CMDNAME, __doc__)
,formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument ('--bump','-b'
,nargs='?'
,choices=['maj','min','rev'], const='rev'
,help='bump the version detected from Git (optionally bump a specific component)')
parser.add_argument ('--suffix','-s'
,help='append (or replace) a suffix (by default attached with ~)')
parser.add_argument ('--snapshot'
,action='store_true'
,help='mark as development snapshot by appending ~dev.YYYYMMDDhhmm, using UTC date from HEAD commit')
opts = parser.parse_args()
version = getVersionFromGit()
version = rebuild (version, **vars(opts))
print (version)
def getVersionFromGit():
get_nearest_matching_tag = 'describe --tags --abbrev=0 --match=' + TAG_PAT
return runGit (get_nearest_matching_tag)
def getTimestampFromGit():
get_head_author_date = 'show -s --format=%ai'
timespec = runGit (get_head_author_date)
timespec = datetime.datetime.fromisoformat (timespec)
timespec = timespec.astimezone (datetime.timezone.utc) # note: convert into UTC
return timespec.strftime ('%Y%m%d%H%M')
def rebuild (version, bump=None, suffix=None, snapshot=False):
mat = re.fullmatch (VER_SYNTAX, version)
if not mat:
__FAIL ('invalid version syntax in "'+version+'"')
maj = mat.group(1)
min = mat.group(2)
rev = mat.group(3)
suf = mat.group(4)
suf_idi = mat.group(5) # detail structure not used (as of 2025)
suf_num = mat.group(6)
if bump=='maj':
maj = bumpedNum(maj)
min = None
rev = None
elif bump=='min':
min = bumpedNum(min)
rev = None
elif bump=='rev':
rev = bumpedNum(rev)
if snapshot:
suf = 'dev.'+getTimestampFromGit()
elif suffix:
suf = suffix
version = maj
if min:
version += '.'+min
elif not min and rev:
version += '.0'
if rev:
version += '.'+rev
if suf:
version += '~'+suf
return version
def bumpedNum (verStr):
mat = re.match (r'\d+', str(verStr))
if not mat:
return '1'
numStr = mat.group(0)
num = int(numStr) + 1
return str(num).zfill(len(numStr))
def runGit (argStr):
''' run Git as system command without shell and retrieve the output '''
argList = [GIT] + argStr.split()
try:
proc = subprocess.run (argList, check=True, capture_output=True, encoding='utf-8', env={'LC_ALL':'C'})
return proc.stdout.rstrip() # Note: sanitised env
except:
__FAIL ('invoking git-describe')
def __ERR (*args, **kwargs):
print (*args, file=sys.stderr, **kwargs)
def __FAIL (msg):
__ERR ("FAILURE: "+msg)
exit (-1)
if __name__=='__main__':
parseAndBuild()

View file

@ -0,0 +1,61 @@
#!/bin/sh
#
# build_lumiera-build-dependencies.sh - prepare/build on a pristine Debian/Ubuntu system (Docker)
#
#
#------------------------------------------------------Setup
# The Debian DEB Depot to retrieve the source packages
DEBIAN_REPO="http://lumiera.org/debian/"
SRC_DISTRO="stretch"
REPO_SECTION="experimental"
#
# GPG pubkey to trust for signed packages
TRUSTED_GPG=$(dirname $0)/deb.lumiera.org.PUB.gpg
#
# Directory for building DEB packages
PACK_DIR=./pack
#
#------------------------------------------------------Setup(End)
#
fail() {
echo "\nFAIL: $1\n\n"
exit 1
}
# Sanity-Checks
[ -f $TRUSTED_GPG ] || fail "GPG Key not found: $TRUSTED_GPG"
mkdir -p $PACK_DIR
[ -w $PACK_DIR ] || fail "Unable to build. Can not write to $PACK_DIR"
# prepare the host system with Lumiera package sources
cp $TRUSTED_GPG /etc/apt/trusted.gpg.d/
chmod a+r-x /etc/apt/trusted.gpg.d/$(basename $TRUSTED_GPG)
echo "deb-src $DEBIAN_REPO $SRC_DISTRO $REPO_SECTION" > /etc/apt/sources.list.d/55-lumiera.list
apt update
apt install -y build-essential ca-certificates
apt update
# build some special build dependencies from source
WORKDIR=$(pwd -P)
cd $PACK_DIR
echo "\n\n======= building NoBug =======\n"
apt-get -y build-dep nobug
apt-get source --compile nobug
dpkg -i nobug-dev*deb libnobug*deb || fail "installing NoBug"
echo "\n\n======= building GDLmm =======\n"
apt-get -y build-dep libgdlmm-3-dev
apt-get source --compile libgdlmm-3-dev || fail "installing GDLmm"
dpkg -i libgdlmm-3*deb
# install the build dependencies of Lumiera from DEB
echo "\n\nInstalling Lumiera build dependencies...\n"
apt-get -y build-dep lumiera
# return to the working directory
cd $WORKDIR
echo "Build-Dependencies of Lumiera successfully installed.\n\n"

Binary file not shown.

View file

@ -0,0 +1,44 @@
#!/bin/sh
#
# docker_open-lumiera-buildenv.sh - launch Docker container with interactive build shell
#
#
#------------------------------------------------------Setup
#
# Working directory path on the host
WORKDIR_HOST="/home/$USER/devel/lumi"
#
# bind-mount of the working dir in the container
WORKDIR_GUEST="/lumi"
#
# Docker image-ID to launch
DOCKER_IMAGE="ubuntu:bionic"
#
# Script code to inject into interactive shell
COMMANDS=$(cat) <<RUN_IN_CONTAINER
. /etc/bash.bashrc
. ~/.bashrc
alias la='ls -latr'
$WORKDIR_GUEST/admin/build_lumiera-build-dependencies.sh
RUN_IN_CONTAINER
#
#------------------------------------------------------Setup(End)
#
# Launch...
# (1) launch the docker container
# (2) start a bash there to process a bash commandline
# (3) this commandline in turn launches an interactive bash
# (4) and this interactive bash gets a startup-Shellscript to perform
# (5) and this shellscript is read from an temporary named pipe to another shellscript
# (6) which in turn prints the script code from the setup-variable $COMMANDS
#
# bash magic thanks to Jonathan Potter; see https://serverfault.com/a/586272
#
#
docker run -v $WORKDIR_HOST:$WORKDIR_GUEST -it $DOCKER_IMAGE bash -c "bash --rcfile <(echo \"${COMMANDS}\" )"

3
admin/git_hooks/DIR_INFO Executable file
View file

@ -0,0 +1,3 @@
git hook scripts
taken out of .git/hooks since .git is not under revision control itself
if you want to use these, just symlink them

15
admin/git_hooks/applypatch-msg Executable file
View file

@ -0,0 +1,15 @@
#!/bin/sh
#
# An example hook script to check the commit log message taken by
# applypatch from an e-mail message.
#
# The hook should exit with non-zero status after issuing an
# appropriate message if it wants to stop the commit. The hook is
# allowed to edit the commit message file.
#
# To enable this hook, make this file executable.
. git-sh-setup
test -x "$GIT_DIR/hooks/commit-msg" &&
exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
:

21
admin/git_hooks/commit-msg Executable file
View file

@ -0,0 +1,21 @@
#!/bin/sh
#
# An example hook script to check the commit log message.
# Called by git-commit with one argument, the name of the file
# that has the commit message. The hook should exit with non-zero
# status after issuing an appropriate message if it wants to stop the
# commit. The hook is allowed to edit the commit message file.
#
# To enable this hook, make this file executable.
# Uncomment the below to add a Signed-off-by line to the message.
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
# This example catches duplicate Signed-off-by lines.
test "" = "$(grep '^Signed-off-by: ' "$1" |
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
echo >&2 Duplicate Signed-off-by lines.
exit 1
}

12
admin/git_hooks/post-commit Executable file
View file

@ -0,0 +1,12 @@
#!/bin/sh
#
# An example hook script that is called after a successful
# commit is made.
#
# To enable this hook, make this file executable.
# see wiki/index.html#GitNotes%20GitAliases for information
user_email="$(git config user.email)"
git tag -s -f -m "signature generated by $user_email" "$user_email/$(git-symbolic-ref HEAD | cut -d/ -f 3-)_signature"

16
admin/git_hooks/post-receive Executable file
View file

@ -0,0 +1,16 @@
#!/bin/sh
#
# An example hook script for the post-receive event
#
# This script is run after receive-pack has accepted a pack and the
# repository has been updated. It is passed arguments in through stdin
# in the form
# <oldrev> <newrev> <refname>
# For example:
# aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master
#
# see contrib/hooks/ for an sample, or uncomment the next line (on debian)
#
#. /usr/share/doc/git-core/contrib/hooks/post-receive-email

8
admin/git_hooks/post-update Executable file
View file

@ -0,0 +1,8 @@
#!/bin/sh
#
# An example hook script to prepare a packed repository for use over
# dumb transports.
#
# To enable this hook, make this file executable by "chmod +x post-update".
exec git-update-server-info

14
admin/git_hooks/pre-applypatch Executable file
View file

@ -0,0 +1,14 @@
#!/bin/sh
#
# An example hook script to verify what is about to be committed
# by applypatch from an e-mail message.
#
# The hook should exit with non-zero status after issuing an
# appropriate message if it wants to stop the commit.
#
# To enable this hook, make this file executable.
. git-sh-setup
test -x "$GIT_DIR/hooks/pre-commit" &&
exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}
:

70
admin/git_hooks/pre-commit Executable file
View file

@ -0,0 +1,70 @@
#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by git-commit with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, make this file executable.
# This is slightly modified from Andrew Morton's Perfect Patch.
# Lines you introduce should not have trailing whitespace.
# Also check for an indentation that has SP before a TAB.
if git-rev-parse --verify HEAD 2>/dev/null
then
git-diff-index -p -M --cached HEAD
else
# NEEDSWORK: we should produce a diff with an empty tree here
# if we want to do the same verification for the initial import.
:
fi |
perl -e '
my $found_bad = 0;
my $filename;
my $reported_filename = "";
my $lineno;
sub bad_line {
my ($why, $line) = @_;
if (!$found_bad) {
print STDERR "*\n";
print STDERR "* You have some suspicious patch lines:\n";
print STDERR "*\n";
$found_bad = 1;
}
if ($reported_filename ne $filename) {
print STDERR "* In $filename\n";
$reported_filename = $filename;
}
print STDERR "* $why (line $lineno)\n";
print STDERR "$filename:$lineno:$line\n";
}
while (<>) {
if (m|^diff --git a/(.*) b/\1$|) {
$filename = $1;
next;
}
if (/^@@ -\S+ \+(\d+)/) {
$lineno = $1 - 1;
next;
}
if (/^ /) {
$lineno++;
next;
}
if (s/^\+//) {
$lineno++;
chomp;
if (/\s$/) {
bad_line("trailing whitespace", $_);
}
if (/^\s* /) {
bad_line("indent SP followed by a TAB", $_);
}
if (/^(?:[<>=]){7}/) {
bad_line("unresolved merge conflict", $_);
}
}
}
exit($found_bad);
'

150
admin/git_hooks/pre-rebase Executable file
View file

@ -0,0 +1,150 @@
#!/bin/sh
#
# Copyright (c) 2006 Junio C Hamano
#
publish=next
basebranch="$1"
if test "$#" = 2
then
topic="refs/heads/$2"
else
topic=`git symbolic-ref HEAD`
fi
case "$basebranch,$topic" in
master,refs/heads/??/*)
;;
*)
exit 0 ;# we do not interrupt others.
;;
esac
# Now we are dealing with a topic branch being rebased
# on top of master. Is it OK to rebase it?
# Is topic fully merged to master?
not_in_master=`git-rev-list --pretty=oneline ^master "$topic"`
if test -z "$not_in_master"
then
echo >&2 "$topic is fully merged to master; better remove it."
exit 1 ;# we could allow it, but there is no point.
fi
# Is topic ever merged to next? If so you should not be rebasing it.
only_next_1=`git-rev-list ^master "^$topic" ${publish} | sort`
only_next_2=`git-rev-list ^master ${publish} | sort`
if test "$only_next_1" = "$only_next_2"
then
not_in_topic=`git-rev-list "^$topic" master`
if test -z "$not_in_topic"
then
echo >&2 "$topic is already up-to-date with master"
exit 1 ;# we could allow it, but there is no point.
else
exit 0
fi
else
not_in_next=`git-rev-list --pretty=oneline ^${publish} "$topic"`
perl -e '
my $topic = $ARGV[0];
my $msg = "* $topic has commits already merged to public branch:\n";
my (%not_in_next) = map {
/^([0-9a-f]+) /;
($1 => 1);
} split(/\n/, $ARGV[1]);
for my $elem (map {
/^([0-9a-f]+) (.*)$/;
[$1 => $2];
} split(/\n/, $ARGV[2])) {
if (!exists $not_in_next{$elem->[0]}) {
if ($msg) {
print STDERR $msg;
undef $msg;
}
print STDERR " $elem->[1]\n";
}
}
' "$topic" "$not_in_next" "$not_in_master"
exit 1
fi
exit 0
################################################################
This sample hook safeguards topic branches that have been
published from being rewound.
The workflow assumed here is:
* Once a topic branch forks from "master", "master" is never
merged into it again (either directly or indirectly).
* Once a topic branch is fully cooked and merged into "master",
it is deleted. If you need to build on top of it to correct
earlier mistakes, a new topic branch is created by forking at
the tip of the "master". This is not strictly necessary, but
it makes it easier to keep your history simple.
* Whenever you need to test or publish your changes to topic
branches, merge them into "next" branch.
The script, being an example, hardcodes the publish branch name
to be "next", but it is trivial to make it configurable via
$GIT_DIR/config mechanism.
With this workflow, you would want to know:
(1) ... if a topic branch has ever been merged to "next". Young
topic branches can have stupid mistakes you would rather
clean up before publishing, and things that have not been
merged into other branches can be easily rebased without
affecting other people. But once it is published, you would
not want to rewind it.
(2) ... if a topic branch has been fully merged to "master".
Then you can delete it. More importantly, you should not
build on top of it -- other people may already want to
change things related to the topic as patches against your
"master", so if you need further changes, it is better to
fork the topic (perhaps with the same name) afresh from the
tip of "master".
Let's look at this example:
o---o---o---o---o---o---o---o---o---o "next"
/ / / /
/ a---a---b A / /
/ / / /
/ / c---c---c---c B /
/ / / \ /
/ / / b---b C \ /
/ / / / \ /
---o---o---o---o---o---o---o---o---o---o---o "master"
A, B and C are topic branches.
* A has one fix since it was merged up to "next".
* B has finished. It has been fully merged up to "master" and "next",
and is ready to be deleted.
* C has not merged to "next" at all.
We would want to allow C to be rebased, refuse A, and encourage
B to be deleted.
To compute (1):
git-rev-list ^master ^topic next
git-rev-list ^master next
if these match, topic has not merged in next at all.
To compute (2):
git-rev-list master..topic
if this is empty, it is fully merged to "master".

78
admin/git_hooks/update Executable file
View file

@ -0,0 +1,78 @@
#!/bin/sh
#
# An example hook script to blocks unannotated tags from entering.
# Called by git-receive-pack with arguments: refname sha1-old sha1-new
#
# To enable this hook, make this file executable by "chmod +x update".
#
# Config
# ------
# hooks.allowunannotated
# This boolean sets whether unannotated tags will be allowed into the
# repository. By default they won't be.
#
# --- Command line
refname="$1"
oldrev="$2"
newrev="$3"
# --- Safety check
if [ -z "$GIT_DIR" ]; then
echo "Don't run this script from the command line." >&2
echo " (if you want, you could supply GIT_DIR then run" >&2
echo " $0 <ref> <oldrev> <newrev>)" >&2
exit 1
fi
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
exit 1
fi
# --- Config
allowunannotated=$(git-repo-config --bool hooks.allowunannotated)
# check for no description
projectdesc=$(sed -e '1p' "$GIT_DIR/description")
if [ -z "$projectdesc" -o "$projectdesc" = "Unnamed repository; edit this file to name it for gitweb" ]; then
echo "*** Project description file hasn't been set" >&2
exit 1
fi
# --- Check types
# if $newrev is 0000...0000, it's a commit to delete a branch
if [ -z "${newrev##0*}" ]; then
newrev_type=commit
else
newrev_type=$(git-cat-file -t $newrev)
fi
case "$refname","$newrev_type" in
refs/tags/*,commit)
# un-annotated tag
short_refname=${refname##refs/tags/}
if [ "$allowunannotated" != "true" ]; then
echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
exit 1
fi
;;
refs/tags/*,tag)
# annotated tag
;;
refs/heads/*,commit)
# branch
;;
refs/remotes/*,commit)
# tracking branch
;;
*)
# Anything else (is there anything else?)
echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
exit 1
;;
esac
# --- Finished
exit 0

5
admin/gnu-indent.sh Normal file
View file

@ -0,0 +1,5 @@
#!/bin/sh
#
# gnu-indent -- call the "indent" tool with parameters suitable for GNU coding style
#
indent -nbad -bap -nbc -bbo -bl -bli2 -bls -ncdb -nce -cp1 -cs -di2 -ndj -nfc1 -nfca -hnl -i2 -ip5 -lp -pcs -psl -nsc -nsob $@

493
admin/rfc.sh Executable file
View file

@ -0,0 +1,493 @@
#!/bin/bash
shopt -s extglob
#
# RFC's are created from ./doc/devel/template/new_rfc.sh and stored in
# ./doc/devel/rfc/ . There are directories for the various states
# ./doc/devel/rfc_final, ./doc/devel/rfc_pending, ./doc/devel/rfc_parked,
# ./doc/devel/rfc_dropped . Which contain symlinks back to ../rfc/
#
function usage()
{
grep -v '^// ' <<"EOF" | less -F
Lumiera RFC maintenance script
==============================
// Note: the source of this documentation is maintained
// directly admin/rfc.sh in its usage() function
// edit it only there and then regenerate
// doc/devel/technical/infra/ with:
// ./admin/rfc.sh help >doc/technical/infra/rfcsh.txt
Usage
-----
./admin/rfc.sh <command> [options]
Commands (with <mandatory> and [optional] parameters)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
find <rfcs> [regex]:: List all matching RFC's (matching `regex`)
show <rfcs> [regex]:: Read RFC's (matching `regex`)
create <title>:: Create a new RFC
edit <rfc> [chapter]:: Edit RFC at chapter
asciidoc <rfc>:: pass the rfc.txt to `asciidoc` command
comment <rfc>:: Add a new comment to a RFC
draft <rfc>:: Change RFC to Draft state
final <rfc>:: Change RFC to Final state
park <rfc>:: Change RFC to Parked state
drop <rfc>:: Change RFC to Dropped state
supersede <rfc> <new>:: Supersede RFC with a new RFC
discard <rfc>:: Delete an RFC
help:: Show this help
process:: Do automatic maintenance work
wrap <rfcs>:: canonical reformatting
Option types
~~~~~~~~~~~~
title:: Quoted string used as RFC title
rfc:: Name of the RFC, smart matched, unique
rfcs:: Name of the RFC, smart matched, multiple
regex:: Regex matched against the content of a RFC
chapter:: Heading of a section
Smart matching
--------------
RFC names don't need to be given exactly, they use a globbing pattern.
This is:
* case insensitive
* whitespaces are ignored
* `*` stands for any number of parameters
* `?` is any single character
* when starting with `/` they are matched against the begin of the name
* some regex operators work too
`find` and `show` can operate on many matches so the given rfc name doesn't
need to be unique. The other commands will complain when the RFC name given
doesn't resolve to one unique RFC.
When `less` presents multiple files one can go forth and back with the `:n`
and `:p` commands.
The tile for `create` should be a normal document title. Possibly quoted
since it may contain spaces and not too long. The filename is this title
in CamelCase with all spaces and special characters removed.
Chapter machching single lines containing this word, special asciidoc
comments in the form `//word:.*` and asciidoc block attributes `[word.*]`
on a single line. When a chapter pattern is not unique, the last one is
picked.
rfc.sh executes git add/rm/mv commands, but never commits. One should do a
commit as soon he finished editing.
EOF
}
function camel_case()
{
sed -e 's/[^[:alnum:]]/ /g;s/ \+\(.\)/\U\1/g' <<<" $1"
}
function untabify()
{
local in="$1"
local tmp
local out
while [[ "$in" ]]; do
tmp="${in%%$'\t'*}"
in="${in:${#tmp}+1}"
out="$out$tmp "
out="${out:0:${#out}/8*8}"
done
out="${out%%*( )}"
echo "$out"
}
function word_wrap()
{
local linelength="${1:-80}"
local indent=""
local text
local tab=$'\t'
local rest
local oldindent
local coderx='//|/\*|#'
local meld=yes
while IFS='' read -r line; do
line="$(untabify "$line")"
# remove DOS linebreaks
line="${line//$'\r'/}"
text="${line##*([![:alnum:]])}"
oldindent="$indent"
indent="${line:0:${#line}-${#text}}"
if [[ "$text" ]]; then
# avoid melding text after // /* and # comments
if [[ "$indent" =~ $coderx ]]; then
meld=no
fi
if [[ $meld = yes && ! "${indent// /}" && ${#oldindent} -eq ${#indent} ]]; then
line="${rest:+$rest }$text"
else
if [[ "$rest" ]]; then
echo "$rest"
fi
fi
indent="${indent//?/ }"
while [[ "${#line}" -ge "${linelength}" ]]; do
local wrapped
local tmpline="${line:0:$linelength}"
wrapped="${tmpline% *}"
if [[ "${#wrapped}" -gt "${#indent}" ]]; then
line="${indent}${line:${#wrapped}+1}"
else
wrapped="$line"
line=''
fi
echo "$wrapped"
done
rest="${line}"
else
meld=yes
if [[ "$rest" ]]; then
echo "$rest"
rest=""
fi
echo "$line"
fi
done
if [[ "$rest" ]]; then
echo "$rest"
fi
}
function smart_wrap()
{
# calling on a file
word_wrap $2 <"$1" >"$1.$$.tmp"
if ! cmp "$1" "$1.$$.tmp" &>/dev/null ; then
cat "$1.$$.tmp" >"$1"
git add "$1"
fi
rm "$1.$$.tmp"
}
function find_rfc()
{
# find rfc by shortname
local file
local match="$1"
match="${match// /}"
match="${match//./\.}"
match="${match//\?/.}"
match="${match//\*/.*}"
local globstate=$(shopt -p nocasematch)
shopt -s nocasematch
for file in $(find ./doc/devel/rfc/ -name '*.txt');
do
local name="/${file##*/}"
if [[ "$name" =~ $match ]]; then
echo "$file"
fi
done
$globstate
}
function find_chapter()
{
# find chapter
local file="$1"
local chapter="$2"
local found=$(grep -n -i "^\($chapter\|//$chapter:.*\|\[$chapter.*\]\)\$" "$file" | tail -1)
if [[ "$found" ]]; then
echo "${found%%:*}"
fi
}
function process_file()
{
local file="$1"
local path="${1%/*}"
local basename="${1##*/}"
local linkdest="$path"
local state=$(grep '^\*State\* *' "$file")
case "$state" in
*Final*)
linkdest="./doc/devel/rfc_final"
;;
*Idea*|*Draft*)
linkdest="./doc/devel/rfc_pending"
;;
*Parked*)
linkdest="./doc/devel/rfc_parked"
;;
*Dropped*)
linkdest="./doc/devel/rfc_dropped"
;;
*)
echo "Unknown State: '$state'" >&2
exit 1
esac
local oldpath
for oldpath in ./doc/devel/rfc_*/$basename; do :; done
if [[ -h "$oldpath" ]]; then
if [[ "$oldpath" != "$linkdest/$basename" ]]; then
git mv "$oldpath" "$linkdest/$basename"
fi
elif [[ ! -s "$linkdest/$basename" ]]; then
ln -s "../rfc/$basename" "$linkdest/"
git add "$linkdest/$basename"
fi
}
function edit()
{
# filename lineoffset chapter
EDITOR="${EDITOR:-$(git config --get core.editor)}"
EDITOR="${EDITOR:-$VISUAL}"
if [ -z "$EDITOR" ]; then
echo -e "\nFATAL\n\$EDITOR undefined\n\n"
exit -1
fi
local file="$1"
local line=0
if [[ "$3" ]]; then
line=$(find_chapter "$file" "$3")
fi
$EDITOR +$(($line+${2:-1})) $file
}
function unique_name()
{
local files=($(find_rfc "$1"))
if [[ ${#files[*]} -gt 1 ]]; then
echo "multiple matches:" >&2
(
IFS=$'\n'
echo "${files[*]}" >&2
)
elif [[ ${#files[*]} -eq 0 ]]; then
echo "no matches" >&2
else
echo ${files[0]}
fi
}
function add_comment()
{
local name="$1"
local nl=$'\n'
local comment="//edit comment$nl$nl$(git config --get user.name):: '$(date +%c)' ~<$(git config --get user.email)>~$nl"
ed "$name" 2>/dev/null <<EOF
/endof_comments:/-1i
$comment
.
wq
EOF
edit "$name" -4 "endof_comments"
}
function edit_state()
{
local name="$1"
local state="$2"
local comment="$3"
ed "$name" 2>/dev/null <<EOF
/^\*State\*/s/\(\*State\* *_\).*_/\1${state}_/
wq
EOF
if [[ "$comment" ]]; then
ed "$name" 2>/dev/null <<EOF
/endof_comments:/-1i
$comment
.
wq
EOF
fi
}
function change_state()
{
#rfcname state
local name="$1"
local state="$2"
local nl=$'\n'
local comment=".State -> $state$nl//add reason$nl$nl$(git config --get user.name):: '$(date +%c)' ~<$(git config --get user.email)>~$nl"
edit_state "$name" "$state" "$comment"
edit "$name" -4 "endof_comments"
process_file "$name"
}
command="$1"
shift
case "$command" in
process)
# for all rfc's
for file in $(find ./doc/devel/rfc -name '*.txt');
do
echo "process $file"
process_file "$file"
done
:
;;
search)
grep -r -C3 -n "$1" ./doc/devel/rfc | less -F
;;
find|list|ls)
if [[ "$2" ]]; then
find_rfc "$1" | xargs grep -i -C3 -n "$2"
else
find_rfc "$1"
fi
;;
show|less|more)
if [[ "$2" ]]; then
less $(find_rfc "$1" | xargs grep -i -l "$2")
else
less $(find_rfc "$1")
fi
;;
create)
TITLE="$@"
name=$(camel_case "$TITLE")
if [[ -f "./doc/devel/rfc/${name}.txt" ]]; then
echo "$name.txt exists already"
else
source ./doc/devel/template/new_rfc.sh >"./doc/devel/rfc/${name}.txt"
edit "./doc/devel/rfc/${name}.txt" 2 abstract
git add "./doc/devel/rfc/${name}.txt"
process_file "./doc/devel/rfc/${name}.txt"
fi
;;
edit)
name=$(unique_name "$1")
if [[ "$name" ]]; then
edit "${name}" 2 "$2"
process_file "$name"
fi
;;
asciidoc)
name=$(unique_name "$1")
if [[ "$name" ]]; then
asciidoc "${name}"
fi
;;
draft)
name=$(unique_name "$1")
if [[ "$name" ]]; then
change_state "$name" Draft
fi
;;
park)
name=$(unique_name "$1")
if [[ "$name" ]]; then
change_state "$name" Parked
fi
;;
final)
name=$(unique_name "$1")
if [[ "$name" ]]; then
change_state "$name" Final
fi
;;
supersede)
name=$(unique_name "$1")
newname=$(unique_name "$2")
newname="${newname##*/}"
newname="${newname%.txt}"
if [[ "$name" && "$newname" ]]; then
change_state "$name" "Superseded by $newname"
fi
;;
drop)
name=$(unique_name "$1")
if [[ "$name" ]]; then
change_state "$name" Dropped
fi
;;
comment)
name=$(unique_name "$1")
if [[ "$name" ]]; then
add_comment "${name}"
process_file "$name"
fi
;;
discard)
name=$(unique_name "$1")
if [[ "$name" ]]; then
for link in ./doc/devel/rfc_*/${name##*/}; do :; done
if [[ -h "$link" ]]; then
git rm -f "${link}" || rm "${link}"
fi
git rm -f "${name}" || rm "${name}"
fi
;;
wrap)
find_rfc "$1" | while read file; do
smart_wrap "$file" 80
process_file "$file"
done
;;
smart_wrap)
# multipurpose smart wrap
smart_wrap "$1" ${2:-80}
;;
help|*)
usage
;;
esac

View file

@ -0,0 +1,8 @@
#/bin/sh
echo "syncing tiddlywikis"
rsync -rLz --partial --del --exclude backups wiki/ lumiera.org:/var/www/wiki
echo "syncing doxygen documentation"
rsync -rz --partial --del doc/devel/html/ lumiera.org:/var/www/doxy

View file

@ -0,0 +1,407 @@
# coding: utf-8
##
## BuilderDoxygen.py - SCons builder for generating Doxygen documentation
##
#
# Astxx, the Asterisk C++ API and Utility Library.
# Copyright (C)
# 2005, 2006, Matthew A. Nicholson
# 2006, Tim Blechmann
# 2007, Christoph Boehme
# 2012, Dirk Baechle
# 2013, Russel Winder
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License version 2.1 as published by the Free Software Foundation.
#####################################################################
# history: 8/2008 adapted for Lumiera build system
# added patch for Doxyfile in subdirectory
# see http://www.scons.org/wiki/DoxygenBuilder
# 4/2025 Upgrade to latest upstream version for Python-3
import os
import os.path
import glob
from fnmatch import fnmatch
from functools import reduce
# Currently supported output formats and their default
# values and output locations.
# From left to right:
# 1. default setting YES|NO
# 2. default output folder for this format
# 3. name of the (main) output file
# 4. default extension "
# 5. field for overriding the output file extension
output_formats = {
"HTML": ("YES", "html", "index", ".html", "HTML_FILE_EXTENSION"),
"LATEX": ("YES", "latex", "refman", ".tex", ""),
"RTF": ("NO", "rtf", "refman", ".rtf", ""),
"MAN": ("NO", "man", "", ".3", "MAN_EXTENSION"),
"XML": ("NO", "xml", "index", ".xml", ""),
}
def DoxyfileParse(file_contents, conf_dir, data=None):
"""
Parse a Doxygen source file and return a dictionary of all the values.
Values will be strings and lists of strings.
"""
if data is None:
data = {}
import shlex
lex = shlex.shlex(instream=file_contents, posix=True)
lex.wordchars += "*+./-:@"
lex.whitespace = lex.whitespace.replace("\n", "")
lex.escape = ""
lineno = lex.lineno
token = lex.get_token()
key = None
last_token = ""
key_token = True # The first token should be a key.
next_key = False
new_data = True
def append_data(data, key, new_data, token):
if new_data or len(data[key]) == 0:
data[key].append(token)
else:
data[key][-1] += token
while token:
if token in ["\n"]:
if last_token not in ["\\"]:
key_token = True
elif token in ["\\"]:
pass
elif key_token:
key = token
key_token = False
else:
if token == "+=":
if key not in data:
data[key] = []
elif token == "=":
if key == "TAGFILES" and key in data:
append_data(data, key, False, "=")
new_data = False
elif key == "@INCLUDE" and key in data:
# don't reset the @INCLUDE list when we see a new @INCLUDE line.
pass
else:
data[key] = []
elif key == "@INCLUDE":
# special case for @INCLUDE key: read the referenced
# file as a doxyfile too.
nextfile = token
if not os.path.isabs(nextfile):
nextfile = os.path.join(conf_dir, nextfile)
if nextfile in data[key]:
raise Exception("recursive @INCLUDE in Doxygen config: " + nextfile)
data[key].append(nextfile)
with open(nextfile, "r") as fh:
DoxyfileParse(fh.read(), conf_dir, data)
else:
append_data(data, key, new_data, token)
new_data = True
last_token = token
token = lex.get_token()
if last_token == "\\" and token != "\n":
new_data = False
append_data(data, key, new_data, "\\")
# compress lists of len 1 into single strings
for (k, v) in list(data.items()):
if len(v) == 0:
data.pop(k)
# items in the following list will be kept as lists and not converted to strings
if k in ["INPUT", "FILE_PATTERNS", "EXCLUDE_PATTERNS", "TAGFILES", "@INCLUDE"]:
continue
if len(v) == 1:
data[k] = v[0]
return data
def DoxySourceFiles(node, env):
"""
Scan the given node's contents (a Doxygen file) and add
any files used to generate docs to the list of source files.
"""
default_file_patterns = [
"*.c",
"*.cc",
"*.cxx",
"*.cpp",
"*.c++",
"*.java",
"*.ii",
"*.ixx",
"*.ipp",
"*.i++",
"*.inl",
"*.h",
"*.hh ",
"*.hxx",
"*.hpp",
"*.h++",
"*.idl",
"*.odl",
"*.cs",
"*.php",
"*.php3",
"*.inc",
"*.m",
"*.mm",
"*.py",
]
default_exclude_patterns = [
"*~",
]
sources = []
# We're running in the top-level directory, but the doxygen
# configuration file is in the same directory as node; this means
# that relative pathnames in node must be adjusted before they can
# go onto the sources list
conf_dir = os.path.dirname(str(node))
data = DoxyfileParse(node.get_text_contents(), conf_dir)
if data.get("RECURSIVE", "NO") == "YES":
recursive = True
else:
recursive = False
file_patterns = data.get("FILE_PATTERNS", default_file_patterns)
exclude_patterns = data.get("EXCLUDE_PATTERNS", default_exclude_patterns)
input = data.get("INPUT")
if input:
for node in data.get("INPUT", []):
if not os.path.isabs(node):
node = os.path.join(conf_dir, node)
if os.path.isfile(node):
sources.append(node)
elif os.path.isdir(node):
if recursive:
for root, dirs, files in os.walk(node):
for f in files:
filename = os.path.join(root, f)
pattern_check = reduce(
lambda x, y: x or bool(fnmatch(filename, y)),
file_patterns,
False,
)
exclude_check = reduce(
lambda x, y: x and fnmatch(filename, y),
exclude_patterns,
True,
)
if pattern_check and not exclude_check:
sources.append(filename)
else:
for pattern in file_patterns:
sources.extend(glob.glob("/".join([node, pattern])))
else:
# No INPUT specified, so apply plain patterns only
if recursive:
for root, dirs, files in os.walk("."):
for f in files:
filename = os.path.join(root, f)
pattern_check = reduce(
lambda x, y: x or bool(fnmatch(filename, y)),
file_patterns,
False,
)
exclude_check = reduce(
lambda x, y: x and fnmatch(filename, y), exclude_patterns, True
)
if pattern_check and not exclude_check:
sources.append(filename)
else:
for pattern in file_patterns:
sources.extend(glob.glob(pattern))
# Add @INCLUDEd files to the list of source files:
for node in data.get("@INCLUDE", []):
sources.append(node)
# Add tagfiles to the list of source files:
for node in data.get("TAGFILES", []):
file = node.split("=")[0]
if not os.path.isabs(file):
file = os.path.join(conf_dir, file)
sources.append(file)
# Add additional files to the list of source files:
def append_additional_source(option, formats):
for f in formats:
if data.get("GENERATE_" + f, output_formats[f][0]) == "YES":
file = data.get(option, "")
if file != "":
if not os.path.isabs(file):
file = os.path.join(conf_dir, file)
if os.path.isfile(file):
sources.append(file)
break
append_additional_source("HTML_STYLESHEET", ["HTML"])
append_additional_source("HTML_HEADER", ["HTML"])
append_additional_source("HTML_FOOTER", ["HTML"])
return sources
def DoxySourceScan(node, env, path):
"""
Doxygen Doxyfile source scanner. This should scan the Doxygen file and add
any files used to generate docs to the list of source files.
"""
filepaths = DoxySourceFiles(node, env)
sources = [env.File(path) for path in filepaths]
return sources
def DoxySourceScanCheck(node, env):
"""Check if we should scan this file"""
return os.path.isfile(node.path)
def DoxyEmitter(target, source, env):
"""Doxygen Doxyfile emitter"""
doxy_fpath = str(source[0])
conf_dir = os.path.dirname(doxy_fpath)
data = DoxyfileParse(source[0].get_text_contents(), conf_dir)
targets = []
out_dir = data.get("OUTPUT_DIRECTORY", ".")
if not os.path.isabs(out_dir):
out_dir = os.path.join(conf_dir, out_dir)
# add our output locations
for (k, v) in list(output_formats.items()):
if data.get("GENERATE_" + k, v[0]) == "YES":
# Initialize output file extension for MAN pages
if k == "MAN":
# Is the given extension valid?
manext = v[3]
if v[4] and v[4] in data:
manext = data.get(v[4])
# Try to strip off dots
manext = manext.replace(".", "")
# Can we convert it to an int?
try:
e = int(manext)
except:
# No, so set back to default
manext = "3"
od = env.Dir(
os.path.join(out_dir, data.get(k + "_OUTPUT", v[1]), "man" + manext)
)
else:
od = env.Dir(os.path.join(out_dir, data.get(k + "_OUTPUT", v[1])))
# don't clobber target folders
env.Precious(od)
# set up cleaning stuff
env.Clean(od, od)
# Add target files
if k != "MAN":
# Is an extension override var given?
if v[4] and v[4] in data:
fname = v[2] + data.get(v[4])
else:
fname = v[2] + v[3]
of = env.File(
os.path.join(out_dir, data.get(k + "_OUTPUT", v[1]), fname)
)
targets.append(of)
# don't clean single files, we remove the complete output folders (see above)
env.NoClean(of)
else:
# Special case: MAN pages
# We have to add a target file docs/man/man3/foo.h.3
# for each input file foo.h, so we scan the config file
# a second time... :(
filepaths = DoxySourceFiles(source[0], env)
for f in filepaths:
if os.path.isfile(f) and f != doxy_fpath:
of = env.File(
os.path.join(
out_dir,
data.get(k + "_OUTPUT", v[1]),
"man" + manext,
f + "." + manext,
)
)
targets.append(of)
# don't clean single files, we remove the complete output folders (see above)
env.NoClean(of)
# add the tag file if neccessary:
tagfile = data.get("GENERATE_TAGFILE", "")
if tagfile != "":
if not os.path.isabs(tagfile):
tagfile = os.path.join(conf_dir, tagfile)
targets.append(env.File(tagfile))
return (targets, source)
def generate(env):
"""
Add builders and construction variables for the
Doxygen tool. This is currently for Doxygen 1.4.6.
"""
doxyfile_scanner = env.Scanner(
DoxySourceScan,
"DoxySourceScan",
scan_check=DoxySourceScanCheck,
)
import SCons.Builder
doxyfile_builder = SCons.Builder.Builder(
action = "cd ${SOURCE.dir} && (${DOXYGEN} ${SOURCE.file} 2>&1 |tee ,doxylog)",
emitter = DoxyEmitter,
target_factory = env.fs.Entry,
single_source = True,
source_scanner = doxyfile_scanner,
)
env.Append(
BUILDERS={
"Doxygen": doxyfile_builder,
}
)
env.AppendUnique(
DOXYGEN="doxygen",
)
def exists(env):
"""
Make sure doxygen exists.
"""
return env.Detect("doxygen")

109
admin/scons/BuilderGCH.py Normal file
View file

@ -0,0 +1,109 @@
# coding: utf-8
##
## BuilderGCH.py - SCons builder for gcc's precompiled headers
##
# Copyright (C) scons.org/wiki/GchBuilder
# 2006, Tim Blechmann
# 2008, Hermann Vosseler <Ichthyostega@web.de>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#####################################################################
# history: 8/2008 adapted for Lumiera build system
# changed to accept a list of precompiled header defs
# TODO: WIP-remove these comments when port to Python 3.x is DONE
# types.py does not contain ListType in Python 3.x
# # Why do we require ListType?
# To do something like
# if type(item) is ListType:
# ....
# But types.py does not have ListType anymore
# if isinstance(item, list):
#from types import ListType
import SCons.Action
import SCons.Builder
import SCons.Scanner.C
import SCons.Util
import SCons.Script
SCons.Script.EnsureSConsVersion(0,96,92)
GchAction = SCons.Action.Action('$GCHCOM', '$GCHCOMSTR')
GchShAction = SCons.Action.Action('$GCHSHCOM', '$GCHSHCOMSTR')
def gen_suffix(env, sources):
return sources[0].get_suffix() + env['GCHSUFFIX']
GchShBuilder = SCons.Builder.Builder(action = GchShAction,
source_scanner = SCons.Scanner.C.CScanner(),
suffix = gen_suffix)
GchBuilder = SCons.Builder.Builder(action = GchAction,
source_scanner = SCons.Scanner.C.CScanner(),
suffix = gen_suffix)
def setup_dependency(target,source,env, key):
scanner = SCons.Scanner.C.CScanner()
path = scanner.path(env)
deps = scanner(source[0], env, path)
if key in env and env[key]:
for header in env[key]:
header_path = header.path.strip('.gch')
if header_path in [x.path for x in deps]:
print("Precompiled header(%s) %s \t <--- %s" % (key,header_path,source[0]))
env.Depends(target, header)
def static_pch_emitter(target,source,env):
SCons.Defaults.StaticObjectEmitter( target, source, env )
setup_dependency(target,source,env, key='GCH')
return (target, source)
def shared_pch_emitter(target,source,env):
SCons.Defaults.SharedObjectEmitter( target, source, env )
setup_dependency(target,source,env, key='GCH-sh')
return (target, source)
def generate(env):
""" Add builders and construction variables for the Gch builder.
"""
env.Append(BUILDERS = {
'gch': env.Builder(
action = GchAction,
target_factory = env.fs.File,
),
'gchsh': env.Builder(
action = GchShAction,
target_factory = env.fs.File,
),
})
try:
bld = env['BUILDERS']['GCH']
bldsh = env['BUILDERS']['GCH-sh']
except KeyError:
bld = GchBuilder
bldsh = GchShBuilder
env['BUILDERS']['PrecompiledHeader'] = bld
env['BUILDERS']['PrecompiledHeaderShared'] = bldsh
env['GCHCOM'] = '$CXX -o $TARGET -x c++-header -c $CXXFLAGS $_CCCOMCOM $SOURCE'
env['GCHSHCOM'] = '$CXX -o $TARGET -x c++-header -c $SHCXXFLAGS $_CCCOMCOM $SOURCE'
env['GCHSUFFIX'] = '.gch'
for suffix in SCons.Util.Split('.c .C .cc .cxx .cpp .c++'):
env['BUILDERS']['StaticObject'].add_emitter( suffix, static_pch_emitter )
env['BUILDERS']['SharedObject'].add_emitter( suffix, shared_pch_emitter )
def exists(env):
return env.Detect('g++')

227
admin/scons/Buildhelper.py Normal file
View file

@ -0,0 +1,227 @@
# coding: utf-8
##
## Buildhelper.py - helpers, custom builders, for SConstruct
##
# Copyright (C)
# 2008, Hermann Vosseler <Ichthyostega@web.de>
#
# **Lumiera** is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version. See the file COPYING for further details.
#####################################################################
import os
import sys
import glob
import fnmatch
from SCons import Util
#
# Common Helper Functions
#
def isCleanupOperation(env):
return env.GetOption('clean')
def isHelpRequest():
""" this is a hack: SCons does all configure tests even if only
the help message is requested. SCons doesn't export the
help option for retrieval by env.GetOption(),
so we scan the commandline directly.
"""
return '-h' in sys.argv or '--help' in sys.argv
def srcSubtree(tree, **args):
""" convenience wrapper: scan the given subtree, which is relative
to the current SConscript, and find all source files.
"""
return list(scanSubtree(tree, **args))
SRCPATTERNS = ['*.c','*.cpp','*.cc']
def scanSubtree(roots, patterns=SRCPATTERNS):
""" first expand (possible) wildcards and filter out non-dirs.
Then scan the given subtree for source filenames
(python generator function)
"""
for root in globRootdirs(roots):
for (d,_,files) in os.walk(root):
d = stripPrefix(d, './')
for p in patterns:
for f in fnmatch.filter(files, p):
yield os.path.join(d,f)
def globRootdirs(roots):
""" helper: expand shell wildcards and filter the resulting list,
so that it only contains existing directories
"""
isDirectory = lambda f: os.path.isdir(f) and os.path.exists(f)
roots = glob.glob(roots)
return (d for d in roots if isDirectory(d) )
def findSrcTrees(location, patterns=SRCPATTERNS):
""" find possible source tree roots, starting with the given location.
When delving down from the initial location(s), a source tree is defined
as a directory containing source files and possibly further sub directories.
After having initially expanded the given location with #globRootdirs, each
directory is examined depth first, until encountering a directory containing
source files, which then yields a result. Especially, this can be used to traverse
an organisational directory structure and find out all possible source trees
to be built into packages, plugins, individual tool executables etc.
@return: the relative path names of all source root dirs found (generator function).
"""
for directory in globRootdirs(location):
if isSrcDir (directory,patterns):
yield directory
else:
for result in findSrcTrees (str(directory)+'/*'):
yield result
def isSrcDir(path, patterns=SRCPATTERNS):
""" helper: investigate the given (relative) path
@param patterns: list of wildcards to define what counts as "source file"
@return: True if it's a directory containing any source file
"""
if not os.path.isdir(path):
return False
else:
for p in patterns:
if glob.glob(path+'/'+p):
return True
def filterNodes(nlist, removeName=None):
""" filter out scons build nodes using the given criteria.
removeName: if set, remove all nodes with this srcname
"""
if removeName:
predicate = lambda n : not fnmatch.fnmatch(os.path.basename(str(n[0])), removeName)
else:
predicate = lambda n : True
return list(filter(predicate, nlist))
def getDirname (d, basePrefix=None):
""" extract directory name without leading path,
or without the explicitly given basePrefix
"""
d = os.path.realpath(d)
if not os.path.isdir(d):
d,_ = os.path.split(d)
if basePrefix:
basePrefix = os.path.realpath(basePrefix)
name = stripPrefix(str(d), basePrefix)
else:
_, name = os.path.split(d)
return name
def stripPrefix(path, prefix):
if path.startswith(prefix):
path = path[len(prefix):]
return path
def createPlugins(env, directory, **kw):
""" investigate the given source directory to identify all contained source trees.
@return: a list of build nodes defining a plugin for each of these source trees.
"""
return [env.LumieraPlugin( getDirname(tree)
, srcSubtree(tree)
, **kw
)
for tree in findSrcTrees(directory)
]
def checkCommandOption(env, optID, val=None, cmdName=None):
""" evaluate and verify an option, which may point at a command.
besides specifying a path, the option may read True, yes or 1,
denoting that the system default for this command should be used.
@return: True, if the key has been expanded and validated,
False, if this failed and the key was removed
"""
if not val:
if not env.get(optID): return False
else:
val = env.get(optID)
if val=='True' or val=='true' or val=='yes' or val=='1' or val == 1 :
if not cmdName:
print("WARNING: no default for %s, please specify a full path." % optID)
del env[optID]
return False
else:
val = env.WhereIs(cmdName)
if not val:
print("WARNING: %s not found, please specify a full path" % cmdName)
del env[optID]
return False
if not os.path.isfile(val):
val = env.WhereIs(val)
if val and os.path.isfile(val):
env[optID] = val
return True
else:
del env[optID]
return False
class Record(dict):
""" a set of properties with record style access.
Record is a dictionary, but the elements can be accessed
conveniently as if they where object fields
"""
def __init__(self, defaults=None, **props):
if defaults:
defaults.update(props)
props = defaults
dict.__init__(self,props)
def __getattr__(self,key):
if key=='__get__' or key=='__set__':
raise AttributeError
return self.setdefault(key)
def __setattr__(self,key,val):
self[key] = val
def extract_localPathDefs (localDefs):
""" extracts the directory configuration values.
For sake of simplicity, paths and directories are defined
immediately as global variables in the SConstruct. This helper
extracts from the given dict the variables matching some magical
pattern and returns them wrapped into a Record for convenient access
"""
def relevantPathDefs (mapping):
for (k,v) in list(mapping.items()):
if (k.startswith('src') or k.startswith('build') or k.startswith('install')) and Util.is_String(v):
v = v.strip()
if not v.endswith('/'): v += '/'
yield (k,v)
return dict(relevantPathDefs(localDefs))

2
admin/scons/DIR_INFO Normal file
View file

@ -0,0 +1,2 @@
python scripts for the scons build system

View file

@ -0,0 +1,179 @@
#!/usr/bin/python
# coding: utf-8
#
# IconSvgRenderer.py - Icon rendering utility script
#
# Copyright (C)
# 2008, Joel Holdsworth <joel@airwebreathe.org.uk>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version. See the file COPYING for further details.
#####################################################################
import os
import sys
import getopt
import shutil
from xml.dom import minidom
rsvgPath = "./rsvg-convert"
artworkLayerPrefix = "artwork:"
#
# 2/2011 some notes by Ichthyo
# The purpose of this python script is
# - to parse a SVG
# - to invoke Inkscape to render this SVG into a raster image (icon)
#
# For the actual Cairo based SVG rendering we rely on an executable 'rsvg-convert',
# which is built during the Lumiera build process.
#
# Judging from the code and the actual SVGs, this seems to work as follows:
# The SVG contains a design to be rendered into raster images of various sizes.
# These sizes are determined by special rectangles, which act as bounding box and
# are placed on a special 'plate' layer, which is a child layer of the main
# 'artwork:' layer. The grid of the SVG is setup such as to result in pixel sizes
# suitable for icon generation. The actual size of the generated icons are then
# parsed from the height and width attributes of the mentioned bounding box
# rectangles.
#
# The parser seems to be rather simplistic; the sizes and positions need to be
# integral numbers. In one instance we had a float number in the y coordinate,
# which resulted in an invalid, zero sized output icon
#
#
def createDirectory (name):
try:
if os.path.isfile (name):
os.remove (name)
if not os.path.exists (name):
os.mkdir (name)
except:
print('WARNING: createDirectory("%s") failed. Permission problems?' % name)
def copyMergeDirectory (src, dst):
listing = os.listdir (src)
for file_name in listing:
src_file_path = os.path.join (src, file_name)
dst_file_path = os.path.join (dst, file_name)
shutil.copyfile (src_file_path, dst_file_path)
def getDocumentSize (svg_element):
width = float(svg_element.getAttribute("width"))
height = float(svg_element.getAttribute("height"))
return [width, height]
def findChildLayerElement (parent_element):
for node in parent_element.childNodes:
if node.nodeType == minidom.Node.ELEMENT_NODE:
if node.tagName == "g":
if node.getAttribute("inkscape:groupmode") == "layer":
return node
return None
def parsePlateLayer (layer):
rectangles = []
for node in layer.childNodes:
if node.nodeType == minidom.Node.ELEMENT_NODE:
if node.tagName == "rect":
x = float(node.getAttribute("x"))
y = float(node.getAttribute("y"))
width = float(node.getAttribute("width"))
height = float(node.getAttribute("height"))
rectangles.append([x, y, width, height])
return rectangles
def parseSVG (file_path):
print("Parsing " + file_path)
svgdoc = minidom.parse (file_path)
for root_node in svgdoc.childNodes:
if root_node.nodeType == minidom.Node.ELEMENT_NODE:
if root_node.tagName == "svg":
size = getDocumentSize (root_node)
layer = findChildLayerElement (root_node)
if layer != None:
layer_name = layer.getAttribute ("inkscape:label")
if layer_name[:len(artworkLayerPrefix)] == artworkLayerPrefix:
artwork_name = layer_name[len(artworkLayerPrefix):]
plate = findChildLayerElement(layer)
if plate != None:
return artwork_name, size, parsePlateLayer(plate)
return None
def renderSvgRsvg (file_path, out_dir, artwork_name, rectangle, _doc_size):
# Prepare a Cairo context
width = int(rectangle[2])
height = int(rectangle[3])
if not os.path.exists(rsvgPath):
print("Error: executable %s not found." % rsvgPath)
os.spawnlp(os.P_WAIT, rsvgPath, rsvgPath,
"--source-rect=%g:%g:%g:%g" % (rectangle[0], rectangle[1], width, height),
"--output=" + os.path.join(out_dir, "%gx%g/%s.png" % (width, height, artwork_name)),
file_path)
def renderSvgIcon (file_path, out_dir):
artwork_name, doc_size, rectangles = parseSVG (file_path)
for rectangle in rectangles:
renderSvgRsvg(file_path, out_dir, artwork_name, rectangle, doc_size)
def getTargetNames (file_path):
"""get a list of target names to be rendered from the given source SVG
usable to setup the build targets for SCons
"""
artwork_name, _ , rectangles = parseSVG (file_path)
return ["%gx%g/%s.png" % (rectangle[2], rectangle[3], artwork_name) for rectangle in rectangles ]
def printHelp():
print("render-icon.py SRCFILE.svg TARGETDIR")
print("An icon rendering utility script for lumiera")
def parseArguments(argv):
_optlist, args = getopt.getopt(argv, "")
if len(args) == 2:
return args[0], args[1]
printHelp()
return None, None
def main (argv):
in_path, out_dir = parseArguments(argv)
if not (in_path and out_dir):
print("Missing arguments in_path and out_dir.")
sys.exit(1)
if os.path.isfile(out_dir):
print("Unable to use '%s' as output directory, because it\'s a file." % out_dir)
sys.exit(1)
if not os.path.isdir(out_dir):
print("Output directory '%s' not found." % out_dir)
sys.exit(1)
# Create the icons folders
createDirectory(os.path.join(out_dir, "48x48"))
createDirectory(os.path.join(out_dir, "32x32"))
createDirectory(os.path.join(out_dir, "24x24"))
createDirectory(os.path.join(out_dir, "22x22"))
createDirectory(os.path.join(out_dir, "16x16"))
renderSvgIcon (in_path, out_dir)
if __name__=="__main__":
main(sys.argv[1:])

View file

@ -0,0 +1,377 @@
# coding: utf-8
##
## LumieraEnvironment.py - custom SCons Environment
##
# Copyright (C)
# 2008, Hermann Vosseler <Ichthyostega@web.de>
#
# **Lumiera** is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version. See the file COPYING for further details.
#####################################################################
from os import path
import SCons.SConf
from SCons.Action import Action
from SCons.Environment import Environment
from Buildhelper import *
class LumieraEnvironment(Environment):
""" Custom SCons build environment for Lumiera
This allows us to carry structured config data without
using global vars. Idea inspired by Ardour.
"""
def __init__(self, buildSetup, buildVars, **kw):
kw.update(VERSION = buildSetup.VERSION
,TARGDIR = buildSetup.TARGDIR
,DESTDIR = '$INSTALLDIR/$PREFIX'
,toolpath = [buildSetup.TOOLDIR ]
,variables = buildVars
)
Environment.__init__ (self, **kw)
self.path = Record (extract_localPathDefs(buildSetup)) # e.g. buildExe -> env.path.buildExe
self.libInfo = {}
self.Tool("BuilderDoxygen")
self.Tool("ToolDistCC")
self.Tool("ToolCCache")
register_LumieraResourceBuilder(self)
register_LumieraCustomBuilders(self)
def Configure (self, *args, **kw):
kw['env'] = self
return LumieraConfigContext(*args, **kw)
def mergeConf (self,other):
""" extract the library/compiler flags from other Environment.
Optionally accepts a list or just sting(s) representing keys
in our own libInfo Dictionary
"""
if isinstance(other, list):
for elm in other:
self.mergeConf(elm)
elif isinstance(other, str):
if other in self.libInfo:
self.mergeConf(self.libInfo[other])
else:
self.Append (LIBS = other.get ('LIBS',[]))
self.Append (LIBPATH = other.get ('LIBPATH', []))
self.Append (CPPPATH = other.get('CPPPATH', []))
self.Append (LINKFLAGS = other.get('LINKFLAGS', []))
return self
def addLibInfo (self, libID, minVersion=0, alias=None):
""" use pkg-config to create an Environment describing the lib.
Don't add this defs to the current Environment, rather store
them in the libInfo Dictionary.
"""
minVersion = str(minVersion)
if 0 != os.system('pkg-config --print-errors --exists "%s >= %s"' % (libID,minVersion)):
print("Problems configuring the Library %s (>= %s)" % (libID,minVersion))
return False
self.libInfo[libID] = libInfo = Environment()
libInfo["ENV"]["PKG_CONFIG_PATH"] = os.environ.get("PKG_CONFIG_PATH")
libInfo.ParseConfig ('pkg-config --cflags --libs '+ libID )
if alias:
self.libInfo[alias] = libInfo
return libInfo
# extending the 'Configure' functionality of SCons,
# especially for library dependency checking
ConfigBase = SCons.SConf.SConfBase
class LumieraConfigContext(ConfigBase):
""" Extends the SCons Configure context with some convenience methods
"""
def __init__(self, *args,**kw):
ConfigBase.__init__(self,*args,**kw)
def CheckPkgConfig (self, libID, minVersion=0, alias=None):
print("Checking for library configuration: %s " % libID)
# self.Message(self,"Checking for library configuration: %s " % libID)
return self.env.addLibInfo (libID, minVersion, alias)
###############################################################################
####### Lumiera custom tools and builders #####################################
def register_LumieraResourceBuilder(env):
""" Registers Custom Builders for generating and installing Icons.
Additionally you need to build the tool (rsvg-convert.c)
used to generate png from the svg source using librsvg.
"""
import IconSvgRenderer as renderer # load Joel's python script for invoking the rsvg-convert (SVG render)
renderer.rsvgPath = env.subst("$TARGDIR/rsvg-convert")
def invokeRenderer(target, source, env):
source = str(source[0])
targetdir = env.subst(env.path.buildIcon)
if targetdir.startswith('#'): targetdir = targetdir[1:]
renderer.main([source,targetdir])
return 0
def createIconTargets(target,source,env):
""" parse the SVG to get the target file names """
source = str(source[0])
targetdir = env.path.buildIcon
targetfiles = renderer.getTargetNames(source) # parse SVG
# additionally create an installation task for each Icon to be generated
installLocation = env.path.installIcon
generateTargets = []
for icon in targetfiles:
icon = targetdir+icon
subdir = getDirname(str(icon))
env.Install (installLocation+subdir, icon)
generateTargets.append(icon)
return (generateTargets, source)
def IconResource(env, source):
""" copy icon pixmap to corresponding icon dir. """
subdir = getDirname(str(source))
toBuild = env.path.buildIcon+subdir
toInstall = env.path.installIcon+subdir
env.Install (toInstall, source)
return env.Install(toBuild, source)
def GuiResource(env, source):
""" pick up giben source resource and install
them (flat) into the configured target
"""
toBuild = env.path.buildUIRes
toInstall = env.path.installUIRes
env.Install (toInstall, source)
return env.Install(toBuild, source)
def ConfigData(env, prefix, source, targetDir=None):
""" install (copy) configuration- and metadata.
target dir is either the install location configured (in SConstruct),
or an explicitly given absolute or relative path segment, which might refer
to the location of the executable through the $ORIGIN token
"""
source = path.join(prefix,str(source))
subdir = getDirname(source, prefix) # removes source location path prefix
if targetDir:
if path.isabs(targetDir):
toBuild = toInstall = path.join(targetDir,subdir)
else:
if targetDir.startswith('$ORIGIN'):
targetDir = targetDir[len('$ORIGIN'):]
toBuild = path.join(env.path.buildExe, targetDir, subdir)
toInstall = path.join(env.path.installExe, targetDir, subdir)
else:
toBuild = path.join(env.path.buildConf, targetDir, subdir)
toInstall = path.join(env.path.installConf, targetDir, subdir)
else:
toBuild = path.join(env.path.buildConf,subdir)
toInstall = path.join(env.path.installConf,subdir)
env.Install (toInstall, source)
return env.Install(toBuild, source)
buildIcon = env.Builder( action = Action(invokeRenderer, "rendering Icon: $SOURCE --> $TARGETS")
, single_source = True
, emitter = createIconTargets
)
env.Append(BUILDERS = {'IconRender' : buildIcon})
env.AddMethod(IconResource)
env.AddMethod(GuiResource)
env.AddMethod(ConfigData)
class WrappedStandardExeBuilder(SCons.Util.Proxy):
""" Helper to add customisations and default configurations to SCons standard builders.
The original builder object is wrapped and most calls are simply forwarded to this
wrapped object by Python magic. But some calls are intercepted in order to inject
suitable default configuration based on the project setup.
"""
def __init__(self, originalBuilder):
SCons.Util.Proxy.__init__ (self, originalBuilder)
def __bool__(self): return True
def __call__(self, env, target=None, source=None, **kw):
""" when the builder gets invoked from the SConscript...
create a clone environment for specific configuration
and then pass on the call to the wrapped original builder.
Automatically define installation targets for build results.
@note only returning the build targets, not the install targets
"""
customisedEnv = self.getCustomEnvironment(env, target=target, **kw) # defined in subclasses
buildTarget = self.buildLocation(customisedEnv, target)
buildTarget = self.invokeOriginalBuilder(customisedEnv, buildTarget, source, **kw)
self.installTarget(customisedEnv, buildTarget, **kw)
return buildTarget
def invokeOriginalBuilder(self, env, target, source, **kw):
return self.get().__call__ (env, target, source, **kw)
def buildLocation(self, env, target):
""" prefix project output directory """
prefix = self.getBuildDestination(env)
return list(prefix+str(name) for name in target)
def installTarget(self, env, buildTarget, **kw):
""" create an additional installation target
for the generated executable artifact
"""
indeedInstall = lambda p: p and p.get('install')
if indeedInstall(kw):
return env.Install (dir = self.getInstallDestination(env), source=buildTarget)
else:
return []
class LumieraExeBuilder(WrappedStandardExeBuilder):
def getCustomEnvironment(self, lumiEnv, **kw):
""" augments the built-in Program() builder to add a fixed rpath based on $ORIGIN
That is: after searching LD_LIBRARY_PATH, but before the standard linker search,
the directory relative to the position of the executable ($ORIGIN) is searched.
This search path is active not only for the executable, but for all libraries
it is linked with.
@note: enabling the new ELF dynamic tags. This causes a DT_RUNPATH to be set,
which results in LD_LIBRARY_PATH being searched *before* the RPATH
"""
custEnv = lumiEnv.Clone()
custEnv.Append( LINKFLAGS = "-Wl,-rpath=\\$$ORIGIN/modules,--enable-new-dtags" )
custEnv.Append( LINKFLAGS = "-Wl,-rpath-link=target/modules" ) ### Workaround for bug in binutils > 2.23 /////TICKET #965
if 'addLibs' in kw:
custEnv.Append(LIBS = kw['addLibs'])
return custEnv
def getBuildDestination(self, lumiEnv): return lumiEnv.path.buildExe
def getInstallDestination(self, lumiEnv): return lumiEnv.path.installExe
class LumieraModuleBuilder(WrappedStandardExeBuilder):
def getCustomEnvironment(self, lumiEnv, target, **kw):
""" augments the built-in SharedLibrary() builder to add some tweaks missing in SCons 1.0,
like setting a SONAME proper instead of just passing the relative pathname to the linker.
Besides, we override the library search path to allow for transitive dependencies between
Lumiera modules; modules are assumed to reside in a subdirectory below the executable.
"""
custEnv = lumiEnv.Clone()
custEnv.Append(LINKFLAGS = "-Wl,-soname="+self.defineSoname(target,**kw))
custEnv.Append( LINKFLAGS = "-Wl,-rpath=\\$$ORIGIN/../modules,--enable-new-dtags" )
if 'addLibs' in kw:
custEnv.Append(LIBS = kw['addLibs'])
return custEnv
def getBuildDestination(self, lumiEnv): return lumiEnv.path.buildLib
def getInstallDestination(self, lumiEnv): return lumiEnv.path.installLib
def defineSoname (self, target, **kw):
""" internal helper to extract or guess
a suitable library SONAME, either using an
explicit spec, falling back on the lib filename
"""
if 'soname' in kw:
soname = self.subst(kw['soname']) # explicitly defined by user
else: # else: use the library filename as DT_SONAME
if SCons.Util.is_String(target):
pathname = target.strip()
elif 1 == len(target):
pathname = str(target[0]).strip()
else:
raise SyntaxError("Lumiera Library builder requires exactly one target spec. Found target="+str(target))
assert pathname
(dirprefix, libname) = path.split(pathname)
if not libname:
raise ValueError("Library name missing. Only got a directory: "+pathname)
soname = "${SHLIBPREFIX}%s$SHLIBSUFFIX" % libname
assert soname
return soname
class LumieraPluginBuilder(LumieraModuleBuilder):
def getCustomEnvironment(self, lumiEnv, target, **kw):
""" in addition to the ModuleBuilder, define the Lumiera plugin suffix
"""
custEnv = LumieraModuleBuilder.getCustomEnvironment(self, lumiEnv, target, **kw)
custEnv.Append (CPPDEFINES='LUMIERA_PLUGIN')
custEnv.Replace(SHLIBPREFIX='', SHLIBSUFFIX='.lum')
return custEnv
def getBuildDestination(self, lumiEnv): return lumiEnv.path.buildPlug
def getInstallDestination(self, lumiEnv): return lumiEnv.path.installPlug
def register_LumieraCustomBuilders (lumiEnv):
""" install the customised builder versions tightly integrated with our build system.
Especially, these builders automatically add the build and installation locations
and set the RPATH and SONAME in a way to allow a relocatable Lumiera directory structure
"""
programBuilder = LumieraExeBuilder (lumiEnv['BUILDERS']['Program'])
libraryBuilder = LumieraModuleBuilder (lumiEnv['BUILDERS']['SharedLibrary'])
smoduleBuilder = LumieraModuleBuilder (lumiEnv['BUILDERS']['LoadableModule'])
lpluginBuilder = LumieraPluginBuilder (lumiEnv['BUILDERS']['LoadableModule'])
lumiEnv['BUILDERS']['Program'] = programBuilder
lumiEnv['BUILDERS']['SharedLibrary'] = libraryBuilder
lumiEnv['BUILDERS']['LoadableModule'] = smoduleBuilder
lumiEnv['BUILDERS']['LumieraPlugin'] = lpluginBuilder
def SymLink(env, target, source, linktext=None):
""" use python to create a symlink
"""
def makeLink(target,source,env):
if linktext:
dest = linktext
else:
dest = str(source[0])
link = str(target[0])
os.symlink(dest, link)
if linktext: srcSpec=linktext
else: srcSpec='$SOURCE'
action = Action(makeLink, "Install link: $TARGET -> "+srcSpec)
env.Command (target,source, action)
# adding SymLink directly as method on the environment object
# Probably that should better be a real builder, but I couldn't figure out
# how to get the linktext through literally, which is necessary for relative links.
# Judging from the sourcecode of SCons.Builder.BuilderBase, there seems to be no way
# to set the executor_kw, which are passed through to the action object.
lumiEnv.AddMethod(SymLink)

73
admin/scons/Options.py Normal file
View file

@ -0,0 +1,73 @@
# coding: utf-8
##
## Options.py - SCons build: command line options and help
##
# Copyright (C)
# 2012, Hermann Vosseler <Ichthyostega@web.de>
#
# **Lumiera** is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version. See the file COPYING for further details.
#####################################################################
from SCons.Script import PathVariable, EnumVariable, BoolVariable, Help
def defineCmdlineVariables(buildVars):
""" several toggles and configuration variables can be set on the commandline,
current settings will be persisted in a options cache file.
you may define custom variable settings in a separate file.
Commandline will override both.
"""
buildVars.AddVariables(
('ARCHFLAGS', 'Set architecture-specific compilation flags (passed literally to gcc)','')
,('CC', 'Set the C compiler to use.', 'gcc')
,('CXX', 'Set the C++ compiler to use.', 'g++')
,PathVariable('CCACHE', 'Integrate with CCache', '', PathVariable.PathAccept)
,PathVariable('DISTCC', 'Invoke C/C++ compiler commands through DistCC', '', PathVariable.PathAccept)
,EnumVariable('BUILDLEVEL', 'NoBug build level for debugging', 'ALPHA', allowed_values=('ALPHA', 'BETA', 'RELEASE'))
,BoolVariable('DEBUG', 'Build with debugging information and no optimisations', False)
,BoolVariable('OPTIMIZE', 'Build with strong optimisation (-O3)', False)
,BoolVariable('VALGRIND', 'Run Testsuite under valgrind control', True)
,BoolVariable('VERBOSE', 'Print full build commands', False)
,('TESTSUITES', 'Run only test suites matching the given pattern', '')
,('TESTMODE', 'test suite error mode for test.sh', '')
# ,BoolVariable('OPENGL', 'Include support for OpenGL preview rendering', False)
# ,EnumVariable('DIST_TARGET', 'Build target architecture', 'auto',
# allowed_values=('auto', 'i386', 'i686', 'x86_64' ), ignorecase=2)
,PathVariable('PREFIX', 'Installation dir prefix', 'usr/local', PathVariable.PathAccept)
,PathVariable('INSTALLDIR', 'Root output directory for install. Final installation will happen in INSTALLDIR/PREFIX/... ', '/', PathVariable.PathIsDir)
,PathVariable('PKGLIBDIR', 'Installation dir for plugins, defaults to PREFIX/lib/lumiera/modules', '',PathVariable.PathAccept)
,PathVariable('PKGDATADIR', 'Installation dir for default config, usually PREFIX/share/lumiera', '',PathVariable.PathAccept)
)
def prepareOptionsHelp(buildVars,env):
prelude = """
USAGE: scons [-c] [OPTS] [key=val [key=val...]] [TARGETS]
Build and optionally install Lumiera.
Without specifying any target, just the (re)build target will run.
Add -c to the commandline to clean up anything a given target would produce
Special Targets:
build : just compile and link
research: build experimental code (might fail)
testcode: additionally compile the Testsuite
check : build and run the Testsuite
doc : generate documentation (Doxygen)
all : build and testcode and doc
install : install created artifacts at PREFIX
Configuration Options:
"""
Help(prelude + buildVars.GenerateHelpText(env))

152
admin/scons/Platform.py Normal file
View file

@ -0,0 +1,152 @@
# coding: utf-8
##
## Platform.py - SCons build: platform configuration and library detection
##
# Copyright (C)
# 2012, Hermann Vosseler <Ichthyostega@web.de>
#
# **Lumiera** is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version. See the file COPYING for further details.
#####################################################################
from SCons.Script import Exit
from Buildhelper import isCleanupOperation, isHelpRequest
def configure(env):
""" locate required libraries.
setup platform specific options.
Abort build in case of failure.
"""
if isCleanupOperation(env) or isHelpRequest():
return env # skip configure in these cases
conf = env.Configure()
# run all configuration checks in the build environment defined thus far
# Perform checks for prerequisites --------------------------------------------
problems = []
if not conf.TryAction('pkg-config --version > $TARGET')[0]:
problems.append('We need pkg-config for including library configurations, exiting.')
if not conf.CheckLibWithHeader('m', 'math.h','C'):
problems.append('Did not find math.h / libm.')
if not conf.CheckLibWithHeader('dl', 'dlfcn.h', 'C'):
problems.append('Functions for runtime dynamic loading not available.')
if not conf.CheckLibWithHeader('pthread', 'pthread.h', 'C'):
problems.append('Did not find the pthread lib or pthread.h.')
else:
conf.env.Append(CPPFLAGS = ' -DHAVE_PTHREAD')
conf.env.Append(CCFLAGS = ' -pthread')
if not conf.CheckLib(symbol='clock_gettime', library='rt'): # note librt is usually installed with libc6
problems.append('We expect the POSIX realtime extensions to be available through librt. ' +
'Unable to use clock_gettime()')
if conf.CheckCHeader('execinfo.h'):
conf.env.Append(CPPFLAGS = ' -DHAVE_EXECINFO_H')
if conf.CheckCHeader('valgrind/valgrind.h'):
conf.env.Append(CPPFLAGS = ' -DHAVE_VALGRIND_H')
else:
print('Valgrind not found. The use of Valgrind is optional; building without.')
if not conf.CheckPkgConfig('nobugmt', 201008.1):
problems.append('Did not find NoBug [http://nobug.pipapo.org/].')
else:
conf.env.mergeConf('nobugmt')
if not conf.CheckCXXHeader('memory'):
problems.append('We rely on the C++11 smart-pointers.')
if not conf.CheckCXXHeader('functional'):
problems.append('We rely on the C++11 functor objects.')
if not conf.CheckLibWithHeader('stdc++fs', 'filesystem', 'C++'):
problems.append('We need the C++17 filesystem support.')
if not conf.CheckCXXHeader('boost/config.hpp'):
problems.append('We need the C++ boost-libraries.')
else:
if not conf.CheckCXXHeader('boost/lexical_cast.hpp'):
problems.append('We need boost::lexical_cast')
if not conf.CheckCXXHeader('boost/format.hpp'):
problems.append('We need boost::format (header).')
if not conf.CheckLibWithHeader('boost_program_options','boost/program_options.hpp','C++'):
problems.append('We need boost::program_options (including binary lib for linking).')
if not conf.CheckPkgConfig('gavl', '1.4'):
problems.append('Did not find Gmerlin Audio Video Lib [https://github.com/bplaum/gavl].')
else:
conf.env.mergeConf('gavl')
if not conf.CheckPkgConfig('alsa', '1.0.23'):
problems.append('Support for ALSA sound output is required')
if not conf.CheckPkgConfig('gtkmm-3.0', '3.10'):
problems.append('Unable to configure the mm-bindings for GTK-3')
if not conf.CheckPkgConfig('glibmm-2.4', '2.39'):
problems.append('Unable to configure the mm-bindings for Glib')
if not conf.CheckPkgConfig('sigc++-2.0', '2.2.10'):
problems.append('Need the signal-slot-binding library SigC++2')
if not conf.CheckPkgConfig('glib-2.0', '2.40'):
problems.append('Need a suitable Glib version.')
if not conf.CheckPkgConfig('gthread-2.0', '2.40'):
problems.append('Need gthread support lib for Glib based thread handling.')
if not conf.CheckPkgConfig('cairomm-1.0', '1.10'):
problems.append('Unable to configure Cairo--')
verGDL = '3.8' # lowered requirements to allow building on Ubuntu/Trusty & Mint (was originally '3.12')
verGDLmm = '3.7.3'
urlGDLmm = 'http://ftp.gnome.org/pub/GNOME/sources/gdlmm/'
urlGDLmmDEB = 'http://lumiera.org/debian/'
if not conf.CheckPkgConfig('gdl-3.0', verGDL):
problems.append('GNOME Docking Library not found. We need at least GDL %s '
'and suitable C++ ("mm")-bindings (GDLmm >=%s)' % (verGDL, verGDLmm))
if not conf.CheckPkgConfig('gdlmm-3.0', verGDLmm, alias='gdl'):
problems.append('We need the C++ bindings for GDL by Fabien Parent: GDLmm >=%s '
'(either from GNOME %s or use the debian package from %s)' %
(verGDLmm, urlGDLmm, urlGDLmmDEB))
if not conf.CheckPkgConfig('librsvg-2.0', '2.30'):
problems.append('Need rsvg Library for rendering icons.')
if not conf.CheckCHeader(['X11/Xutil.h', 'X11/Xlib.h'],'<>'):
problems.append('Xlib.h and Xutil.h required. Please install libx11-dev.')
# NOTE the following dependencies where for the video displayer widget.
# As of 11/2015 this is broken and disabled. Might be obsolete....
if not conf.CheckPkgConfig('xv') : problems.append('Need libXv...')
if not conf.CheckPkgConfig('x11') : problems.append('Need X-lib...') # for the xvdisplayer widget
if not conf.CheckPkgConfig('xext'): problems.append('Need libXext.')
# report missing dependencies
if problems:
print("*** unable to build due to the following problems:")
for isue in problems:
print(" * %s" % isue)
print()
print("build aborted.")
Exit(1)
print("** Gathered Library Info: %s" % list(conf.env.libInfo.keys()))
# create new env containing the finished configuration
return conf.Finish()

131
admin/scons/Setup.py Normal file
View file

@ -0,0 +1,131 @@
# coding: utf-8
##
## Setup.py - SCons build: setup, definitions and compiler flags
##
# Copyright (C)
# 2012, Hermann Vosseler <Ichthyostega@web.de>
#
# **Lumiera** is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version. See the file COPYING for further details.
#####################################################################
from SCons.Script import EnsurePythonVersion, EnsureSConsVersion, Variables, Decider
from LumieraEnvironment import *
from Buildhelper import *
import Options
#-------------------------------------------------------Configuration
TARGDIR = 'target'
VERSION = '0.pre.04~rc.1'
TOOLDIR = './admin/scons' # SCons plugins
OPTCACHE = 'optcache'
CUSTOPTFILE = 'custom-options'
# these are accessible via env.path.xxxx
buildExe = '#$TARGDIR'
buildLib = '#$TARGDIR/modules'
buildPlug = '#$TARGDIR/modules'
buildIcon = '#$TARGDIR/gui/icons' # for IconResource() and IconRender()
buildUIRes = '#$TARGDIR/gui/' # for GuiResource()
buildConf = '#$TARGDIR/config' # for ConfigData()
installExe = '#$DESTDIR/lib/lumiera'
installLib = '#$DESTDIR/lib/lumiera/modules'
installPlug = '#$DESTDIR/lib/lumiera/modules'
installIcon = '#$DESTDIR/share/lumiera/icons'
installUIRes = '#$DESTDIR/share/lumiera/'
installConf = '#$DESTDIR/lib/lumiera/config'
#-------------------------------------------------------Configuration
buildSetup = Record(locals())
def defineBuildEnvironment():
""" create a custom build environment,
define the basic compiler and linker flags,
define locations in source and target tree,
parse the commandline and pick up options
"""
EnsureSConsVersion(2,0)
EnsurePythonVersion(2,6)
Decider('MD5-timestamp') # detect changed files by timestamp, then do a MD5
buildVars = Variables([OPTCACHE, CUSTOPTFILE])
Options.defineCmdlineVariables(buildVars)
env = LumieraEnvironment(buildSetup, buildVars)
env.Replace( CPPPATH =["#src"] # used to find includes, "#" means always absolute to build-root
, CPPDEFINES=['LUMIERA_VERSION='+VERSION ] # note: it's a list to append further defines
, CCFLAGS='-Wall -Wextra -Wformat-security'
, CXXFLAGS='-std=gnu++23 -Wno-enum-compare'
, CFLAGS='-std=gnu99'
)
env.Append(LINKFLAGS='-Wl,--no-undefined') # require every dependency is given on link, in the right order
env.Append(LINKFLAGS='-Wl,--as-needed') # by default only link against dependencies actually needed to resolve symbols
handleVerboseMessages(env)
handleNoBugSwitches(env)
env.Append(CPPDEFINES = '_GNU_SOURCE')
appendCppDefine(env,'DEBUG','DEBUG', 'NDEBUG')
# appendCppDefine(env,'OPENGL','USE_OPENGL')
appendVal(env,'ARCHFLAGS','CCFLAGS') # for both C and C++
appendVal(env,'OPTIMIZE', 'CCFLAGS', val=' -O3')
appendVal(env,'DEBUG', 'CCFLAGS', val=' -ggdb')
# setup search path for Lumiera plugins
appendCppDefine(env,'PKGLIBDIR','LUMIERA_PLUGIN_PATH=\\"$PKGLIBDIR/:ORIGIN/modules\\"'
,'LUMIERA_PLUGIN_PATH=\\"ORIGIN/modules\\"')
appendCppDefine(env,'PKGDATADIR','LUMIERA_CONFIG_PATH=\\"$PKGLIBDIR/:.\\"'
,'LUMIERA_CONFIG_PATH=\\"$DESTDIR/share/lumiera/:.\\"')
Options.prepareOptionsHelp(buildVars,env)
buildVars.Save(OPTCACHE, env)
return env
def appendCppDefine(env,var,cppVar, elseVal=''):
if env[var]:
env.Append(CPPDEFINES = env.subst(cppVar) )
elif elseVal:
env.Append(CPPDEFINES = env.subst(elseVal))
def appendVal(env,var,targetVar,val=None):
if env[var]:
env.Append( **{targetVar: env.subst(val) or env[var]})
def handleNoBugSwitches(env):
""" set the build level for NoBug.
Release builds imply no DEBUG
whereas ALPHA and BETA require DEBUG
"""
level = env['BUILDLEVEL']
if level in ['ALPHA', 'BETA']:
if not env['DEBUG']:
print('Warning: NoBug ALPHA or BETA builds requires DEBUG=yes, switching DEBUG on!')
env.Replace( DEBUG = 1 )
env.Append(CPPDEFINES = 'EBUG_'+level)
elif level == 'RELEASE':
env.Replace( DEBUG = 0 )
def handleVerboseMessages(env):
""" toggle verbose build output """
if not env['VERBOSE']:
# SetOption('silent', True)
env['CCCOMSTR'] = env['SHCCCOMSTR'] = " Compiling $SOURCE"
env['CXXCOMSTR'] = env['SHCXXCOMSTR'] = " Compiling++ $SOURCE"
env['LINKCOMSTR'] = " Linking --> $TARGET"
env['LDMODULECOMSTR'] = " creating module [ $TARGET ]"

67
admin/scons/ToolCCache.py Normal file
View file

@ -0,0 +1,67 @@
# coding: utf-8
##
## ToolCCache.py - SCons tool for integrating with CCache compiler cache
##
# Copyright (C) Lumiera.org and FreeOrion.org
# 2008, Hermann Vosseler <Ichthyostega@web.de>
#
# **Lumiera** is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version. See the file COPYING for further details.
#####################################################################
# This SCons builder was extracted from http://www.freeorion.org/
# FreeOrion is an open-source platform-independent galactic conquest game
#
# history: 12/2008 adapted for Lumiera build system
import os
from Buildhelper import *
def generate(env):
""" Modify the environment such as to redirect any
C/C++ compiler invocations through CCache, while using
CCache config variables found in the os.environment.
"""
if not exists(env): return
assert env['CCACHE']
if not env['CCACHE'] in env['CC']:
env['CC'] = env.subst('$CCACHE $CC')
if not env['CCACHE'] in env['CXX']:
env['CXX'] = env.subst('$CCACHE $CXX')
print(env.subst("* Build using $CCACHE"))
for i in ['HOME'
,'CCACHE_DIR'
,'CCACHE_TEMPDIR'
,'CCACHE_LOGFILE'
,'CCACHE_PATH'
,'CCACHE_CC'
,'CCACHE_CPP2'
,'CCACHE_PREFIX'
,'CCACHE_DISABLE'
,'CCACHE_READONLY'
,'CCACHE_NOSTATS'
,'CCACHE_NLEVELS'
,'CCACHE_HARDLINK'
,'CCACHE_RECACHE'
,'CCACHE_UMASK'
,'CCACHE_HASHDIR'
,'CCACHE_UNIFY'
,'CCACHE_EXTENSION'
]:
if i in os.environ and i not in env:
env['ENV'][i] = os.environ[i]
def exists(env):
""" Ensure CCache is available.
"""
return checkCommandOption(env, 'CCACHE', cmdName='ccache')

56
admin/scons/ToolDistCC.py Normal file
View file

@ -0,0 +1,56 @@
# coding: utf-8
##
## ToolDistCC.py - SCons tool for distributed compilation using DistCC
##
# Copyright (C) Lumiera.org and FreeOrion.org
# 2008, Hermann Vosseler <Ichthyostega@web.de>
#
# **Lumiera** is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version. See the file COPYING for further details.
#####################################################################
# This SCons builder was extracted from http://www.freeorion.org/
# FreeOrion is an open-source platform-independent galactic conquest game
#
# history: 12/2008 adapted for Lumiera build system
import os
from Buildhelper import *
def generate(env):
""" Modify the environment such as to redirect any
C/C++ compiler invocations through DistCC. Additionally
pull in the environment config variables used by DistCC
"""
if not exists(env): return
assert env['DISTCC']
if not env['DISTCC'] in env['CC']:
env['CC'] = env.subst('$DISTCC $CC')
if not env['DISTCC'] in env['CXX']:
env['CXX'] = env.subst('$DISTCC $CXX')
print(env.subst("* Build using $DISTCC"))
for i in ['HOME'
,'DISTCC_HOSTS'
,'DISTCC_VERBOSE'
,'DISTCC_FALLBACK'
,'DISTCC_LOG'
,'DISTCC_MMAP'
,'DISTCC_SAVE_TEMPS'
,'DISTCC_TCP_CORK'
,'DISTCC_SSH'
]:
if i in os.environ and i not in env:
env['ENV'][i] = os.environ[i]
def exists(env):
""" Ensure DistCC exists.
"""
return checkCommandOption(env, 'DISTCC', cmdName='distcc')

44
admin/setVersion Executable file
View file

@ -0,0 +1,44 @@
#!/bin/bash
#
# setVersion - place the version info given as argument
# into all the necessary places in the Lumiera tree
#
#
set -e
function fail() {
echo -e "\nFAIL: $1\n\n"
exit -1
}
PROJ_ROOT=$(git rev-parse --show-toplevel)
cd $PROJ_ROOT
[ $# -eq 1 ] || fail "need version as argument\n\nsetVersion <ver>"
[ -n "$1" ] || fail "need a nonemty version spec"
VER="$1"
function rewrite() {
# Process the indicated file with sed and replace the existing version spec
# The PREFIX argument must match everything from line start before the version;
# then the _remainder_ of this line will be replaced by the NEWVER
FILE="$1"
PREFIX="$2"
NEWVER="$3"
echo "rewrite..... $FILE"
egrep -q "^$PREFIX" $FILE || fail "not found in $FILE : $PREFIX"
#
sed -r -f - -i "$FILE" <<END_SCRIPT
/^$PREFIX/ {
s/(^$PREFIX).+/\1 $NEWVER/
}
END_SCRIPT
}
rewrite data/config/setup.ini 'version\s*=' "$VER"
rewrite doc/devel/Doxyfile 'PROJECT_NUMBER\s*=' "$VER"
rewrite doc/devel/Doxyfile.browse 'PROJECT_NUMBER\s*=' "$VER"
rewrite admin/scons/Setup.py 'VERSION\s*=' "\'$VER\'"
rewrite README 'Version:' "$VER"
echo -e "\nSUCCESSFULLY rewritten version $VER\ncheck git diff\n\n"

52
admin/testfilter.sh Executable file
View file

@ -0,0 +1,52 @@
#!/bin/sh
#
# Little hack to filter nobug logging output producing something suiteable for testsuites
#
gawk --posix -f /dev/fd/3 3<<"EOF"
BEGIN {
FS = ": "
toescape = "[]().*{}"
prev = ""
LOGSUPPRESS="TRACE|INFO|NOTICE|WARNING|ERR|TODO|PLANNED|FIXME|DEPRECATED|UNIMPLEMENTED|RESOURCE_ANNOUNCE|RESOURCE_ENTER|RESOURCE_STATE|RESOURCE_LEAVE"
}
function escape(string) {
for (i = 1; i <= length(toescape); ++i)
gsub("\\"substr(toescape, i, 1), "\\"substr(toescape, i, 1), string)
return string
}
function linerest(start, end) {
result = $start
for (i = start+1; i <= end; i++)
{
result = result": "$i
}
return result
}
function remove_duplicate_spaces(rest) {
return "foo"rest"bar"
}
/[0-9]{10}: [A-Z]*: / {
rest = linerest(6, NF);
rest = escape(rest)
gsub(/0x[0-9a-f]+/,"0x[0-9a-f]+", rest)
new = $2 ": .*: " $4 ": " $5 ": " rest
if (new != prev && !(new ~ LOGSUPPRESS))
{
print "err: " new
prev = new
}
}
EOF

3
admin/treeinfo.sh Executable file
View file

@ -0,0 +1,3 @@
#!/bin/sh
COLUMNS=$(tput cols)
find -name DIR_INFO -printf '%-30h: ' -exec head -1 {} \; | sort -k1,1 | cut -c 1-${COLUMNS:-92}

51
admin/vg-run.sh Normal file
View file

@ -0,0 +1,51 @@
#!/bin/bash
#
# vg-run.sh - convenience wrapper script to run an executable with valgrind
# using "typical options"; output goes to a logfile, which is
# fed to less afterwards.
#
# a valgrind suppression file is generated automatically, in
# case there is an executable "vgsuppression" located in the same
# directory as the target executable
#
# Ichthyo 8/2007
#
LOGFILE=,valgrind.log
SUPPRESS=vgsuppression
MODULEDIR=modules
VALGRINDFLAGS=${VALGRINDFLAGS:---leak-check=yes --show-reachable=yes --demangle=yes}
EXECUTABLE=$1
if [[ ! -x $EXECUTABLE ]]; then
echo -e "ERROR: executable \"$EXECUTABLE\" not found.\n\n"
exit -1
fi
PATHPREFIX=${EXECUTABLE%/*}
SUPPRESS="$PATHPREFIX/$SUPPRESS"
# need to set a library search path, because valgrind doesn't handle DT_RUNPATH and $ORIGIN properly
export LD_LIBRARY_PATH=$PATHPREFIX/$MODULEDIR:$LD_LIBRARY_PATH
if [[ -x $SUPPRESS ]]; then
if [[ $SUPPRESS -nt $SUPPRESS.supp ]]; then
echo 'generating valgrind supression file...'
valgrind $VALGRINDFLAGS -q --gen-suppressions=all $SUPPRESS 2>&1 \
| awk '/^{/ {i = 1;} /^}/ {i = 0; print $0;} {if (i == 1) print $0;}' >$SUPPRESS.supp
echo 'done.'
fi
SUPPRESSIONFLAG="--suppressions=$SUPPRESS.supp"
else
echo 'no suppression.'
fi
echo "running......$@"
valgrind $VALGRINDFLAGS --log-file=$LOGFILE.%p $SUPPRESSIONFLAG $@ &
PID=$!
wait $PID
less $LOGFILE.$PID

3
admin/vgsuppression_gen.sh Executable file
View file

@ -0,0 +1,3 @@
#!/bin/sh
valgrind --leak-check=yes --show-reachable=yes --gen-suppressions=all ./vgsuppression 2>&1 | sed '/==[0-9]*==/d;'

1
data/DIR_INFO Normal file
View file

@ -0,0 +1 @@
Additional configuration, icons, graphics for install

25
data/SConscript Normal file
View file

@ -0,0 +1,25 @@
# -*- python -*-
##
## SConscript - SCons buildscript for Icons and Resources
##
from Buildhelper import scanSubtree
Import('env')
# define Icons to render and install
vector_icon_dir = 'icons/svg'
prerendered_icon_dir = 'icons/prerendered'
icons = ( [env.IconRender(f) for f in scanSubtree(vector_icon_dir, ['*.svg'])]
+ [env.IconResource(f) for f in scanSubtree(prerendered_icon_dir, ['*.png'])]
)
#define Configuration files to install (dir-prefix, name)
config = ( env.ConfigData('config','setup.ini', targetDir='$ORIGIN')
+ env.ConfigData('config','dummy_lumiera.ini')
)
Export('icons config')

1
data/config/DIR_INFO Normal file
View file

@ -0,0 +1 @@
Lumiera configuration files

View file

@ -0,0 +1,4 @@
# This is an dummy Lumiera config file
#
# Actually Lumiera can't yet load any extended config, as of 1/2011
#

24
data/config/setup.ini Normal file
View file

@ -0,0 +1,24 @@
###########################################################
# ### Lumiera installation and platform configuration ###
#
# (file located relative to the Lumiera executable)
#
[Lumiera]
# Setup of the Lumiera video editor main application.
# $ORIGIN denotes the directory of the executable.
#
gui = gtk_gui.lum
modulepath = $ORIGIN/modules
configpath = $ORIGIN/../../share/lumiera/config:$ORIGIN/config:~/.lumiera # currently unused (2/2011)
title = Lumiera
version = 0.pre.04~rc.1
website = http://www.lumiera.org
authors = Joel Holdsworth|Christian Thäter|Hermann Voßeler|Stefan Kangas|Michael Fisher|Michael Ploujnikov|and others...
copyright = 2007 - 2025
[Gui]
#stylesheet = lumiera.css
stylesheet = lumiera-light-theme-complement.css
iconpath = $ORIGIN/../../share/lumiera/icons:$ORIGIN/gui/icons
resourcepath = $ORIGIN/../../share/lumiera:$ORIGIN/gui

26
data/icons/README Normal file
View file

@ -0,0 +1,26 @@
#
# Lumiera Icon Artwork
#
# Copyright (C) Lumiera.org
# 2008, Joel Holdsworth <joel@airwebreathe.org.uk>
#
# Icon Artwork and similar materials accompanying the Lumiera Application
# is dual-licensed under the GNU General Public License version 2 or above,
# and
# Creative Commons Attribution-ShareAlike 3.0 Unported License
#
#
This directory holds Icons and similar graphics resources for the Lumiera GUI.
- prerendered: Raster image Icons rendered into a selection of sizes
- svg: Scalable Vector Grahpics Icons, to be rendered into suitable sizes
by the build process. Rendering is done with the help of lib Cairo.
The build creates an executable from src/tools/rsvg-convert.c
The invocation of the icon rendering is done with the help of a
Python script IconSvgRenderer.py, which first parses the SVG document
and then invokes rsvg-convert to generate the raster images.

Binary file not shown.

After

Width:  |  Height:  |  Size: 540 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 788 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -0,0 +1,206 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="150"
height="100"
id="icon"
sodipodi:version="0.32"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
version="1.0"
sodipodi:docname="__Icon_TEMPLATE.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<title
id="doctitle">Icon: TEMPLATE</title>
<defs
id="defsz" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="8"
inkscape:cx="75"
inkscape:cy="50"
inkscape:document-units="px"
inkscape:current-layer="aardvark"
showgrid="false"
inkscape:snap-nodes="true"
inkscape:snap-bbox="true"
inkscape:snap-global="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1680"
inkscape:window-height="1050"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="pixelgrid"
visible="true"
enabled="true"
spacingx="0.5"
spacingy="0.5"
empspacing="2"
originx="0"
originy="0" />
</sodipodi:namedview>
<metadata
id="metadead">
<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>Icon: TEMPLATE</dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
<dc:creator>
<cc:Agent>
<dc:title>Ichthyostega</dc:title>
</cc:Agent>
</dc:creator>
<dc:publisher>
<cc:Agent>
<dc:title>Lumiera.org</dc:title>
</cc:Agent>
</dc:publisher>
<dc:description>TEMPLATE for new SVG Icons
prepared for Lumiera build :: Icon rendering</dc:description>
<dc:date>never</dc:date>
<dc:identifier>icon:template</dc:identifier>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
inkscape:label="artwork:placement"
id="aardvark"
style="display:inline">
<g
inkscape:groupmode="layer"
id="layerp"
inkscape:label="plate#1"
style="display:none"
sodipodi:insensitive="true">
<rect
id="bbox48"
x="8"
y="44"
width="48"
height="48"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox32"
x="60"
y="60"
width="32"
height="32"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox24"
x="96"
y="68"
width="24"
height="24"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox22"
x="97"
y="69"
width="22"
height="22"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox16"
x="124"
y="76"
width="16"
height="16"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
</g>
<g
id="gicon48">
<rect
id="dummy48"
x="8.5"
y="44.5"
width="47"
height="47"
rx="0"
ry="0"
style="fill:none;fill-opacity:0.5;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:1, 1;stroke-dashoffset:0.5;stroke-opacity:1;marker:none" />
</g>
<g
id="gicon32">
<rect
id="dummy32"
x="60.5"
y="60.5"
width="31"
height="31"
rx="0"
ry="0"
style="fill:none;fill-opacity:0.5;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:1, 1;stroke-dashoffset:0.5;stroke-opacity:1;marker:none" />
</g>
<g
id="gicon24">
<rect
id="dummy24"
x="97.5"
y="69.5"
width="21"
height="21"
rx="0"
ry="0"
style="fill:none;fill-opacity:0.5;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:1, 1;stroke-dashoffset:0.5;stroke-opacity:1;marker:none" />
</g>
<g
id="gicon16">
<rect
id="dummy16"
x="124.5"
y="76.5"
width="15"
height="15"
rx="0"
ry="0"
style="fill:none;fill-opacity:0.5;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:2;stroke-dasharray:1, 1;stroke-dashoffset:0.5;stroke-opacity:1;marker:none" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

713
data/icons/svg/app-icon.svg Normal file
View file

@ -0,0 +1,713 @@
<?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="150"
height="100"
id="icon"
sodipodi:version="0.32"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
version="1.0"
sodipodi:docname="app-icon.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<title
id="doctitle">App-icon</title>
<defs
id="defsz">
<linearGradient
inkscape:collect="always"
id="linearGradient10047">
<stop
style="stop-color:#555753;stop-opacity:1"
offset="0"
id="stop10049" />
<stop
style="stop-color:#eeeeec;stop-opacity:1"
offset="1"
id="stop10051" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient10027">
<stop
style="stop-color:#555753;stop-opacity:1"
offset="0"
id="stop10029" />
<stop
id="stop10045"
offset="0.82309282"
style="stop-color:#555753;stop-opacity:1" />
<stop
id="stop10035"
offset="0.92868489"
style="stop-color:#d3d7cf;stop-opacity:1" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop10031" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient9856">
<stop
style="stop-color:#888a85;stop-opacity:1"
offset="0"
id="stop9858" />
<stop
id="stop9864"
offset="0.04709055"
style="stop-color:#888a85;stop-opacity:1" />
<stop
style="stop-color:#555753;stop-opacity:1"
offset="0.23050508"
id="stop9874" />
<stop
style="stop-color:#555753;stop-opacity:1"
offset="1"
id="stop9860" />
</linearGradient>
<inkscape:path-effect
vertical="false"
scale_y_rel="false"
deactivate_knotholder="false"
bendpath-nodetypes="cc"
prop_scale="1"
is_visible="true"
bendpath="m 573.23098,118.10429 c 26.3574,9.12694 57.80555,27.44466 105.31044,26.93611"
id="path-effect15992"
effect="bend_path" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient9856"
id="linearGradient9862"
x1="108.5"
y1="83.5"
x2="108.5"
y2="72"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient10027"
id="linearGradient10033"
x1="33"
y1="59"
x2="33"
y2="72"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient10047"
id="radialGradient10055"
cx="33.1978"
cy="73.593964"
fx="33.1978"
fy="73.593964"
r="23.500003"
gradientTransform="matrix(0.8936168,-2.1708241e-7,-6.9085817e-8,0.2127659,3.3338919,55.341721)"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2"
inkscape:cx="-135"
inkscape:cy="35"
inkscape:document-units="px"
inkscape:current-layer="artwork"
showgrid="false"
inkscape:snap-nodes="false"
inkscape:snap-bbox="false"
inkscape:snap-global="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1680"
inkscape:window-height="1031"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:snap-intersection-line-segments="true"
inkscape:object-paths="true"
inkscape:object-nodes="true"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid13478"
visible="true"
enabled="true"
spacingx="0.5"
spacingy="0.5"
empspacing="2"
originx="0"
originy="0" />
</sodipodi:namedview>
<metadata
id="metadead">
<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>App-icon</dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
<dc:creator>
<cc:Agent>
<dc:title>Joel Holdsworth</dc:title>
</cc:Agent>
</dc:creator>
<dc:publisher>
<cc:Agent>
<dc:title>Lumiera.org</dc:title>
</cc:Agent>
</dc:publisher>
<dc:description>The Lumiera Application Logo
prepared for Lumiera build :: Icon rendering</dc:description>
<dc:date>2008</dc:date>
<dc:identifier>app-icon</dc:identifier>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="artwork"
inkscape:label="artwork:app-icon"
style="display:inline">
<g
inkscape:groupmode="layer"
id="layerp"
inkscape:label="plate#1"
style="display:none"
sodipodi:insensitive="true">
<rect
id="bbox48"
x="8"
y="44"
width="48"
height="48"
style="display:inline;fill:#000000;fill-opacity:0.5;fill-rule:evenodd;stroke:#5a8fb2;stroke-width:0.1;stroke-opacity:1"
sodipodi:insensitive="true" />
<rect
id="bbox24"
x="96"
y="68"
width="24"
height="24"
style="display:inline;fill:#000000;fill-opacity:0.5;fill-rule:evenodd;stroke:#5a8fb2;stroke-width:0.1;stroke-opacity:1"
sodipodi:insensitive="true" />
<rect
id="bbox22"
x="97"
y="69"
width="22"
height="22"
style="display:inline;fill:#000000;fill-opacity:0.5;fill-rule:evenodd;stroke:#5a8fb2;stroke-width:0.1;stroke-opacity:1"
sodipodi:insensitive="true" />
</g>
<g
id="template2">
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc"
id="path9886"
d="M -177.0341,282.31973 -14.7785,198.8 -184,164 -361.3696,197.09475 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
id="path9884"
d="m -180,139.28125 -180.9375,57.875 1.59375,0.6875 c 54.88591,20.17794 122.68471,57.57388 183.40625,39.90625 58.2053,14.10701 111.68205,-20.96691 161.15625,-38.9375 z"
style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.20000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
<path
inkscape:connector-curvature="0"
id="path9888"
d="m -181.2491,145.83343 c -0.965,0.0786 -1.9717,0.31532 -3.1432,0.6833 l -9.1107,2.82433 c -2.0682,0.64961 -3.4149,1.74482 -0.9111,2.6421 l 11.1151,3.96318 c 2.0341,0.77764 3.9099,0.48183 5.7397,-0.27333 l 10.4774,-3.46208 c 1.0849,-0.41512 2.9773,-1.24819 -0.6833,-2.551 l -9.0197,-3.18875 c -1.4225,-0.50629 -2.8559,-0.76877 -4.4642,-0.63775 z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc"
id="path9890"
d="m -160.8571,161.27218 c -1.9209,0.66806 -3.6791,1.67481 -1.1688,2.56282 l 11.1417,3.92183 c 2.0448,0.77048 3.7136,0.35456 5.3933,-0.41831 l 9.8183,-3.4512 c 0.9996,-0.42538 3.1536,-1.43568 -0.5155,-2.72484 l -9.0961,-3.30658 c -1.4172,-0.44406 -2.7765,-0.91081 -4.0115,-0.4236 z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc"
id="path9892"
d="m -118.1679,169.13807 -10.51,3.89794 c -2.2196,0.66377 -3.9387,1.48662 -1.639,2.23813 l 11.7321,4.24522 c 1.9603,0.74942 2.8245,0.53982 5.0408,-0.33889 l 10.1495,-3.90175 c 1.7627,-0.6265 2.9563,-1.24063 0.0324,-2.30746 l -11.1368,-3.95107 c -1.4558,-0.51292 -2.0738,-0.41463 -3.669,0.11788 z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccscccc"
id="path9894"
d="m -345.9071,198.90755 13.0873,5.2515 c 2.7143,1.00325 3.2613,1.08361 5.4886,0.48579 l 13.7018,-4.62408 c 1.6203,-0.4672 1.781,-1.60387 -1.0029,-2.54598 -0.2545,-0.0861 -11.259,-5.03108 -11.259,-5.03108 -2.2315,-0.46302 -2.806,-0.39117 -4.6734,0.28705 l -12.5033,3.89907 c -2.1334,0.63967 -4.2112,1.4435 -2.8391,2.27773 z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m -86.068599,180.67255 -10.3243,4.01218 c -2.1775,0.68322 -3.869501,1.53019 -1.6392,2.30371 l 11.6352,4.21113 c 1.8992,0.77138 2.746199,0.55564 4.924399,-0.34881 l 9.9725,-4.0161 c 1.7311,-0.64487 2.9066,-1.277 0.0728,-2.37509 l -11.0596,-3.90836 c -1.411099,-0.52796 -1.751699,-0.58528 -3.317699,-0.0371 l -0.2641,0.15852 z"
id="path9900"
sodipodi:nodetypes="cccccccccc" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc"
id="path9902"
d="m -62.3331,196.66044 c -2.1775,0.68322 -3.8695,1.53019 -1.6392,2.30371 l 11.6352,4.21113 c 1.8992,0.77138 2.7461,0.55564 4.9243,-0.34882 l 9.3687,-4.09158 c 1.731,-0.64487 2.9066,-1.27701 0.0728,-2.37509 l -11.0596,-3.90836 c -1.4111,-0.52796 -1.7517,-0.58528 -3.3177,-0.0371 l -9.9845,4.24615 z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m -311.4074,212.35795 10.9356,3.99399 c 2.7595,1.00324 3.2946,1.0836 5.314,0.48578 l 12.7036,-4.32818 c 1.4635,-0.4672 1.4207,-1.60386 -1.3946,-2.54597 -0.2574,-0.0861 -9.9691,-3.77358 -9.9691,-3.77358 -2.2062,-0.46302 -2.7413,-0.39117 -4.4039,0.28705 l -10.8727,3.60319 c -1.9227,0.63966 -3.7642,1.4435 -2.3129,2.27772 z"
id="path9904"
sodipodi:nodetypes="ccccscccc" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccsccccc"
id="path9906"
d="m -264.5135,229.20002 c 2.7594,0.77428 4.2254,0.59759 6.1287,-0.0135 l 14.2729,-3.47515 c 1.3794,-0.47654 0.8088,-1.37584 -1.8745,-2.20948 -3.2993,-1.02501 -7.4534,-2.60399 -10.5175,-3.65488 -2.0794,-0.89276 -3.9151,-1.16619 -5.4822,-0.47735 l -11.8539,3.50357 c -2.5519,0.72591 -3.6429,1.89022 -1.2711,2.71518 4.6152,1.53055 6.0417,2.00026 10.5976,3.61124 z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m -223.4892,237.29738 13.4445,-2.75022 c 1.3794,-0.47655 1.5022,-1.55546 -1.2531,-2.10594 l -9.4819,-1.89434 c -2.4937,-0.58207 -4.0187,-1.06263 -5.5858,-0.3738 l -13.2002,2.77866 c -2.5519,0.7259 -5.4034,1.47599 -3.0316,2.30094 l 11.7368,2.26495 c 2.62,0.88218 4.7955,0.12207 7.3713,-0.22025 z"
id="path9950"
sodipodi:nodetypes="ccscccccc" />
</g>
<g
id="template1">
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc"
id="path8852"
d="m -377.05043,-90.740359 180.9219,-57.871091 165.234299,59.527341 -149.906199,66.34374 -96,-24.5 z"
style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:#800000;stroke-width:0.20000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M -193.15013,-5.5642392 -30.894531,-89.083969 c -49.4742,17.97059 -102.939299,53.07027 -161.144599,38.96326 -61.4687,17.88502 -130.2105,-20.68294 -185.4465,-40.66851 z"
id="path16034"
sodipodi:nodetypes="ccccc" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m -197.36513,-142.05054 c -0.965,0.0786 -1.9717,0.31532 -3.1432,0.6833 l -9.1107,2.82433 c -2.0682,0.64961 -3.4149,1.74482 -0.9111,2.6421 l 11.1151,3.96318 c 2.0341,0.77764 3.9099,0.48183 5.7397,-0.27333 l 10.4774,-3.46208 c 1.0849,-0.41512 2.9773,-1.24819 -0.6833,-2.551 l -9.0197,-3.18875 c -1.4225,-0.50629 -2.8559,-0.76877 -4.4642,-0.63775 z"
id="path16036" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m -176.97313,-126.61179 c -1.9209,0.66806 -3.6791,1.67481 -1.1688,2.56282 l 11.1417,3.92183 c 2.0448,0.77048 3.7136,0.35456 5.3933,-0.41831 l 9.8183,-3.4512 c 0.9996,-0.42538 3.1536,-1.43568 -0.5155,-2.72484 l -9.0961,-3.30658 c -1.4172,-0.44406 -2.7765,-0.91081 -4.0115,-0.4236 z"
id="path16038"
sodipodi:nodetypes="ccccccccc" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m -134.28393,-118.7459 -10.51,3.89794 c -2.2196,0.66377 -3.9387,1.48662 -1.639,2.23813 l 11.7321,4.24522 c 1.9603,0.74942 2.8245,0.53982 5.0408,-0.33889 l 10.1495,-3.90175 c 1.7627,-0.6265 2.9563,-1.24063 0.0324,-2.30746 l -11.1368,-3.95107 c -1.4558,-0.51292 -2.0738,-0.41463 -3.669,0.11788 z"
id="path16040"
sodipodi:nodetypes="ccccccccc" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m -362.02313,-88.976419 13.0873,5.2515 c 2.7143,1.00325 3.2613,1.08361 5.4886,0.48579 l 13.7018,-4.62408 c 1.6203,-0.4672 1.781,-1.60387 -1.0029,-2.54598 -0.2545,-0.08612 -11.259,-5.03108 -11.259,-5.03108 -2.2315,-0.46302 -2.806,-0.39117 -4.6734,0.28705 l -12.5033,3.89907 c -2.1334,0.63967 -4.2112,1.4435 -2.8391,2.27773 z"
id="path16042"
sodipodi:nodetypes="ccccscccc" />
<path
inkscape:connector-curvature="0"
id="path16044"
d="m -183.21373,-47.939839 c 0,0 -48.1059,6.49531 -100.4742,-11.77273 -64.5136,-22.50476 -79.5675,-29.83778 -79.5675,-29.83778"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.20000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
sodipodi:nodetypes="csc" />
<path
inkscape:connector-curvature="0"
id="path16046"
d="m -345.59633,-97.060549 c 0,0 47.2939,21.92164 91.1372,35.11521 43.8433,13.19359 93.167,15.62933 93.167,15.62933"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.20000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
sodipodi:nodetypes="csc" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccc"
id="path16048"
d="m -102.18463,-107.21142 -10.3243,4.01218 c -2.1775,0.68322 -3.8695,1.53019 -1.6392,2.30371 l 11.6352,4.211131 c 1.8992,0.77138 2.746199,0.55564 4.924399,-0.34881 l 9.9725,-4.016101 c 1.7311,-0.64487 2.9066,-1.277 0.0728,-2.37509 l -11.0596,-3.90836 c -1.411099,-0.52796 -1.751699,-0.58528 -3.317699,-0.0371 l -0.2641,0.15852 z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m -78.449131,-91.223529 c -2.1775,0.68322 -3.8695,1.53019 -1.6392,2.30371 l 11.6352,4.21113 c 1.8992,0.77138 2.7461,0.55564 4.9243,-0.34882 l 9.3687,-4.09158 c 1.731,-0.64487 2.9066,-1.27701 0.0728,-2.37509 l -11.0596,-3.90836 c -1.4111,-0.52796 -1.7517,-0.58528 -3.3177,-0.03714 z"
id="path16050"
sodipodi:nodetypes="ccccccccc" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccscccc"
id="path16052"
d="m -327.52343,-75.526019 10.9356,3.99399 c 2.7595,1.00324 3.2946,1.0836 5.314,0.48578 l 12.7036,-4.32818 c 1.4635,-0.4672 1.4207,-1.60386 -1.3946,-2.54597 -0.2574,-0.08613 -9.9691,-3.77358 -9.9691,-3.77358 -2.2062,-0.46302 -2.7413,-0.39117 -4.4039,0.28705 l -10.8727,3.60319 c -1.9227,0.63966 -3.7642,1.4435 -2.3129,2.27772 z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m -280.62953,-58.683949 c 2.7594,0.77428 4.2254,0.59759 6.1287,-0.01348 l 14.2729,-3.47515 c 1.3794,-0.47654 0.8088,-1.37584 -1.8745,-2.20948 -3.2993,-1.02501 -7.4534,-2.60399 -10.5175,-3.65488 -2.0794,-0.89276 -3.9151,-1.16619 -5.4822,-0.47735 l -11.8539,3.50357 c -2.5519,0.72591 -3.6429,1.89022 -1.2711,2.71518 4.6152,1.53055 6.0417,2.00026 10.5976,3.61124 z"
id="path16054"
sodipodi:nodetypes="cccsccccc" />
<path
inkscape:connector-curvature="0"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.20000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="m -36.541731,-79.685619 c 0,0 -15.9135,5.96755 -68.768999,23.58606 -52.8555,17.61851 -86.6717,5.68339 -86.6717,5.68339"
id="path16056" />
<g
id="g16058"
transform="matrix(1.4977647,0,0,1.4977647,-1232.0425,-263.18298)"
inkscape:path-effect="#path-effect15992">
<path
inkscape:connector-curvature="0"
id="path16060"
d="m 573.04054,118.33954 c 15.0983,5.2199 29.61826,12.08333 44.82595,17.1163 19.51078,6.45667 40.01704,10.07666 60.57469,9.8702"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.13353233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
inkscape:original-d="M 580.38105,116.25308 H 686.6293" />
<path
inkscape:connector-curvature="0"
id="path16062"
d="m 573.84672,116.61089 -1.05666,3.04738"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.13353233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
inkscape:original-d="m 580.57076,114.35579 v 3.2254" />
<path
inkscape:connector-curvature="0"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.13353233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="m 584.84276,120.69281 -1.17428,3.00425"
id="path16064"
inkscape:original-d="m 591.88662,114.35579 v 3.2254" />
<path
inkscape:connector-curvature="0"
id="path16066"
d="m 596.37505,125.30977 -1.20849,2.9915"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.13353233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
inkscape:original-d="m 603.91289,114.35579 v 3.2254" />
<path
inkscape:connector-curvature="0"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.13353233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="m 606.83802,129.46311 -1.15833,3.00952"
id="path16068"
inkscape:original-d="m 614.85501,114.35579 v 3.2254" />
<path
inkscape:connector-curvature="0"
id="path16070"
d="m 618.03182,133.51163 -1.02027,3.05957"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.13353233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
inkscape:original-d="m 626.47471,114.35579 v 3.2254" />
<path
inkscape:connector-curvature="0"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.13353233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="m 628.77838,136.77115 -0.85141,3.11242"
id="path16072"
inkscape:original-d="m 637.44964,114.35579 v 3.2254" />
<path
inkscape:connector-curvature="0"
id="path16074"
d="m 640.87492,139.67562 -0.65247,3.15905"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.13353233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
inkscape:original-d="m 649.61143,114.35579 v 3.2254" />
<path
inkscape:connector-curvature="0"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.13353233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="m 652.16269,141.65255 -0.4576,3.19112"
id="path16076"
inkscape:original-d="m 660.82458,114.35579 v 3.2254" />
<path
inkscape:connector-curvature="0"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.13353233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="m 676.3206,143.43703 -0.009,3.22451"
id="path16078"
inkscape:original-d="m 684.57101,114.35579 v 3.2254" />
<path
inkscape:connector-curvature="0"
id="path16080"
d="m 665.16103,143.03581 -0.22166,3.21495"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.13353233;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
inkscape:original-d="m 673.6289,114.35579 v 3.2254" />
</g>
<path
inkscape:connector-curvature="0"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.20000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="m -150.48563,-135.24479 -197.5221,64.879941"
id="path16086"
sodipodi:nodetypes="cc" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc"
id="path16088"
d="m -135.46523,-129.5614 -195.6953,65.082911"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.20000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
<path
inkscape:connector-curvature="0"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.20000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="m -119.44063,-124.34166 c -62.0689,23.33953 -123.4964,46.977261 -193.7467,65.854231"
id="path16090"
sodipodi:nodetypes="cc" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc"
id="path16092"
d="m -103.13853,-119.273 c -63.8144,25.758961 -125.2507,51.878831 -193.4626,65.570061"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.20000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
<path
inkscape:connector-curvature="0"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.20000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="m -49.998831,-91.140229 c -57.017299,26.73494 -99.268199,42.22648 -169.592399,46.24654"
id="path16094"
sodipodi:nodetypes="cc" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc"
id="path16096"
d="m -66.029831,-96.255279 c -52.087899,22.00844 -117.826199,43.47334 -169.882299,50.16112"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.20000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
<path
inkscape:connector-curvature="0"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.20000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="m -99.967831,-108.35277 c -60.206899,24.850141 -118.637999,47.532901 -173.332899,57.062371"
id="path16098"
sodipodi:nodetypes="cc" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc"
id="path16100"
d="m -83.729531,-102.4664 c -60.206999,24.850131 -117.395299,47.636451 -176.232599,55.094721"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.20000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccscccccc"
id="path16102"
d="m -239.60523,-50.586589 13.4445,-2.75022 c 1.3794,-0.47655 1.5022,-1.55546 -1.2531,-2.10594 l -9.4819,-1.89434 c -2.4937,-0.58207 -4.0187,-1.06263 -5.5858,-0.3738 l -13.2002,2.77866 c -2.5519,0.7259 -5.4034,1.47599 -3.0316,2.30094 l 11.7368,2.26495 c 2.62,0.88218 4.7955,0.12207 7.3713,-0.22025 z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc"
id="path8786"
d="m -176.52363,-143.39639 -197.7251,63.256091"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.20000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
<g
transform="translate(1669.1863,-717.32088)"
id="g8792">
<path
inkscape:connector-curvature="0"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.20000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="m -1859.2363,566.76341 -197.7251,63.2561"
id="path8794"
sodipodi:nodetypes="cc" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc"
id="path8796"
d="m -1845.7099,573.92448 -197.725,63.2561"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.20000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
</g>
<g
transform="translate(1675.9495,-713.74034)"
id="g8818">
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc"
id="path8800"
d="m -1897.9293,561.76866 175.5749,63.2561"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.18846485;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc"
id="path8816"
d="m -1909.2333,569.63684 175.5748,63.2561"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.18846485;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
</g>
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc"
id="path8802"
d="m -227.63173,-148.03759 175.574799,63.256101"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.18846485;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc"
id="path8832"
d="M -216.30593,-155.88397 -0.11603083,-77.995089"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.23206167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc"
id="path8834"
d="m -227.63173,-148.03759 175.574799,63.256101"
style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#009fda;stroke-width:0.18846485;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" />
</g>
<g
id="glogo48">
<path
inkscape:connector-curvature="0"
style="fill:url(#radialGradient10055);fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 33.497089,77.698474 55.500003,66.372655 32.552468,61.653549 8.499997,66.141412 Z"
id="path9975"
sodipodi:nodetypes="ccccc" />
<path
inkscape:connector-curvature="0"
style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient10033);fill-opacity:1;fill-rule:nonzero;stroke:#555753;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0.60000002;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
d="m 33.094894,58.301526 -24.5363014,7.848226 0.2161228,0.09323 c 7.4428866,2.736259 16.6368446,7.807392 24.8710796,5.411547 7.893017,1.913002 15.144812,-2.84325 21.853835,-5.280179 z"
id="path9977" />
<path
inkscape:connector-curvature="0"
style="fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m 32.841904,59.994654 c -0.12184,0.0099 -0.248945,0.03981 -0.396857,0.08627 l -1.150306,0.356597 c -0.261128,0.08202 -0.431161,0.220299 -0.115034,0.333588 l 1.403379,0.500387 c 0.256823,0.09818 0.49366,0.06084 0.724687,-0.03451 l 1.322864,-0.437118 c 0.136978,-0.05241 0.37591,-0.157595 -0.08627,-0.322087 L 33.40555,60.075174 c -0.179603,-0.06392 -0.360582,-0.09706 -0.563644,-0.08052 z"
id="path9979" />
<path
inkscape:connector-curvature="0"
style="fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m 35.416573,61.943932 c -0.24253,0.08435 -0.464519,0.21146 -0.147572,0.323579 l 1.406738,0.495166 c 0.258174,0.09728 0.468875,0.04477 0.680952,-0.05282 l 1.239646,-0.435744 c 0.126208,-0.05371 0.39817,-0.181268 -0.06509,-0.344035 L 37.382788,61.512597 C 37.203854,61.456531 37.03223,61.3976 36.876301,61.459113 Z"
id="path9981"
sodipodi:nodetypes="ccccccccc" />
<path
inkscape:connector-curvature="0"
style="fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m 40.806459,62.93707 -1.32698,0.492149 c -0.280243,0.08381 -0.497295,0.187699 -0.206938,0.282584 l 1.481281,0.535996 c 0.247505,0.09462 0.356618,0.06816 0.636445,-0.04279 l 1.281463,-0.492631 c 0.222557,-0.0791 0.37326,-0.156641 0.0041,-0.291337 l -1.406118,-0.498857 c -0.183808,-0.06476 -0.261836,-0.05235 -0.463244,0.01488 z"
id="path9983"
sodipodi:nodetypes="ccccccccc" />
<path
inkscape:connector-curvature="0"
style="fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m 13.324644,66.394404 1.652385,0.663048 c 0.342705,0.12667 0.411768,0.136815 0.692984,0.06134 l 1.729973,-0.583832 c 0.204577,-0.05899 0.224867,-0.202502 -0.126625,-0.321452 -0.03213,-0.01087 -1.421548,-0.635217 -1.421548,-0.635217 -0.281746,-0.05846 -0.354282,-0.04939 -0.590057,0.03624 l -1.578652,0.492292 c -0.26936,0.08076 -0.5317,0.182254 -0.35846,0.287583 z"
id="path9985"
sodipodi:nodetypes="ccccscccc" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccc"
id="path9987"
d="m 44.859277,64.393399 -1.303533,0.506573 c -0.274928,0.08626 -0.488558,0.1932 -0.206963,0.290864 l 1.469045,0.531692 c 0.239791,0.09739 0.346733,0.07015 0.621749,-0.04404 l 1.259116,-0.507069 c 0.218566,-0.08142 0.366984,-0.161232 0.0092,-0.299875 l -1.396372,-0.493465 c -0.178164,-0.06666 -0.221167,-0.0739 -0.418888,-0.0047 l -0.03335,0.02002 z"
style="fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
style="fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m 47.856093,66.412011 c -0.274929,0.08626 -0.488558,0.1932 -0.206964,0.290863 l 1.469047,0.531693 c 0.239791,0.09739 0.346719,0.07015 0.621736,-0.04404 l 1.18288,-0.516598 c 0.218554,-0.08142 0.366984,-0.161233 0.0092,-0.299876 L 49.53562,65.880588 c -0.178163,-0.06666 -0.221167,-0.0739 -0.418889,-0.0047 l -1.26063,0.536114 z"
id="path9989"
sodipodi:nodetypes="ccccccccc" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccscccc"
id="path9991"
d="m 17.680533,68.092636 1.380716,0.504276 c 0.348411,0.126667 0.415972,0.136814 0.670938,0.06133 l 1.603942,-0.54647 c 0.184779,-0.05899 0.179375,-0.202502 -0.176081,-0.321451 -0.0325,-0.01087 -1.258686,-0.476448 -1.258686,-0.476448 -0.278552,-0.05846 -0.346113,-0.04939 -0.556031,0.03624 l -1.372774,0.454934 c -0.242758,0.08076 -0.475264,0.182255 -0.292024,0.287583 z"
style="fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
style="fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m 23.6013,70.219095 c 0.348398,0.09776 0.533493,0.07545 0.773801,-0.0017 l 1.802079,-0.438769 c 0.174162,-0.06017 0.102119,-0.173712 -0.236671,-0.278966 -0.416566,-0.129416 -0.941058,-0.328777 -1.327927,-0.461461 -0.262543,-0.112719 -0.494315,-0.147241 -0.692176,-0.06027 l -1.496659,0.442357 c -0.3222,0.09165 -0.459948,0.238656 -0.160488,0.342815 0.58271,0.193245 0.762818,0.25255 1.338041,0.45595 z"
id="path9993"
sodipodi:nodetypes="cccsccccc" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccscccccc"
id="path9995"
d="m 28.780977,71.241457 1.697487,-0.347239 c 0.174161,-0.06017 0.189665,-0.196391 -0.158215,-0.265894 l -1.197174,-0.239176 c -0.314851,-0.07349 -0.507396,-0.134167 -0.705256,-0.0472 l -1.66664,0.35083 c -0.322201,0.09165 -0.682228,0.186357 -0.382767,0.290514 l 1.481874,0.28597 c 0.330798,0.111383 0.605474,0.01541 0.930691,-0.02781 z"
style="fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
d="m 33.076172,59.347656 -21.554688,6.892578 c 7.046794,2.792288 14.935616,6.489725 21.861328,4.47461 a 0.98051356,0.98051356 0 0 1 0.503907,-0.01172 c 6.545128,1.586321 12.755913,-1.743725 18.871093,-4.273437 z"
id="path10025"
style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#eeeeec;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0.60000002;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.75294118;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
inkscape:original="M 33.09375 58.3125 L 8.5625 66.15625 L 8.78125 66.25 C 16.224137 68.98626 25.422015 74.052095 33.65625 71.65625 C 41.549268 73.569255 48.790977 68.811929 55.5 66.375 L 33.09375 58.3125 z "
inkscape:radius="-0.98041552"
sodipodi:type="inkscape:offset" />
</g>
<g
id="glogo24">
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc"
id="path8856"
d="M 108.82643,86.48326 118.49998,78.669124 108.5,75.399647 97.500002,78.478613 Z"
style="fill:#888a85;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-linejoin:round" />
<path
inkscape:connector-curvature="0"
id="path8854"
d="m 108.5,72 -10.9375,6.511188 c 3.33624,2.244016 7.48577,6.480415 11.1875,4.494449 3.52666,1.576044 6.75236,-2.313901 9.75,-4.321585 z"
style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient9862);fill-opacity:1;fill-rule:nonzero;stroke:#2e3436;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
<path
inkscape:connector-curvature="0"
id="path8858"
d="m 108.41352,72.751665 c -0.0585,0.0088 -0.11947,0.03523 -0.19045,0.07634 l -0.55202,0.315536 c -0.12531,0.07258 -0.20691,0.194932 -0.0552,0.295177 l 0.67346,0.442768 c 0.12325,0.08688 0.2369,0.05383 0.34777,-0.03054 l 0.63483,-0.386784 c 0.0657,-0.04638 0.18039,-0.139449 -0.0414,-0.285001 L 108.684,72.822916 c -0.0862,-0.05656 -0.17304,-0.08589 -0.27048,-0.07125 z"
style="fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc"
id="path8860"
d="m 109.64907,74.476494 c -0.11639,0.07463 -0.22292,0.187109 -0.0708,0.286319 l 0.67508,0.438149 c 0.12389,0.08608 0.22501,0.03961 0.32678,-0.04673 l 0.59489,-0.385571 c 0.0606,-0.04752 0.19108,-0.160395 -0.0312,-0.304421 l -0.55114,-0.369413 c -0.0859,-0.04961 -0.16823,-0.101756 -0.24305,-0.04733 l -0.70051,0.428995 z"
style="fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc"
id="path8862"
d="m 112.23561,75.355274 -0.6368,0.435481 c -0.13449,0.07416 -0.23865,0.166086 -0.0993,0.250045 l 0.71085,0.47428 c 0.11878,0.08373 0.17114,0.06031 0.30542,-0.03786 l 0.61496,-0.435906 c 0.10681,-0.06999 0.17913,-0.138604 0.002,-0.25779 l -0.67478,-0.441417 c -0.0882,-0.0573 -0.12565,-0.04632 -0.22231,0.01317 z"
style="fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccscccc"
id="path8864"
d="m 98.436876,78.68114 0.79296,0.5867 c 0.16446,0.112083 0.197603,0.121061 0.332555,0.05427 l 0.830189,-0.516604 c 0.0982,-0.0522 0.10792,-0.179186 -0.0608,-0.284438 -0.0154,-0.0096 -0.682185,-0.562076 -0.682185,-0.562076 -0.135207,-0.05173 -0.170016,-0.0437 -0.283162,0.03207 l -0.757576,0.435607 c -0.129263,0.07146 -0.255157,0.161267 -0.172021,0.254469 z"
style="fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
style="fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m 114.18051,76.643913 -0.62555,0.448245 c -0.13193,0.07633 -0.23445,0.170953 -0.0993,0.257372 l 0.70498,0.470468 c 0.11507,0.08618 0.16639,0.06208 0.29837,-0.03897 l 0.60423,-0.448682 c 0.10489,-0.07205 0.17611,-0.142666 0.004,-0.265346 l -0.6701,-0.436645 c -0.0855,-0.05898 -0.10613,-0.06539 -0.20102,-0.0041 l -0.016,0.01771 z"
id="path8870"
sodipodi:nodetypes="cccccccccc" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc"
id="path8872"
d="m 115.61865,78.430091 c -0.13194,0.07633 -0.23446,0.170953 -0.0993,0.257372 l 0.70498,0.470471 c 0.11507,0.08618 0.16638,0.06208 0.29836,-0.03897 l 0.56765,-0.457115 c 0.10488,-0.07204 0.17611,-0.142668 0.004,-0.265345 l -0.6701,-0.436645 c -0.0855,-0.05898 -0.10614,-0.06539 -0.20102,-0.0041 l -0.60496,0.474383 z"
style="fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
style="fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m 100.52722,80.183826 0.66258,0.446212 c 0.1672,0.112082 0.19962,0.12106 0.32198,0.05427 l 0.76971,-0.483547 c 0.0887,-0.05219 0.0861,-0.179184 -0.0845,-0.284437 -0.0156,-0.0096 -0.60403,-0.421587 -0.60403,-0.421587 -0.13367,-0.05173 -0.16609,-0.0437 -0.26683,0.03207 l -0.65878,0.40255 c -0.11649,0.07146 -0.22807,0.161269 -0.14013,0.254469 z"
id="path8874"
sodipodi:nodetypes="ccccscccc" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccsccccc"
id="path8876"
d="m 103.36852,82.065434 c 0.16719,0.0865 0.25602,0.06676 0.37134,-0.0015 l 0.8648,-0.388247 c 0.0836,-0.05324 0.049,-0.153709 -0.11358,-0.246843 -0.19991,-0.114516 -0.4516,-0.290919 -0.63726,-0.408326 -0.12599,-0.09974 -0.23721,-0.130287 -0.33216,-0.05333 l -0.71823,0.39142 c -0.15462,0.0811 -0.22073,0.211177 -0.077,0.303342 0.27964,0.170993 0.36607,0.22347 0.64211,0.403449 z"
style="fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
style="fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m 105.85419,82.970074 0.8146,-0.307256 c 0.0836,-0.05324 0.091,-0.173776 -0.0759,-0.235277 l -0.57451,-0.211636 c -0.15109,-0.06503 -0.24349,-0.118718 -0.33844,-0.04176 l -0.7998,0.310435 c -0.15462,0.0811 -0.32739,0.164898 -0.18369,0.257062 l 0.71114,0.253041 c 0.15874,0.09856 0.29056,0.01364 0.44663,-0.02461 z"
id="path8920"
sodipodi:nodetypes="ccscccccc" />
<path
d="m 108.4668,73.216797 -9.013675,5.355469 c 1.354365,1.001113 2.725395,2.099213 4.076175,2.86914 1.78688,1.018504 3.29382,1.423241 4.73437,0.650391 a 1.0296619,1.0296619 0 0 1 0.90625,-0.03125 c 1.36919,0.61188 2.60683,0.200924 4.10352,-0.744141 1.10843,-0.699909 2.27835,-1.678897 3.44726,-2.580078 z"
id="path9880"
style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#eeeeec;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.31451613;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
inkscape:original="M 108.5 72 L 97.5625 78.5 C 100.89874 80.744019 105.04827 84.985966 108.75 83 C 112.27666 84.576043 115.50236 80.695184 118.5 78.6875 L 108.5 72 z "
inkscape:radius="-1.0295589"
sodipodi:type="inkscape:offset" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 46 KiB

View file

@ -0,0 +1,320 @@
<?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="150"
height="100"
id="icon"
sodipodi:version="0.32"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
version="1.0"
sodipodi:docname="arrow-hand-down.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<title
id="doctitle">Icon: arrow-hand-down</title>
<defs
id="defsz">
<linearGradient
inkscape:collect="always"
id="Gloss">
<stop
style="stop-color:#ffffff;stop-opacity:0.39215687"
offset="0"
id="stop3328" />
<stop
style="stop-color:#e6e6e6;stop-opacity:0.19607843"
offset="1"
id="stop3330" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#Gloss"
id="linearGradient3334"
x1="128.72638"
y1="83.184044"
x2="132.27362"
y2="86.36319"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0,1,1,0,48,-48)" />
<linearGradient
inkscape:collect="always"
xlink:href="#Gloss"
id="linearGradient885"
gradientUnits="userSpaceOnUse"
x1="128.4325"
y1="82.56572"
x2="132.28908"
y2="86.347733"
gradientTransform="matrix(0,1.5,1.5008815,0,-18.07405,-118.5)" />
<filter
inkscape:collect="always"
style="color-interpolation-filters:sRGB"
id="filter1637"
x="-0.12728689"
width="1.2545738"
y="-0.061356014"
height="1.122712">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.38347509"
id="feGaussianBlur1639" />
</filter>
<filter
inkscape:collect="always"
style="color-interpolation-filters:sRGB"
id="filter3647"
x="-0.15054306"
width="1.3010861"
y="-0.067912159"
height="1.1358243">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.67783205"
id="feGaussianBlur3649" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="15"
inkscape:cx="113"
inkscape:cy="32"
inkscape:document-units="px"
inkscape:current-layer="aardvark"
showgrid="false"
inkscape:snap-nodes="true"
inkscape:snap-bbox="true"
inkscape:snap-global="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1680"
inkscape:window-height="1050"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="pixelgrid"
visible="true"
enabled="true"
spacingx="0.5"
spacingy="0.5"
empspacing="2"
originx="0"
originy="0" />
</sodipodi:namedview>
<metadata
id="metadead">
<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>Icon: arrow-hand-down</dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
<dc:creator>
<cc:Agent>
<dc:title>Ichthyostega</dc:title>
</cc:Agent>
</dc:creator>
<dc:publisher>
<cc:Agent>
<dc:title>Lumiera.org</dc:title>
</cc:Agent>
</dc:publisher>
<dc:description>Triangle hand used to indicate expander-expand
prepared for Lumiera build :: Icon rendering</dc:description>
<dc:date>2022</dc:date>
<dc:identifier>icon:arrow-hand-down</dc:identifier>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
inkscape:label="artwork:arrow-hand-down"
id="aardvark"
style="display:inline">
<g
inkscape:groupmode="layer"
id="layerp"
inkscape:label="plate#1"
style="display:none"
sodipodi:insensitive="true">
<rect
id="bbox24"
x="96"
y="68"
width="24"
height="24"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox16"
x="124"
y="76"
width="16"
height="16"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
</g>
<g
id="ghand24">
<g
id="bevel24">
<path
id="path861"
style="fill:black;fill-opacity:0.31372549;stroke:none;stroke-width:0.05"
d="m 108,91.5 v -3 l 7.5,-18 3,-1.5 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
id="path863"
style="fill:#ffffff;fill-opacity:0.74509804;stroke:none;stroke-width:0.05"
d="m 118.5,69 h -21 l 3,1.5 h 15 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
id="path865"
style="fill:#f2f2f2;fill-opacity:0.66666667;stroke:none;stroke-width:0.05"
d="m 108,91.5 v -3 l -7.5,-18 -3,-1.5 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
</g>
<g
id="counter24">
<path
id="path869"
style="fill:#c8c8c8;fill-opacity:0.62745098;stroke:none;stroke-width:0.05"
d="m 101,71 7,17 v 0.5 l -7.5,-18 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
id="path871"
style="fill:#646464;fill-opacity:0.19607843;stroke:none;stroke-width:0.05"
d="m 101,71 h 14 l 0.5,-0.5 h -15 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
id="path873"
style="fill:#ffffff;fill-opacity:0.70588235;stroke:none;stroke-width:0.05"
d="m 115.5,70.5 -7.5,18 V 88 l 7,-17 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
</g>
<path
id="gloss32"
style="fill:url(#linearGradient885);fill-opacity:1;stroke:none;stroke-width:0.05000001"
d="m 100.5,70.5 7.5,18 7.5,-18 z"
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0" />
<path
id="contour24"
style="fill:none;fill-opacity:0.75;stroke:black;stroke-opacity:1;stroke-width:0.07;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
d="M 107.77955,91.15899 97.41175,68.95312 h 20.81301"
sodipodi:nodetypes="ccc"
inkscape:connector-curvature="0" />
<path
id="shadow24"
style="fill:#43434b;fill-opacity:0.2745098;stroke:none;stroke-width:0.30000001;filter:url(#filter3647)"
d="m 107.94897,91.678614 0.28068,-2.306195 8.18945,-17.141703 2.33606,-4.50653 -0.95271,4.189705 L 109.5,90.055899 Z"
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0" />
</g>
<g
id="ghand16">
<g
id="bevel16">
<path
id="path3266"
style="fill:black;fill-opacity:0.31372549;stroke:none;stroke-width:0.05"
d="m 132,92 v -2 l 5,-12 2,-1 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
id="path3268"
style="fill:#f2f2f2;fill-opacity:0.66666667;stroke:none;stroke-width:0.05"
d="m 139,77 h -14 l 2,1 h 10 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
id="path3273"
style="fill:#ffffff;fill-opacity:0.74509804;stroke:none;stroke-width:0.05"
d="m 132,92 v -2 l -5,-12 -2,-1 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
</g>
<g
id="counter16">
<path
id="path3298"
style="fill:#ffffff;fill-opacity:0.70588235;stroke:none;stroke-width:0.05"
d="m 137,78 -5,12 v -0.5 l 4.5,-11 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
id="path3291"
style="fill:#646464;fill-opacity:0.19607843;stroke:none;stroke-width:0.05"
d="m 127.5,78.5 h 9 L 137,78 h -10 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
id="path3275"
style="fill:#323232;fill-opacity:0.19607843;stroke:none;stroke-width:0.05"
d="m 127.5,78.5 4.5,11 V 90 l -5,-12 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
</g>
<path
id="gloss16"
style="fill:url(#linearGradient3334);fill-opacity:1;stroke:none;stroke-width:0.05"
d="m 127,78 5,12 5,-12 z"
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0" />
<path
id="contour16"
style="fill:none;fill-opacity:0.75;stroke:black;stroke-opacity:1;stroke-width:0.05;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
d="M 131.84766,91.76172 124.94531,76.96875 H 138.8125"
sodipodi:nodetypes="ccc"
inkscape:connector-curvature="0" />
<path
id="shadow16"
style="fill:#43434b;fill-opacity:0.52747258;stroke:none;stroke-width:0.30000001;filter:url(#filter1637)"
d="m 131.96194,92.247377 0.37264,-1.712166 5.02939,-10.607146 1.59797,-3.460877 -0.45851,2.26652 -5.19372,11.92377 z"
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -0,0 +1,357 @@
<?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="150"
height="100"
id="icon"
sodipodi:version="0.32"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
version="1.0"
sodipodi:docname="arrow-hand-up.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<title
id="doctitle">Icon: arrow-hand-up</title>
<defs
id="defsz">
<linearGradient
inkscape:collect="always"
id="Gloss">
<stop
style="stop-color:#ffffff;stop-opacity:0.39215687"
offset="0"
id="stop3328" />
<stop
style="stop-color:#e6e6e6;stop-opacity:0.19607843"
offset="1"
id="stop3330" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#Gloss"
id="linearGradient3334"
x1="131.65076"
y1="82.34111"
x2="128.30205"
y2="85.035446"
gradientUnits="userSpaceOnUse"
gradientTransform="rotate(-90,132,84)" />
<filter
inkscape:collect="always"
style="color-interpolation-filters:sRGB"
id="filter9142"
x="-0.044394028"
width="1.0887881"
y="-0.50396832"
height="2.0079366">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.26626095"
id="feGaussianBlur9144" />
</filter>
<filter
inkscape:collect="always"
style="color-interpolation-filters:sRGB"
id="filter1057"
x="-0.13383683"
width="1.2676737"
y="-0.065107281"
height="1.1302146">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.40572579"
id="feGaussianBlur1059" />
</filter>
<linearGradient
inkscape:collect="always"
xlink:href="#Gloss"
id="linearGradient885"
gradientUnits="userSpaceOnUse"
x1="132.14272"
y1="82.502457"
x2="128.49089"
y2="84.880989"
gradientTransform="matrix(0,-1.5,1.5008815,0,-18.074046,278.5)" />
<filter
inkscape:collect="always"
style="color-interpolation-filters:sRGB"
id="filter1100"
x="-0.15399804"
width="1.3079961"
y="-0.074919384"
height="1.1498388">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.70175557"
id="feGaussianBlur1102" />
</filter>
<filter
inkscape:collect="always"
style="color-interpolation-filters:sRGB"
id="filter1092"
x="-0.050922564"
width="1.1018451"
y="-0.57808105"
height="2.1561621">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.45812538"
id="feGaussianBlur1094" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="15"
inkscape:cx="113"
inkscape:cy="32"
inkscape:document-units="px"
inkscape:current-layer="aardvark"
showgrid="false"
inkscape:snap-nodes="true"
inkscape:snap-bbox="true"
inkscape:snap-global="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1680"
inkscape:window-height="1050"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="pixelgrid"
visible="true"
enabled="true"
spacingx="0.5"
spacingy="0.5"
empspacing="2"
originx="0"
originy="0" />
</sodipodi:namedview>
<metadata
id="metadead">
<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>Icon: arrow-hand-up</dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
<dc:creator>
<cc:Agent>
<dc:title>Ichthyostega</dc:title>
</cc:Agent>
</dc:creator>
<dc:publisher>
<cc:Agent>
<dc:title>Lumiera.org</dc:title>
</cc:Agent>
</dc:publisher>
<dc:description>Triangle hand used to indicate expander-collapse
prepared for Lumiera build :: Icon rendering</dc:description>
<dc:date>2022</dc:date>
<dc:identifier>icon:arrow-hand-up</dc:identifier>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
inkscape:label="artwork:arrow-hand-up"
id="aardvark"
style="display:inline">
<g
inkscape:groupmode="layer"
id="layerp"
inkscape:label="plate#1"
style="display:none"
sodipodi:insensitive="true">
<rect
id="bbox24"
x="96"
y="68"
width="24"
height="24"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox16"
x="124"
y="76"
width="16"
height="16"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
</g>
<g
id="ghand24">
<g
id="bevel24">
<path
id="path861"
style="fill:#333333;fill-opacity:0.19607843;stroke:none;stroke-width:0.05"
d="m 108,68.5 v 3 l 7.5,18 3,1.5 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
id="path863"
style="fill:black;fill-opacity:0.31372549;stroke:none;stroke-width:0.05"
d="m 118.5,91 h -21 l 3,-1.5 h 15 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
id="path865"
style="fill:#ffffff;fill-opacity:0.74509804;stroke:none;stroke-width:0.05"
d="m 108,68.5 v 3 l -7.5,18 -3,1.5 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
</g>
<g
id="counter24">
<path
id="path869"
style="fill:#646464;fill-opacity:0.19607843;stroke:none;stroke-width:0.05"
d="m 101,89 7,-17 v -0.5 l -7.5,18 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
id="path871"
style="fill:#ffffff;fill-opacity:0.70588235;stroke:none;stroke-width:0.05"
d="m 101,89 h 14 l 0.5,0.5 h -15 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
id="path873"
style="fill:#c8c8c8;fill-opacity:0.62745098;stroke:none;stroke-width:0.05"
d="M 115.5,89.5 108,71.5 V 72 l 7,17 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
</g>
<path
id="gloss32"
style="fill:url(#linearGradient885);fill-opacity:1;stroke:none;stroke-width:0.05000001"
d="m 100.5,89.5 7.5,-18 7.5,18 z"
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0" />
<path
id="contour24"
style="fill:none;fill-opacity:0.75;stroke:black;stroke-opacity:1;stroke-width:0.07;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
d="M 107.77955,68.84101 97.612097,90.604938"
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0" />
<path
id="shadow24"
style="fill:#43434b;fill-opacity:0.5098038;stroke:none;stroke-width:0.30000001;filter:url(#filter1092)"
d="m 96.608302,90.915632 3.456138,-0.456159 15.87711,-0.0928 2.83406,0.599194 -1.81291,0.529399 -15.22842,0.28274 z"
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0" />
<path
id="shadow224"
style="fill:#43434b;fill-opacity:0.2745098;stroke:none;stroke-width:0.30000001;filter:url(#filter1100)"
d="m 118.25359,90.803458 -1.33376,-0.889204 -8.44895,-19.384274 -0.46208,-1.924912 1.74976,2.956872 9.18683,19.52347 z"
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0" />
</g>
<g
id="ghand16">
<g
id="bevel16">
<path
id="path3266"
style="fill:black;fill-opacity:0.31372549;stroke:none;stroke-width:0.05"
d="m 139,91 h -14 l 2,-1 h 10 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
id="path3268"
style="fill:#ffffff;fill-opacity:0.74509804;stroke:none;stroke-width:0.05"
d="m 132,76 v 2 l -5,12 -2,1 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
id="path3273"
style="fill:#333333;fill-opacity:0.19607843;stroke:none;stroke-width:0.05"
d="m 132,76 v 2 l 5,12 2,1 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
</g>
<g
id="counter16">
<path
id="path3298"
style="fill:#646464;fill-opacity:0.19607843;stroke:none;stroke-width:0.05"
d="m 127.5,89.5 4.5,-11 V 78 l -5,12 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
id="path3291"
style="fill:#c8c8c8;fill-opacity:0.62745098;stroke:none;stroke-width:0.05"
d="m 137,90 -5,-12 v 0.5 l 4.5,11 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
id="path3275"
style="fill:#ffffff;fill-opacity:0.70588235;stroke:none;stroke-width:0.05"
d="m 127,90 0.5,-0.5 h 9 L 137,90 Z"
inkscape:connector-curvature="0" />
</g>
<path
id="gloss16"
style="fill:url(#linearGradient3334);fill-opacity:1;stroke:none;stroke-width:0.05"
d="m 127,90 5,-12 5,12 z"
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0" />
<path
id="contour16"
style="fill:none;fill-opacity:0.75;stroke:black;stroke-opacity:1;stroke-width:0.05;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
d="m 131.84766,76.23828 -6.71485,14.398439"
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0" />
<path
id="shadow16"
style="fill:#43434b;fill-opacity:0.52747258;stroke:none;stroke-width:0.30000001;filter:url(#filter9142)"
d="m 124.79333,90.91345 1.97262,-0.200203 10.72807,-0.147758 1.61771,0.468244 -1.45594,0.436929 -10.19203,-0.05528 z"
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0" />
<path
id="shadow216"
style="fill:#43434b;fill-opacity:0.2745098;stroke:none;stroke-width:0.30000001;filter:url(#filter1057)"
d="M 138.81439,90.767992 137.92522,90.175189 132.29259,77.25234 132,76 l 1.15104,1.940313 6.12455,13.015647 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -0,0 +1,318 @@
<?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="150"
height="100"
id="icon"
sodipodi:version="0.32"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
version="1.0"
sodipodi:docname="arrow-hand.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<title
id="doctitle">Icon: arrow-hand</title>
<defs
id="defsz">
<linearGradient
inkscape:collect="always"
id="Gloss">
<stop
style="stop-color:#ffffff;stop-opacity:0.39215687"
offset="0"
id="stop3328" />
<stop
style="stop-color:#e6e6e6;stop-opacity:0.19607843"
offset="1"
id="stop3330" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#Gloss"
id="linearGradient3334"
x1="128.72638"
y1="83.184044"
x2="132.27362"
y2="86.36319"
gradientUnits="userSpaceOnUse" />
<filter
inkscape:collect="always"
style="color-interpolation-filters:sRGB"
id="filter961"
x="-0.06260625"
width="1.1252125"
y="-0.1276051"
height="1.2552102">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.39128906"
id="feGaussianBlur963" />
</filter>
<linearGradient
inkscape:collect="always"
xlink:href="#Gloss"
id="linearGradient885"
gradientUnits="userSpaceOnUse"
x1="128.4325"
y1="82.56572"
x2="132.28908"
y2="86.347733"
gradientTransform="matrix(1.5,0,0,1.5008815,-90.500002,-46.074046)" />
<filter
inkscape:collect="always"
style="color-interpolation-filters:sRGB"
id="filter864"
x="-0.070129702"
width="1.1402594"
y="-0.15211347"
height="1.3042269">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.68075106"
id="feGaussianBlur866" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="15"
inkscape:cx="113"
inkscape:cy="32"
inkscape:document-units="px"
inkscape:current-layer="aardvark"
showgrid="false"
inkscape:snap-nodes="true"
inkscape:snap-bbox="true"
inkscape:snap-global="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1680"
inkscape:window-height="1030"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0">
<inkscape:grid
type="xygrid"
id="pixelgrid"
visible="true"
enabled="true"
spacingx="0.5"
spacingy="0.5"
empspacing="2"
originx="0"
originy="0" />
</sodipodi:namedview>
<metadata
id="metadead">
<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>Icon: arrow-hand</dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
<dc:creator>
<cc:Agent>
<dc:title>Ichthyostega</dc:title>
</cc:Agent>
</dc:creator>
<dc:publisher>
<cc:Agent>
<dc:title>Lumiera.org</dc:title>
</cc:Agent>
</dc:publisher>
<dc:description>Triangle hand used to indicate menu and expander
prepared for Lumiera build :: Icon rendering</dc:description>
<dc:date>2022</dc:date>
<dc:identifier>icon:arrow-hand</dc:identifier>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
inkscape:label="artwork:arrow-hand"
id="aardvark"
style="display:inline">
<g
inkscape:groupmode="layer"
id="layerp"
inkscape:label="plate#1"
style="display:none"
sodipodi:insensitive="true">
<rect
id="bbox24"
x="96"
y="68"
width="24"
height="24"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox16"
x="124"
y="76"
width="16"
height="16"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
</g>
<g
id="ghand24">
<g
id="bevel24">
<path
id="path861"
style="fill:black;fill-opacity:0.31372549;stroke:none;stroke-width:0.05"
d="m 119.5,80 h -3 l -18,7.5 -1.5,3 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
id="path863"
style="fill:#ffffff;fill-opacity:0.74509804;stroke:none;stroke-width:0.05"
d="M 97,90.5 V 69.49383 l 1.5,3.001763 v 15.008815 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
id="path865"
style="fill:#f2f2f2;fill-opacity:0.66666667;stroke:none;stroke-width:0.05"
d="m 119.5,80 -3,0.0062 -18,-7.5062 -1.5,-3 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
</g>
<g
id="counter24">
<path
id="path869"
style="fill:#c8c8c8;fill-opacity:0.62745098;stroke:none;stroke-width:0.05"
d="m 99,73 17,7 h 0.5 l -18,-7.504407 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
id="path871"
style="fill:#646464;fill-opacity:0.19607843;stroke:none;stroke-width:0.05"
d="m 99,73 v 14 l -0.5,0.504408 V 72.495593 Z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
id="path873"
style="fill:#ffffff;fill-opacity:0.70588235;stroke:none;stroke-width:0.05"
d="M 98.5,87.504408 116.5,80 H 116 l -17,7 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
</g>
<path
id="gloss32"
style="fill:url(#linearGradient885);fill-opacity:1;stroke:none;stroke-width:0.05"
d="M 98.5,72.495593 116.5,80 l -18,7.5 z"
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0" />
<path
id="contour24"
style="fill:none;fill-opacity:0.75;stroke:black;stroke-opacity:1;stroke-width:0.07;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
d="M 119.15899,79.779553 96.95312,69.41175 v 20.813006"
sodipodi:nodetypes="ccc"
inkscape:connector-curvature="0" />
<path
id="shadow24"
style="fill:#43434b;fill-opacity:0.5098038;stroke:none;stroke-width:0.30000001;filter:url(#filter864)"
d="m 96.10078,90.632603 3.657302,-2.050299 17.191748,-7.944762 3.01993,-1.021416 -2.25683,2.152288 -17.45154,8.219648 z"
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0" />
</g>
<g
id="ghand16">
<g
id="bevel16">
<path
id="path3266"
style="fill:black;fill-opacity:0.31372549;stroke:none;stroke-width:0.05"
d="m 140,84 h -2 l -12,5 -1,2 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
id="path3268"
style="fill:#ffffff;fill-opacity:0.74509804;stroke:none;stroke-width:0.05"
d="M 125,91 V 77 l 1,2 v 10 z"
inkscape:connector-curvature="0" />
<path
id="path3273"
style="fill:#f2f2f2;fill-opacity:0.66666667;stroke:none;stroke-width:0.05"
d="m 140,84 h -2 l -12,-5 -1,-2 z"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
</g>
<g
id="counter16">
<path
id="path3298"
style="fill:#c8c8c8;fill-opacity:0.62745098;stroke:none;stroke-width:0.05"
d="m 126.5,79.5 11,4.5 h 0.5 l -12,-5 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
id="path3291"
style="fill:#646464;fill-opacity:0.19607843;stroke:none;stroke-width:0.05"
d="m 126.5,79.5 v 9 L 126,89 V 79 Z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
id="path3275"
style="fill:#ffffff;fill-opacity:0.70588235;stroke:none;stroke-width:0.05"
d="m 126,89 12,-5 h -0.5 l -11,4.5 z"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
<path
id="gloss16"
d="m 126,79 12,5 -12,5 z"
style="fill:url(#linearGradient3334);fill-opacity:1;stroke:none;stroke-width:0.05"
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0" />
<path
id="contour16"
style="fill:none;fill-opacity:0.75;stroke:black;stroke-opacity:1;stroke-width:0.05;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
d="M 139.76172,83.847656 124.96875,76.945312 V 90.8125"
sodipodi:nodetypes="ccc"
inkscape:connector-curvature="0" />
<path
id="shadow16"
style="fill:#43434b;fill-opacity:0.52747258;stroke:none;stroke-width:0.30000001;filter:url(#filter961)"
d="m 124.8125,91.125 1.02574,-0.990352 12.33755,-5.751836 2.16796,-0.414062 -1.34492,1.120289 -11.7957,5.895336 z"
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -0,0 +1,517 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="150"
height="100"
id="icon"
sodipodi:version="0.32"
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
version="1.0"
sodipodi:docname="panel-play.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<title
id="doctitle">Icon: play control</title>
<defs
id="defsz">
<filter
inkscape:collect="always"
style="color-interpolation-filters:sRGB"
id="filter21"
x="-0.069065808"
y="-0.094578709"
width="1.1381316"
height="1.1891574">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.8775"
id="feGaussianBlur21" />
</filter>
<filter
inkscape:collect="always"
style="color-interpolation-filters:sRGB"
id="filter28"
x="-0.08906238"
y="-0.13716608"
width="1.1781248"
height="1.2743322">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="1.7338546"
id="feGaussianBlur28" />
</filter>
<filter
inkscape:collect="always"
style="color-interpolation-filters:sRGB"
id="filter1"
x="-0.078995671"
y="-0.10222452"
width="1.1579913"
height="1.204449">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.686925"
id="feGaussianBlur1" />
</filter>
<filter
inkscape:collect="always"
style="color-interpolation-filters:sRGB"
id="filter2"
x="-0.13502681"
y="-0.16314888"
width="1.2700536"
height="1.3262978">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.87631782"
id="feGaussianBlur2" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5"
inkscape:cx="75"
inkscape:cy="40"
inkscape:document-units="px"
inkscape:current-layer="layerp"
showgrid="false"
inkscape:snap-nodes="true"
inkscape:snap-bbox="true"
inkscape:snap-global="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1920"
inkscape:window-height="1061"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1">
<inkscape:grid
type="xygrid"
id="pixelgrid"
visible="false"
enabled="true"
spacingx="0.5"
spacingy="0.5"
empspacing="2"
originx="0"
originy="0"
units="px" />
</sodipodi:namedview>
<metadata
id="metadead">
<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>Icon: play control</dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
<dc:creator>
<cc:Agent>
<dc:title>Ichthyostega</dc:title>
</cc:Agent>
</dc:creator>
<dc:publisher>
<cc:Agent>
<dc:title>Lumiera.org</dc:title>
</cc:Agent>
</dc:publisher>
<dc:description>Icon to identify a play-control in the GUI
prepared for Lumiera build :: Icon rendering</dc:description>
<dc:identifier>icon:panel-play</dc:identifier>
<dc:date>2025</dc:date>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
inkscape:label="artwork:panel-play"
id="aardvark"
style="display:inline">
<g
inkscape:groupmode="layer"
id="layerp"
inkscape:label="plate#1"
style="display:none"
sodipodi:insensitive="true">
<rect
id="bbox48"
x="8"
y="44"
width="48"
height="48"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-width:0.1;stroke-opacity:1"
sodipodi:insensitive="true" />
<rect
id="bbox32"
x="60"
y="60"
width="32"
height="32"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-width:0.1;stroke-opacity:1"
sodipodi:insensitive="true" />
<rect
id="bbox24"
x="96"
y="68"
width="24"
height="24"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-width:0.1;stroke-opacity:1"
sodipodi:insensitive="true" />
<rect
id="bbox22"
x="97"
y="69"
width="22"
height="22"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-width:0.1;stroke-opacity:1"
sodipodi:insensitive="true" />
<rect
id="bbox16"
x="124"
y="76"
width="16"
height="16"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-width:0.1;stroke-opacity:1"
sodipodi:insensitive="true" />
</g>
<g
id="player48">
<g
id="shadow1"
style="display:inline;mix-blend-mode:normal;fill:#4d4d5a;fill-opacity:0.686957;filter:url(#filter28)"
transform="translate(0.55689404,1.6033577)">
<path
id="sh_f1"
style="display:inline"
d="m 43.920868,53.907033 a 11.68072,12 0 0 0 -11.68072,12 11.68072,12 0 0 0 11.68072,12 11.68072,12 0 0 0 11.680721,-12 11.68072,12 0 0 0 -11.680721,-12 z m 0,7.5 a 4.3802703,4.5 0 0 1 4.38027,4.5 4.3802703,4.5 0 0 1 -4.38027,4.5 4.3802703,4.5 0 0 1 -4.38027,-4.5 4.3802703,4.5 0 0 1 4.38027,-4.5 z m -23.361442,-7.5 a 11.68072,12 0 0 0 -11.6807199,12 11.68072,12 0 0 0 11.6807199,12 11.68072,12 0 0 0 11.680722,-12 11.68072,12 0 0 0 -11.680722,-12 z m 0,7.5 a 4.3802703,4.5 0 0 1 4.380271,4.5 4.3802703,4.5 0 0 1 -4.380271,4.5 4.3802703,4.5 0 0 1 -4.380269,-4.5 4.3802703,4.5 0 0 1 4.380269,-4.5 z" />
<path
id="sh_h1"
style="display:inline"
d="m 27.374586,76.244353 h 3 v 8 h -3 z m 5,-2e-6 8,4 -8,4 z" />
</g>
<g
id="film1"
style="display:inline;stroke:#6c5d6f;stroke-opacity:1">
<path
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#6c5d6f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="M 15.519846,76.588962 26,81 h 2"
id="filmpath11"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#6c5d6f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="m 39,81 h 2.5 l 8.677558,-5.30418"
id="filmpath12"
sodipodi:nodetypes="ccc" />
</g>
<g
id="spool11"
transform="translate(-22.970703,34)">
<path
id="film11"
style="color:black;font-variation-settings:normal;overflow:visible;opacity:1;vector-effect:none;fill:#6c5d6f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.999997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none"
d="m 42.970703,20 a 12,12 0 0 0 -12,12 12,12 0 0 0 12,12 12,12 0 0 0 12,-12 12,12 0 0 0 -12,-12 z m 0,7.5 a 4.5,4.5 0 0 1 4.5,4.5 4.5,4.5 0 0 1 -4.5,4.5 4.5,4.5 0 0 1 -4.5,-4.5 4.5,4.5 0 0 1 4.5,-4.5 z" />
<circle
style="color:black;font-variation-settings:normal;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.999997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none"
id="core11"
cx="42.970703"
cy="32"
r="4.5" />
</g>
<g
id="spool12"
transform="translate(1.029297,34)">
<path
id="film12"
style="color:black;font-variation-settings:normal;overflow:visible;opacity:1;vector-effect:none;fill:#6c5d6f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.999997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none"
d="m 42.970703,20 a 12,12 0 0 0 -12,12 12,12 0 0 0 12,12 12,12 0 0 0 12,-12 12,12 0 0 0 -12,-12 z m 0,7.5 a 4.5,4.5 0 0 1 4.5,4.5 4.5,4.5 0 0 1 -4.5,4.5 4.5,4.5 0 0 1 -4.5,-4.5 4.5,4.5 0 0 1 4.5,-4.5 z" />
<circle
style="color:black;font-variation-settings:normal;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.999997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none"
id="core12"
cx="42.970703"
cy="32"
r="4.5" />
</g>
<g
id="head1"
transform="translate(5.03,33)"
style="display:inline">
<path
style="fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.999999px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 26.97,44.0 8.24,4.14 -8.24,3.86 z"
id="play1"
sodipodi:nodetypes="cccc" />
<rect
style="color:black;font-variation-settings:normal;overflow:visible;opacity:1;vector-effect:none;fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none"
id="pause1"
width="3.3"
height="8"
x="21.97"
y="44"
ry="0" />
</g>
</g>
<g
id="player32">
<g
id="shadow2"
style="font-variation-settings:normal;opacity:1;mix-blend-mode:normal;vector-effect:none;fill:#4d4d5a;fill-opacity:0.686957;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;filter:url(#filter21);stop-color:black;stop-opacity:1"
transform="translate(0.95831709,1.0146887)">
<path
id="sh_f2"
style="display:inline;stroke-width:0.999995"
d="m 67.095397,66.394602 a 7.3772554,7.5 0 0 0 -7.377255,7.5 7.3772554,7.5 0 0 0 7.377255,7.5 7.3772554,7.5 0 0 0 7.377255,-7.5 7.3772554,7.5 0 0 0 -7.377255,-7.5 z m 0,4.6875 a 2.7664708,2.8125 0 0 1 2.766471,2.8125 2.7664708,2.8125 0 0 1 -2.766471,2.8125 2.7664708,2.8125 0 0 1 -2.766471,-2.8125 2.7664708,2.8125 0 0 1 2.766471,-2.8125 z m 15.738147,-4.6875 a 7.3772554,7.5 0 0 0 -7.377256,7.5 7.3772554,7.5 0 0 0 7.377256,7.5 7.3772554,7.5 0 0 0 7.377255,-7.5 7.3772554,7.5 0 0 0 -7.377255,-7.5 z m 0,4.6875 a 2.7664708,2.8125 0 0 1 2.766471,2.8125 2.7664708,2.8125 0 0 1 -2.766471,2.8125 2.7664708,2.8125 0 0 1 -2.766471,-2.8125 2.7664708,2.8125 0 0 1 2.766471,-2.8125 z" />
<path
id="sh_h2"
style="display:inline"
d="m 71.169115,80.66177 h 3.295818 v 8 h -3.295818 z m 5.000002,-2e-6 8.236654,4.13805 -8.236654,3.86195 z" />
</g>
<g
id="film2"
style="display:inline;stroke:#6c5d6f;stroke-opacity:1"
transform="translate(44.26571,4)">
<path
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#6c5d6f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="M 18.034986,74.181114 24.73429,81 h 3"
id="filmpath21"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#6c5d6f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="m 38.73429,81 h 1 l 5.39516,-7.755972"
id="filmpath22"
sodipodi:nodetypes="ccc" />
</g>
<g
id="spool21"
transform="matrix(0.625,0,0,0.625,40.643311,53.5)"
style="stroke-width:1.59999">
<path
id="film21"
style="color:black;font-variation-settings:normal;overflow:visible;opacity:1;vector-effect:none;fill:#6c5d6f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.59999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none"
d="m 42.970703,20 a 12,12 0 0 0 -12,12 12,12 0 0 0 12,12 12,12 0 0 0 12,-12 12,12 0 0 0 -12,-12 z m 0,7.5 a 4.5,4.5 0 0 1 4.5,4.5 4.5,4.5 0 0 1 -4.5,4.5 4.5,4.5 0 0 1 -4.5,-4.5 4.5,4.5 0 0 1 4.5,-4.5 z" />
<circle
style="color:black;font-variation-settings:normal;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:1.59999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none"
id="core21"
cx="42.970703"
cy="32"
r="4.800005" />
</g>
<g
id="spool22"
transform="matrix(0.625,0,0,0.625,56.643314,53.5)"
style="stroke-width:1.59999">
<path
id="film22"
style="color:black;font-variation-settings:normal;overflow:visible;opacity:1;vector-effect:none;fill:#6c5d6f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.59999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none"
d="m 42.970703,20 a 12,12 0 0 0 -12,12 12,12 0 0 0 12,12 12,12 0 0 0 12,-12 12,12 0 0 0 -12,-12 z m 0,7.5 a 4.5,4.5 0 0 1 4.5,4.5 4.5,4.5 0 0 1 -4.5,4.5 4.5,4.5 0 0 1 -4.5,-4.5 4.5,4.5 0 0 1 4.5,-4.5 z" />
<circle
style="color:black;font-variation-settings:normal;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:1.59999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none"
id="core22"
cx="42.970703"
cy="32"
r="4.800005" />
</g>
<g
id="head2">
<path
style="fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.999999px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 76,81 8.24,4.14 -8.24,3.86 z"
id="play2"
sodipodi:nodetypes="cccc" />
<rect
style="color:black;font-variation-settings:normal;overflow:visible;vector-effect:none;fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none"
id="pause2"
width="3.3"
height="8"
x="71"
y="81"
ry="0" />
</g>
</g>
<g
id="player22">
<g
id="shadow3"
style="opacity:1;mix-blend-mode:normal;fill:#4d4d5a;fill-opacity:0.686957;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter1);stop-color:black;stop-opacity:1"
transform="translate(0.84768657,0.28256219)">
<path
id="sh_f3"
style="display:inline;stroke-width:0.999999"
d="m 112.87836,74.017224 a 5.2174378,5.5 0 0 0 -5.21743,5.5 5.2174378,5.5 0 0 0 5.21743,5.5 5.2174378,5.5 0 0 0 5.21744,-5.5 5.2174378,5.5 0 0 0 -5.21744,-5.5 z m 0,3.4 a 1.9921126,2.1 0 0 1 1.99212,2.1 1.9921126,2.1 0 0 1 -1.99212,2.1 1.9921126,2.1 0 0 1 -1.99211,-2.1 1.9921126,2.1 0 0 1 1.99211,-2.1 z m -10.43487,-3.4 a 5.2174378,5.5 0 0 0 -5.217441,5.5 5.2174378,5.5 0 0 0 5.217441,5.5 5.2174378,5.5 0 0 0 5.21744,-5.5 5.2174378,5.5 0 0 0 -5.21744,-5.5 z m 0,3.4 a 1.9921126,2.1 0 0 1 1.99211,2.1 1.9921126,2.1 0 0 1 -1.99211,2.1 1.9921126,2.1 0 0 1 -1.99211,-2.1 1.9921126,2.1 0 0 1 1.99211,-2.1 z" />
<path
id="sh_h3"
style="display:inline"
d="m 107.7728,84.144666 5.16,3.18 -5.16,2.82 z m -3,0 h 2.16 v 6 h -2.16 z" />
</g>
<g
id="film3"
style="display:inline;stroke:#6c5d6f;stroke-opacity:1"
transform="translate(81.211899,7.9246864)">
<path
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#6c5d6f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="m 17.35566,73.66163 5.432441,5.413684 h 1.5"
id="filmpath31"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#6c5d6f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="m 30.788101,79.075314 c 0,0 0.371411,0.08901 0.568296,0 2.246177,-1.015505 3.708651,-3.792829 5.093206,-5.72838"
id="filmpath32"
sodipodi:nodetypes="csc" />
</g>
<g
id="spool31"
transform="matrix(0.625,0,0,0.625,77.5895,60.42469)"
style="display:inline;stroke-width:1.59999">
<path
id="film31"
style="color:black;font-variation-settings:normal;overflow:visible;opacity:1;vector-effect:none;fill:#6c5d6f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.59999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none"
d="m 39.86,20.12 a 8.8,8.8 0 0 0 -8.8,8.8 8.8,8.8 0 0 0 8.8,8.8 8.8,8.8 0 0 0 8.8,-8.8 8.8,8.8 0 0 0 -8.8,-8.8 z m 0,5.5 a 3.3,3.3 0 0 1 3.3,3.3 3.3,3.3 0 0 1 -3.3,3.3 3.3,3.3 0 0 1 -3.3,-3.3 3.3,3.3 0 0 1 3.3,-3.3 z" />
<circle
style="color:black;font-variation-settings:normal;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:1.59999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none"
id="core31"
cx="39.906609"
cy="28.970312"
r="3.2498157" />
</g>
<g
id="spool32"
transform="matrix(0.625,0,0,0.625,88.5875,60.425004)"
style="display:inline;stroke-width:1.59999">
<path
id="film32"
style="color:black;font-variation-settings:normal;overflow:visible;opacity:1;vector-effect:none;fill:#6c5d6f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.59999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none"
d="m 39.86,20.12 a 8.8,8.8 0 0 0 -8.8,8.8 8.8,8.8 0 0 0 8.8,8.8 8.8,8.8 0 0 0 8.8,-8.8 8.8,8.8 0 0 0 -8.8,-8.8 z m 0,5.5 a 3.3,3.3 0 0 1 3.3,3.3 3.3,3.3 0 0 1 -3.3,3.3 3.3,3.3 0 0 1 -3.3,-3.3 3.3,3.3 0 0 1 3.3,-3.3 z" />
<circle
style="color:black;font-variation-settings:normal;overflow:visible;opacity:1;vector-effect:none;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:1.59999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none"
id="core32"
cx="39.906609"
cy="28.970312"
r="3.2498157" />
</g>
<g
id="head3">
<path
style="fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 108,84 5.16,3.18 L 108,90 Z"
id="play3"
sodipodi:nodetypes="cccc" />
<rect
style="color:black;font-variation-settings:normal;overflow:visible;vector-effect:none;fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none"
id="pause3"
width="2.16"
height="6"
x="105"
y="84"
ry="0" />
</g>
</g>
<g
id="player16">
<g
id="shadow4"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#4d4d5a;fill-opacity:0.686957;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;filter:url(#filter2);stop-color:black;stop-opacity:1"
transform="translate(0,1.2374369)">
<path
id="sh_f4"
style="display:inline;stroke-width:0.999997"
d="m 135.92968,77.955062 a 4.1296023,3.8080361 0 0 0 -4.12961,3.808036 4.1296023,3.8080361 0 0 0 4.12961,3.808037 4.1296023,3.8080361 0 0 0 4.1296,-3.808037 4.1296023,3.8080361 0 0 0 -4.1296,-3.808036 z m 0,1.962259 a 2.0016424,1.8457774 0 0 1 2.00164,1.845777 2.0016424,1.8457774 0 0 1 -2.00164,1.845778 2.0016424,1.8457774 0 0 1 -2.00164,-1.845778 2.0016424,1.8457774 0 0 1 2.00164,-1.845777 z m -7.31669,-2.11458 a 4.1296023,3.8080361 0 0 0 -4.1296,3.808036 4.1296023,3.8080361 0 0 0 4.1296,3.808036 4.1296023,3.8080361 0 0 0 4.12961,-3.808036 4.1296023,3.8080361 0 0 0 -4.12961,-3.808036 z m 0,1.962259 a 2.0016424,1.8457774 0 0 1 2.00165,1.845777 2.0016424,1.8457774 0 0 1 -2.00165,1.845777 2.0016424,1.8457774 0 0 1 -2.00163,-1.845777 2.0016424,1.8457774 0 0 1 2.00163,-1.845777 z" />
<path
id="sh_h4"
style="display:inline;stroke-width:0.999999"
d="m 129.63291,85.646447 h 2.18121 v 5.047358 h -2.18121 z m 2.96371,0 4.93951,2.700337 -4.93951,2.347021 z" />
</g>
<g
id="film4">
<path
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#6c5d6f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="m 124.9,83.48 3.05,5.51 h 1.5"
id="filmpath41"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#6c5d6f;stroke-width:1.1;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;stroke-dasharray:none"
d="m 135.82,89.04 c 0,0 0.62,0.08 1.04,-0.3 0.6,-0.55 1.34,-2.57 2.44,-5.59"
id="filmpath42"
sodipodi:nodetypes="csc" />
</g>
<g
id="spool41">
<path
id="film41"
style="color:black;font-variation-settings:normal;overflow:visible;vector-effect:none;fill:#6c5d6f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.999997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none"
d="m 128.22,77.5 a 4.25,4.25 0 0 0 -4.25,4.25 4.25,4.25 0 0 0 4.25,4.25 4.25,4.25 0 0 0 4.25,-4.25 4.25,4.25 0 0 0 -4.25,-4.25 z m 0,2.19 a 2.06,2.06 0 0 1 2.06,2.06 2.06,2.06 0 0 1 -2.06,2.06 2.06,2.06 0 0 1 -2.06,-2.06 2.06,2.06 0 0 1 2.06,-2.06 z" />
<circle
style="color:black;font-variation-settings:normal;display:inline;overflow:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.625;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="core41"
cx="128.25"
cy="81.75"
r="1.94" />
</g>
<g
id="spool42"
transform="translate(0,0.16948494)">
<path
id="film42"
style="color:black;font-variation-settings:normal;overflow:visible;vector-effect:none;fill:#6c5d6f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.999997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none"
d="m 135.75,77.5 a 4.25,4.25 0 0 0 -4.25,4.25 4.25,4.25 0 0 0 4.25,4.25 4.25,4.25 0 0 0 4.25,-4.25 4.25,4.25 0 0 0 -4.25,-4.25 z m 0,2.19 a 2.06,2.06 0 0 1 2.06,2.06 2.06,2.06 0 0 1 -2.06,2.06 2.06,2.06 0 0 1 -2.06,-2.06 2.06,2.06 0 0 1 2.06,-2.06 z" />
<circle
style="color:black;font-variation-settings:normal;display:inline;overflow:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.625;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="core42"
cx="135.8"
cy="81.75"
r="1.9400001" />
</g>
<g
id="head4">
<path
style="fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 132,86 5.0547,3.206326 L 132,92 Z"
id="play4"
sodipodi:nodetypes="cccc" />
<rect
style="color:black;font-variation-settings:normal;overflow:visible;vector-effect:none;fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none"
id="pause4"
width="2.2329035"
height="6"
x="128.97"
y="86"
ry="0" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 26 KiB

View file

@ -0,0 +1,355 @@
<?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="150"
height="100"
id="icon"
sodipodi:version="0.32"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
version="1.0"
sodipodi:docname="placement.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<title
id="doctitle">Icon: placement</title>
<defs
id="defsz">
<linearGradient
id="SphereGlow_green">
<stop
offset="0"
style="stop-color:#ecfbe9;stop-opacity:0.70588237"
id="stop5572" />
<stop
offset="0.75999999"
style="stop-color:#b1edc6;stop-opacity:0.58823532"
id="stop5578" />
<stop
offset="1"
style="stop-color:#629889;stop-opacity:0.86274511"
id="stop5574" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#SphereGlow_green"
id="radialGradient900"
gradientUnits="userSpaceOnUse"
cx="200"
cy="227.36218"
fx="200"
fy="227.36218"
r="10.15"
gradientTransform="matrix(0.6991,0,0,0.6991,-8.1767,-75.2124)" />
<radialGradient
inkscape:collect="always"
xlink:href="#SphereGlow_green"
id="radialGradient924"
gradientUnits="userSpaceOnUse"
cx="200"
cy="227.36218"
fx="200"
fy="227.36218"
r="10.15"
gradientTransform="matrix(0.99271412,0,0,0.9924095,-90.979233,-146.1521)" />
<radialGradient
inkscape:collect="always"
xlink:href="#SphereGlow_green"
id="radialGradient881"
gradientUnits="userSpaceOnUse"
cx="200"
cy="227.36218"
fx="200"
fy="227.36218"
r="10.15"
gradientTransform="matrix(1.39,0,0,1.39,-202.16115,-240.24904)" />
<radialGradient
inkscape:collect="always"
xlink:href="#SphereGlow_green"
id="radialGradient866"
gradientUnits="userSpaceOnUse"
cx="200"
cy="227.36218"
fx="200"
fy="227.36218"
r="10.15"
gradientTransform="matrix(2.134,0,0,2.134,-394.51542,-417.81291)" />
<filter
inkscape:collect="always"
style="color-interpolation-filters:sRGB"
id="filter852"
x="-0.0648"
width="1.1296"
y="-0.0648"
height="1.1296">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.40770001"
id="feGaussianBlur854" />
</filter>
<filter
inkscape:collect="always"
style="color-interpolation-filters:sRGB"
id="filter867"
x="-0.072196473"
width="1.1443929"
y="-0.071804594"
height="1.1436092">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.62112013"
id="feGaussianBlur869" />
</filter>
<filter
inkscape:collect="always"
style="color-interpolation-filters:sRGB"
id="filter910"
x="-0.0888"
width="1.1776"
y="-0.0888"
height="1.1776">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="1.0656"
id="feGaussianBlur912" />
</filter>
<filter
inkscape:collect="always"
style="color-interpolation-filters:sRGB"
id="filter883"
x="-0.0792"
width="1.1584"
y="-0.0792"
height="1.1584">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="1.4495704"
id="feGaussianBlur885" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="8"
inkscape:cx="75"
inkscape:cy="32"
inkscape:document-units="px"
inkscape:current-layer="aardvark"
showgrid="false"
inkscape:snap-nodes="true"
inkscape:snap-bbox="true"
inkscape:snap-global="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1680"
inkscape:window-height="1030"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid13478"
visible="true"
enabled="true"
spacingx="0.5"
spacingy="0.5"
empspacing="2"
originx="0"
originy="0" />
</sodipodi:namedview>
<metadata
id="metadead">
<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>Icon: placement</dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
<dc:creator>
<cc:Agent>
<dc:title>Ichthyostega</dc:title>
</cc:Agent>
</dc:creator>
<dc:publisher>
<cc:Agent>
<dc:title>Lumiera.org</dc:title>
</cc:Agent>
</dc:publisher>
<dc:description>Artwork for the »Placement« emblem
prepared for Lumiera build :: Icon rendering</dc:description>
<dc:date>2022</dc:date>
<dc:identifier>icon:placement</dc:identifier>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
inkscape:label="artwork:placement"
id="aardvark"
style="display:inline">
<g
inkscape:groupmode="layer"
id="layerp"
inkscape:label="plate#1"
style="display:none"
sodipodi:insensitive="true">
<rect
id="bbox48"
x="8"
y="44"
width="48"
height="48"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox32"
x="60"
y="60"
width="32"
height="32"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox24"
x="96"
y="68"
width="24"
height="24"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox22"
x="97"
y="69"
width="22"
height="22"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox16"
x="124"
y="76"
width="16"
height="16"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
</g>
<g
id="gplace48">
<circle
id="shadow48"
cx="31.897429"
cy="68.10257"
r="21.963188"
style="fill:#43434b;fill-opacity:0.52747258;stroke:none;stroke-width:0.30000001;filter:url(#filter883)" />
<circle
id="disc48"
cx="31.559999"
cy="67.599998"
r="21.299999"
style="fill:url(#radialGradient866);fill-opacity:1;stroke:#003c23;stroke-opacity:1;stroke-width:0.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;marker:none" />
<path
id="symbol48"
style="fill:#054b3f;fill-opacity:1;stroke:none;stroke-width:1"
d="M 27.266803,53.550259 23.856,78.36 c -4.612132,-0.519678 -4.141053,-3.328569 -2.923051,-6.675 l -2.61,-0.885 c -2.365476,5.736575 -1.717118,10.814277 6.12087,11.4378 h 0.528258 C 33.017092,82.059472 35.833224,77.431225 36.077051,71.629345 L 33.240612,72 c -0.403288,3.290065 -1.701037,5.882291 -5.788982,6.4 l 1.864421,-11.51 h 4.1347 c 3.191229,2.1e-5 5.624116,-0.627086 7.304358,-1.995131 1.680198,-1.368022 2.450167,-3.305295 2.301497,-5.761847 -0.110486,-1.827351 -0.779332,-3.186363 -2.030708,-4.134981 -1.251418,-0.948636 -3.00366,-1.448258 -5.279882,-1.448301 h -7.865323 z m 3.803,2.532923 h 4.270071 c 1.260847,2.1e-5 2.251487,0.234277 2.978407,0.813424 0.737969,0.57923 1.154944,1.391856 1.218403,2.440333 0.09924,1.637643 -0.380433,2.91732 -1.353798,3.796028 -0.973408,0.878774 -2.412956,1.355742 -4.332204,1.355742 h -4.134699 z"
sodipodi:nodetypes="cccccccccccssscccccsssccc"
inkscape:connector-curvature="0" />
</g>
<g
id="gplace32">
<circle
id="shadow32"
cx="76.187927"
cy="75.942558"
r="14.4"
style="fill:#43434b;fill-opacity:0.52747258;stroke:none;stroke-width:0.30000001;filter:url(#filter910)" />
<circle
id="disc32"
cx="75.921059"
cy="75.497215"
r="13.9"
style="fill:url(#radialGradient881);fill-opacity:1;stroke:#003c23;stroke-opacity:1;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;marker:none" />
<path
id="symbol32"
style="fill:#054b3f;fill-opacity:1;stroke:none;stroke-width:1"
d="m 73.4,66.047489 -2.281994,16.42609 C 68.06037,82.130321 68.192778,80.210378 69,78 l -1.77,-0.7 c -1.508775,3.946246 -1.053593,7.284278 4.140972,7.696127 h 0.3501 c 5.331769,-0.117788 7.198136,-3.174829 7.359732,-7.007076 l -1.879828,0.244825 C 76.9337,80.407023 76.209251,82.158042 73.5,82.5 l 1.276782,-7.759222 h 2.740239 c 2.173888,1.3e-5 3.742344,-0.396018 4.840905,-1.31782 1.052486,-0.88314 1.604102,-2.065352 1.505657,-3.687953 -0.07226,-1.190991 -0.572903,-2.147268 -1.345836,-2.731229 -0.829363,-0.626596 -1.990652,-0.9566 -3.499199,-0.956629 h -5.21268 z m 2.559693,1.673043 h 2.829954 c 0.835617,1.3e-5 1.542947,0.121385 2.013199,0.497996 0.614219,0.491909 0.785071,1.037197 0.827128,1.729736 0.06577,1.081692 -0.361626,1.84819 -0.936501,2.330568 -0.664782,0.557818 -1.638452,0.875848 -2.910417,0.875848 h -2.740239 z"
sodipodi:nodetypes="cccccccccccssscccccsssccc"
inkscape:connector-curvature="0" />
</g>
<g
id="gplace24">
<circle
id="shadow24"
cx="107.92383"
cy="79.922096"
r="10.34"
style="fill:#43434b;fill-opacity:0.52747258;stroke:none;stroke-width:0.30000001;filter:url(#filter867)" />
<circle
id="disc24"
cx="107.564"
cy="79.484299"
r="9.9239998"
style="fill:url(#radialGradient924);fill-opacity:1;stroke:#003c23;stroke-opacity:1;stroke-width:0.29999998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;marker:none" />
<path
id="symbol24"
style="fill:#054b3f;fill-opacity:1;stroke:none;stroke-width:1"
d="m 105.50537,72.932933 -1.58705,11.414674 c -1.93576,-0.311348 -1.86285,-1.563253 -1.34622,-3.122447 l -1.22096,-0.125084 c -1.09403,2.646548 -0.83875,4.809842 2.78631,5.097502 l 0.24432,-0.002 c 3.72081,-0.08227 5.08119,-2.25666 5.19396,-4.933337 l -1.31185,0.156771 c -0.18652,1.51786 -0.78923,2.717803 -2.6799,2.956646 l 0.85942,-5.282149 h 1.89694 c 1.47594,1e-5 2.60402,-0.307052 3.38113,-0.938195 0.77709,-0.631132 1.1332,-1.524886 1.06444,-2.658208 -0.0511,-0.843042 -0.36044,-1.470017 -0.9392,-1.907659 -0.57878,-0.437663 -1.38919,-0.656717 -2.44194,-0.656737 h -3.6316 z m 1.75201,1.15711 h 1.95955 c 0.58314,1e-5 1.04131,0.108083 1.37751,0.37527 0.34131,0.267226 0.53416,0.642128 0.56351,1.125839 0.0459,0.755521 -0.17595,1.345896 -0.62613,1.751285 -0.4502,0.405419 -1.11599,0.625466 -2.00364,0.625466 h -1.89694 z"
sodipodi:nodetypes="cccccccccccssscccccsssccc"
inkscape:connector-curvature="0" />
</g>
<g
id="gplace16">
<circle
id="shadow16"
cx="131.90001"
cy="83.952499"
r="7.5500002"
style="fill:#43434b;fill-opacity:0.52747258;stroke:none;stroke-width:0.30000001;filter:url(#filter852)" />
<circle
id="disc16"
cx="131.64999"
cy="83.695"
r="7"
style="fill:url(#radialGradient900);fill-opacity:1;stroke:#003c23;stroke-opacity:1;stroke-width:0.34999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;marker:none" />
<path
id="symbol16"
style="fill:#054b3f;fill-opacity:1;stroke:none;stroke-width:1"
d="m 130.38401,79.003475 -1.13693,8.339858 c -1.53738,-0.173226 -1.38035,-1.230356 -0.97435,-2.345833 l -0.87,-0.295 c -0.7885,1.912192 -0.57238,3.669659 2.04029,3.8775 H 129.65 c 2.94785,-0.116478 3.76872,-1.64604 3.85,-3.58 l -1,0.15339 c -0.25217,1.430122 -0.79823,2.051751 -2.1,2.21661 L 131,83.5 h 1.44533 c 1.06374,7e-6 1.8747,-0.258973 2.43478,-0.714988 0.56007,-0.456008 0.81672,-1.101765 0.76717,-1.920616 -0.0368,-0.609117 -0.25978,-1.062121 -0.6769,-1.378327 -0.41714,-0.316212 -1.00122,-0.482753 -1.75997,-0.482767 h -2.62177 z m 1.22241,0.844308 h 1.46861 c 0.42029,7e-6 0.77294,0.08161 1.01525,0.274657 0.24599,0.193077 0.38498,0.463953 0.40613,0.813444 0.0331,0.545881 -0.14836,1.028773 -0.47282,1.321676 -0.32446,0.292925 -0.82675,0.448397 -1.4665,0.448397 h -1.42351 z"
sodipodi:nodetypes="cccccccccccssscccccsssccc"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,481 @@
<?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="150"
height="100"
id="icon"
sodipodi:version="0.32"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
version="1.0"
sodipodi:docname="tool-arrow.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<title
id="doctitle">Icon: tool-arrow</title>
<defs
id="defsz">
<linearGradient
inkscape:collect="always"
id="linearGradient10554">
<stop
style="stop-color:white;stop-opacity:1;"
offset="0"
id="stop10556" />
<stop
style="stop-color:white;stop-opacity:0;"
offset="1"
id="stop10558" />
</linearGradient>
<linearGradient
id="linearGradient124">
<stop
style="stop-color:#ffffff;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop125" />
<stop
style="stop-color:silver;stop-opacity:1;"
offset="1"
id="stop126" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient8773">
<stop
style="stop-color:black;stop-opacity:0.3137255"
offset="0"
id="stop8775" />
<stop
style="stop-color:black;stop-opacity:0;"
offset="1"
id="stop8777" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient10554"
id="linearGradient14473"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-137.34366,-352.57235)"
x1="240.9062"
y1="425.18195"
x2="248.28683"
y2="437.96558" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient8773"
id="radialGradient14479"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.234973,0,18.5877)"
cx="-57.850174"
cy="24.296782"
fx="-58.028885"
fy="27.01318"
r="8.087534" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient8773"
id="radialGradient8830"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.234973,0,18.5877)"
cx="-57.850174"
cy="24.296782"
fx="-58.028885"
fy="27.01318"
r="8.087534" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient8773"
id="radialGradient8838"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.3189,0,0,0.41215831,154.96524,77.472687)"
cx="-57.850174"
cy="24.296782"
fx="-58.028885"
fy="27.01318"
r="8.087534" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient10554"
id="linearGradient8855"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-143.84355,-395.09223)"
x1="240.9062"
y1="425.18195"
x2="248.28683"
y2="437.96558" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient124"
id="radialGradient8858"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.6670334,0,0,2.399476,-490.75028,-800.6137)"
cx="307.7507"
cy="361.47824"
fx="307.7507"
fy="361.47824"
r="12.509617" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient124"
id="linearGradient8861"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.5891814,3.6707672,-0.9176918,0.3972953,-490.75027,-800.61371)"
x1="253.75711"
y1="-129.52815"
x2="252.00447"
y2="-135.47408" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient10554"
id="linearGradient7968"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.3333333,0,0,1.3333333,-251.3124,-500.60971)"
x1="240.9062"
y1="425.18195"
x2="248.28683"
y2="437.96558" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient124"
id="radialGradient7971"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1113546,0,0,1.5996493,-273.02082,-503.24197)"
cx="307.7507"
cy="361.47824"
fx="307.7507"
fy="361.47824"
r="12.509617" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient124"
id="linearGradient7974"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0594534,2.447176,-0.611794,0.2648633,-273.02082,-503.24198)"
x1="253.75711"
y1="-129.52815"
x2="252.00447"
y2="-135.47408" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient124"
id="radialGradient7979"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.833516,0,0,1.199737,-153.62497,-354.54654)"
cx="307.7507"
cy="361.47824"
fx="307.7507"
fy="361.47824"
r="12.509617" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient124"
id="linearGradient7982"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.79459,1.835382,-0.4588455,0.1986475,-153.62497,-354.54654)"
x1="253.75711"
y1="-129.52815"
x2="252.00447"
y2="-135.47408" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient10554"
id="linearGradient7986"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.7041896,0,0,0.7041896,-41.406433,-220.43017)"
x1="240.9062"
y1="425.18195"
x2="248.28683"
y2="437.96558" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient124"
id="radialGradient7989"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.5869533,0,0,0.8448423,-52.871564,-221.82036)"
cx="307.7507"
cy="361.47824"
fx="307.7507"
fy="361.47824"
r="12.509617" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient124"
id="linearGradient7992"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.559542,1.292457,-0.3231142,0.1398855,-52.871561,-221.82036)"
x1="253.75711"
y1="-129.52815"
x2="252.00447"
y2="-135.47408" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="8"
inkscape:cx="75"
inkscape:cy="50"
inkscape:document-units="px"
inkscape:current-layer="artwork"
showgrid="false"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
inkscape:snap-global="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1680"
inkscape:window-height="977"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="0">
<inkscape:grid
type="xygrid"
id="grid13478"
visible="true"
enabled="true"
spacingx="0.5"
spacingy="0.5"
empspacing="2"
originx="0"
originy="0" />
</sodipodi:namedview>
<metadata
id="metadead">
<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>Icon: tool-arrow</dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
<dc:creator>
<cc:Agent>
<dc:title>Joel Holdsworth</dc:title>
</cc:Agent>
</dc:creator>
<dc:publisher>
<cc:Agent>
<dc:title>Lumiera.org</dc:title>
</cc:Agent>
</dc:publisher>
<dc:description>prepared for Lumiera build :: Icon rendering</dc:description>
<dc:date>2008</dc:date>
<dc:identifier>icon:tool-arrow</dc:identifier>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="artwork"
inkscape:label="artwork:tool-arrow"
style="display:inline">
<g
inkscape:groupmode="layer"
id="layerp"
inkscape:label="plate#1"
style="display:none"
sodipodi:insensitive="true">
<rect
id="bbox48"
x="8"
y="44"
width="48"
height="48"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox32"
x="60"
y="60"
width="32"
height="32"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox24"
x="96"
y="68"
width="24"
height="24"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox22"
x="97"
y="69"
width="22"
height="22"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox16"
x="124"
y="76"
width="16"
height="16"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
</g>
<g
id="gicon48">
<ellipse
id="shadow48"
ry="1.9003495"
rx="8.087534"
cy="24.296782"
cx="-57.850174"
style="display:inline;opacity:0.7;fill:url(#radialGradient8830);fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.9783517,0,0,2.6311023,150.94798,21.55292)" />
<path
sodipodi:nodetypes="cccccccc"
style="display:inline;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#555753;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 21.5,49.5 v 31 L 30.625174,74.387037 36.5,87.5 41,85 35.312678,72.699537 l 8.186207,-0.875 z"
id="path14359"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="ccccccccc"
id="path14361"
d="m 31.494661,66.393867 4.193,5.47964 -0.770981,1.1558 5.414085,11.749959 -3.580549,2.018572 -5.647334,-12.584081 -1.502876,-0.0011 -0.852358,-6.65226 z"
style="display:inline;fill:url(#linearGradient8861);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.24999988;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
style="display:inline;fill:url(#radialGradient8858);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.25;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
d="m 42.428285,71.442167 -9.778982,1.03639 -10.656797,7.058934 0.05113,-28.746562 z"
id="path14363"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="ccccc"
id="path14365"
d="m 41.352312,71.052617 -8.886822,0.94924 -9.958165,6.598954 -0.01109,-26.63525 z"
style="display:inline;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient8855);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
inkscape:connector-curvature="0" />
</g>
<g
id="gicon32">
<ellipse
id="shadow32"
style="display:inline;opacity:0.7;fill:url(#radialGradient8838);fill-opacity:1;stroke:none;stroke-width:1.52099919;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
cx="78.666649"
cy="87.486794"
rx="10.666649"
ry="3.3333397" />
<path
id="path7942"
d="m 68.5,63.5 v 21 l 6,-4 4,8 3,-1.5 -4,-7.5 6,-1 z"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#555753;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:nodetypes="cccccccc"
inkscape:connector-curvature="0" />
<path
style="fill:url(#linearGradient7974);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 75.14218,74.762567 2.54096,4.115712 -0.62974,0.865233 3.76104,7.040091 -2.09045,1.044639 -3.82698,-7.62097 -1.13871,0.04138 -0.44746,-4.708373 z"
id="path7944"
sodipodi:nodetypes="ccccccccc"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="ccccc"
id="path7946"
d="M 82.46659,78.173634 75.30247,79.357306 69.0002,83.575985 68.9986,64.713208 Z"
style="fill:url(#radialGradient7971);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
style="display:inline;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient7968);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 81.42262,77.84474 -6.32181,1.044424 -5.59708,3.753794 0.01965,-16.689795 z"
id="path7948"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0" />
</g>
<g
id="gicon24">
<ellipse
id="shadow24"
ry="1.9003495"
rx="8.087534"
cy="24.296782"
cx="-57.850174"
style="display:inline;opacity:0.7;fill:url(#radialGradient14479);fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(0.989175,0,0,1.31555,167.22388,56.536408)" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#555753;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 102.51565,70.50995 v 15.44351 l 4.54688,-3 2.78125,6.4375 2.28125,-1 -2.71875,-6.28125 4.0931,-0.4375 z"
id="rect16" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc"
id="rect91"
d="m 107.49727,78.956867 1.86763,2.574089 -0.4723,0.648924 2.57762,5.953897 -1.3657,0.598909 -2.67687,-6.181548 -0.85404,0.03104 -0.44985,-3.042022 z"
style="fill:url(#linearGradient7982);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.24999988;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
style="fill:url(#radialGradient7979);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.25;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
d="m 112.39587,81.28373 -4.42387,0.46295 -4.94643,3.25483 -0.009,-13.24474 z"
id="path15"
sodipodi:nodetypes="ccccc" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc"
id="path7947"
d="m 111.38437,80.978458 -4.0646,0.38781 -3.8111,2.78019 -0.009,-11.17262 z"
style="display:inline;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient14473);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</g>
<g
id="gicon16">
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#555753;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 127.5,77.5 v 11 l 3,-2 2,4 2,-1 -2,-4 h 3 z"
id="path14451" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc"
id="path14453"
d="m 131.008,83.448252 1.58303,1.516888 -0.52232,0.802948 1.7649,3.511869 -1.12353,0.555673 -1.70088,-3.465705 -0.77997,-0.279483 -0.18844,-2.231446 z"
style="fill:url(#linearGradient7992);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.24999988;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
style="fill:url(#radialGradient7989);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.25;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
d="m 134.29014,84.997498 -2.43444,0.0023 -3.85153,2.559874 -8.7e-4,-8.824576 z"
id="path14455"
sodipodi:nodetypes="ccccc" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc"
id="path14457"
d="m 133.09792,84.503506 -1.46156,0.03872 -3.12458,2.09729 -0.006,-6.745991 z"
style="display:inline;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient7986);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB

View file

@ -0,0 +1,263 @@
<?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="150"
height="100"
id="icon"
sodipodi:version="0.32"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
version="1.0"
sodipodi:docname="tool-i-beam.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<title
id="doctitle">Icon: tool-i-beam</title>
<defs
id="defsz">
<linearGradient
inkscape:collect="always"
id="linearGradient8773">
<stop
style="stop-color:black;stop-opacity:0.3137255"
offset="0"
id="stop8775" />
<stop
style="stop-color:black;stop-opacity:0;"
offset="1"
id="stop8777" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient8773"
id="radialGradient14479"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.234973,0,18.5877)"
cx="-57.850174"
cy="24.296782"
fx="-58.028885"
fy="27.01318"
r="8.087534" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient8773"
id="radialGradient8778"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.234973,0,18.5877)"
cx="-57.850174"
cy="24.296782"
fx="-58.028885"
fy="27.01318"
r="8.087534" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient8773"
id="radialGradient8788"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.234973,0,18.5877)"
cx="-57.850174"
cy="24.296782"
fx="-58.028885"
fy="27.01318"
r="8.087534" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="8"
inkscape:cx="75"
inkscape:cy="50"
inkscape:document-units="px"
inkscape:current-layer="artwork"
showgrid="false"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
inkscape:snap-global="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1680"
inkscape:window-height="977"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="0">
<inkscape:grid
type="xygrid"
id="grid13478"
visible="true"
enabled="true"
spacingx="0.5"
spacingy="0.5"
empspacing="2"
originx="0"
originy="0" />
</sodipodi:namedview>
<metadata
id="metadead">
<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>Icon: tool-i-beam</dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
<dc:creator>
<cc:Agent>
<dc:title>Joel Holdsworth</dc:title>
</cc:Agent>
</dc:creator>
<dc:publisher>
<cc:Agent>
<dc:title>Lumiera.org</dc:title>
</cc:Agent>
</dc:publisher>
<dc:description>prepared for Lumiera build :: Icon rendering</dc:description>
<dc:date>2008</dc:date>
<dc:identifier>icon:tool-i-beam</dc:identifier>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="artwork"
inkscape:label="artwork:tool-i-beam"
style="display:inline">
<g
inkscape:groupmode="layer"
id="layerp"
inkscape:label="plate#1"
style="display:none"
sodipodi:insensitive="true">
<rect
id="bbox48"
x="8"
y="44"
width="48"
height="48"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox32"
x="60"
y="60"
width="32"
height="32"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox24"
x="96"
y="68"
width="24"
height="24"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox22"
x="97"
y="69"
width="22"
height="22"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox16"
x="124"
y="76"
width="16"
height="16"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
</g>
<g
id="gicon48">
<ellipse
id="shadow48"
ry="1.9003495"
rx="8.087534"
cy="24.296782"
cx="-57.850174"
style="display:inline;opacity:0.7;fill:url(#radialGradient8788);fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(1.97835,0,0,2.6311,145.94789,21.072816)" />
<path
inkscape:connector-curvature="0"
style="fill:#eeeeec;fill-rule:evenodd;stroke:#555753;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 25.5,50.509196 c -1,0 -2,1 -2,1.989516 0,1.010484 1,2.010484 2,2.010484 h 2 c 1,0 2,1 2,2 v 21.989516 c 0,1 -1,2 -2,2 h -2 c -1,0 -2,1 -2,2 0,1.017752 1,2 2,2 h 4 c 1.04304,0.04305 2,-1 2,-2 0,1 1,2 2,2 l 4,-0.01903 c 0.99998,-0.0048 2,-1 2,-1.98097 0,-1.01903 -1.00004,-2.028544 -2,-2.01903 l -2,0.01903 c -1,0 -2,-1 -2,-2 V 56.509196 c 0,-1 1,-2 2,-2 l 2,-0.01048 c 0.99998,-0.0052 2,-1 2,-1.96875 0,-1.03125 -1,-2.03387 -2,-2.03125 l -4,0.01048 c -1,0 -2,1 -2,2 0,-1 -1,-2 -2,-2 z"
id="path8786"
sodipodi:nodetypes="cssccccssscccsssccccssscccs" />
</g>
<g
id="gicon32">
<ellipse
id="shadow32"
ry="1.9003495"
rx="8.087534"
cy="24.296782"
cx="-57.850174"
transform="matrix(1.3189,0,0,1.7540667,152.29859,44.715211)"
style="display:inline;opacity:0.7;fill:url(#radialGradient8778);fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
id="path8765"
style="fill:#eeeeec;fill-rule:evenodd;stroke:#555753;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 71.5,64.5 C 71,64.498835 70,65 70,66 c 0,1 1,1.5 1.5,1.5 h 2 c 0.5,0 1,0.5 1,1.006989 V 83.166666 C 74.5,83.833333 73.83333,84.5 73.16667,84.5 H 71.5 C 71,84.5 70,85 70,86 c 0,1 1,1.5 1.5,1.5 h 3 c 1,0 1.5,-1 1.5,-1.5 0,0.5 0.5,1.5 1.5,1.5 h 3 C 81,87.5 82,87 82,86 82,85 81,84.5 80.5,84.5 h -2 c -0.66667,0 -1,-0.673656 -1,-1.340323 V 68.5 c 0,-0.5 0.5,-1 1,-1 h 2 C 81,67.5 82,67 82,66 82,65 81,64.5 80.5,64.5 h -3 c -1,0 -1.5,1 -1.5,1.5 0,-0.5 -0.5,-1.5 -1.5,-1.493011 z"
sodipodi:nodetypes="cssccccssscccsssccccssscccs"
inkscape:connector-curvature="0" />
</g>
<g
id="gicon24">
<ellipse
id="shadow24"
ry="1.9003495"
rx="8.087534"
cy="24.296782"
cx="-57.850174"
style="display:inline;opacity:0.7;fill:url(#radialGradient14479);fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
transform="matrix(0.989175,0,0,1.31555,164.72395,56.536408)" />
<path
id="path7969"
d="m 104.5,71.505242 c -0.5,0 -1,0.5 -1,0.994758 0,0.505242 0.5,1.005242 1,1.005242 h 1 c 0.5,0 1,0.5 1,1 V 85.5 c 0,0.5 -0.5,1 -1,1 h -1 c -0.5,0 -1,0.5 -1,1 0,0.508876 0.5,1 1,1 h 2 c 0.52152,0.02152 1,-0.5 1,-1 0,0.5 0.5,1 1,1 l 2,-0.0095 c 0.49999,-0.0024 1,-0.5 1,-0.990485 0,-0.509515 -0.50002,-1.014272 -1,-1.009515 l -1,0.0095 c -0.5,0 -1,-0.5 -1,-1 V 74.505242 c 0,-0.5 0.5,-1 1,-1 l 1,-0.0052 c 0.49999,-0.0026 1,-0.5 1,-0.984375 C 111.5,72 111,71.49869 110.5,71.5 l -2,0.0052 c -0.5,0 -1,0.5 -1,1 0,-0.5 -0.5,-1 -1,-1 z"
style="fill:#eeeeec;fill-rule:evenodd;stroke:#555753;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
sodipodi:nodetypes="cssccccssscccsssccccssscccs"
inkscape:connector-curvature="0" />
</g>
<g
id="gicon16">
<path
style="fill:#eeeeec;fill-rule:evenodd;stroke:#555753;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 129.5,77.5 c -0.50963,0 -1,0.5 -1,1 0,0.5 0.5,1 1,1 v 0 c 0.5,0 1,0.5 1,1 v 7 c 0,0.5 -0.5,1 -1,1 v 0 c -0.5,0 -1,0.5 -1,1 0,0.5 0.5,1 1,1 h 1 c 0.5,0 1,-0.5 1,-1 0,0.5 0.5,1 1,1 h 1 c 0.5,0 1,-0.5 1,-1 0,-0.5 -0.5,-1 -1,-1 v 0 c -0.5,0 -1,-0.5 -1,-1 v -7 c 0,-0.5 0.5,-1 1,-1 v 0 c 0.5,0 1,-0.5 1,-1 0,-0.5 -0.5,-1 -1,-1 h -1 c -0.5,0 -1,0.5 -1,1 0,-0.5 -0.5,-1 -1,-1 z"
id="path7977"
sodipodi:nodetypes="cssccccssscccsssccccssscccs"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -0,0 +1,213 @@
<?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="150"
height="100"
id="icon"
sodipodi:version="0.32"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
version="1.0"
sodipodi:docname="track-disabled.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<title
id="doctitle">Icon: track-disabled</title>
<defs
id="defsz">
<linearGradient
id="linearGradient14313">
<stop
id="stop14315"
offset="0"
style="stop-color:#d5d5d5;stop-opacity:1;" />
<stop
style="stop-color:#dadada;stop-opacity:1;"
offset="0.55299991"
id="stop14317" />
<stop
id="stop14319"
offset="0.80015606"
style="stop-color:#b6b6b6;stop-opacity:1;" />
<stop
id="stop14321"
offset="1"
style="stop-color:#a2a2a2;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient14313"
id="radialGradient15234"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.9845232,-0.01897377,0.01641167,0.8792366,119.7485,61.3536)"
cx="11.368229"
cy="26.534439"
fx="11.368229"
fy="26.534439"
r="7.4999995" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient14313"
id="radialGradient8912"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.3537194,-0.02608894,0.02256605,1.2089503,91.154188,48.8612)"
cx="11.368229"
cy="26.534439"
fx="11.368229"
fy="26.534439"
r="7.4999995" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="8.2466667"
inkscape:cx="75"
inkscape:cy="50"
inkscape:document-units="px"
inkscape:current-layer="artwork"
showgrid="false"
inkscape:snap-nodes="true"
inkscape:snap-bbox="true"
inkscape:snap-global="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1680"
inkscape:window-height="1031"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid13478"
visible="true"
enabled="true"
spacingx="0.5"
spacingy="0.5"
empspacing="2"
originx="0"
originy="0" />
</sodipodi:namedview>
<metadata
id="metadead">
<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>Icon: track-disabled</dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
<dc:creator>
<cc:Agent>
<dc:title>Joel Holdsworth</dc:title>
</cc:Agent>
</dc:creator>
<dc:publisher>
<cc:Agent>
<dc:title>Lumiera.org</dc:title>
</cc:Agent>
</dc:publisher>
<dc:description>prepared for Lumiera build :: Icon rendering</dc:description>
<dc:date>2008</dc:date>
<dc:identifier>icon:track-disabled</dc:identifier>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="artwork"
inkscape:label="artwork:track-disabled"
style="display:inline">
<g
inkscape:groupmode="layer"
id="layerp"
inkscape:label="plate#1"
style="display:none"
sodipodi:insensitive="true">
<rect
id="bbox24"
x="96"
y="68"
width="24"
height="24"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox22"
x="97"
y="69"
width="22"
height="22"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox16"
x="124"
y="76"
width="16"
height="16"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
</g>
<g
id="gicon24">
<path
id="path8908"
style="display:inline;overflow:visible;visibility:visible;opacity:0.9;fill:url(#radialGradient8912);fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.70164645;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
d="m 118.3125,81.332513 c -2.97756,3.859487 -6.55875,4.766712 -10.15465,4.766712 -3.59604,0 -8.10439,-0.627138 -8.80082,-4.766712 0.75556,-3.7851 2.70833,-6.101288 7.72365,-6.144326 5.48075,-0.04689 8.14261,3.453588 11.23182,6.144326 z"
sodipodi:nodetypes="czcsc"
inkscape:connector-curvature="0" />
<path
id="path8906"
style="display:inline;overflow:visible;visibility:visible;fill:#888a85;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.60000002;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
d="m 118.47393,81.332513 c -3.003,3.859487 -6.61458,4.766712 -10.24114,4.766712 -3.62657,0 -8.17328,-0.627138 -8.87576,-4.766712 0.76202,-3.7851 -3.38553,3.698337 1.24877,5.740762 5.35672,2.3606 13.19326,1.516488 17.86813,-5.740762 z"
sodipodi:nodetypes="czcsc"
inkscape:connector-curvature="0" />
</g>
<g
id="gicon16">
<path
id="path13696"
style="display:inline;overflow:visible;visibility:visible;fill:#888a85;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.60000002;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
d="m 139.6174,84.9691 c -2.184,2.8069 -4.8106,3.4667 -7.4481,3.4667 -2.6375,0 -5.9442,-0.4561 -6.4551,-3.4667 0.5542,-2.7528 -2.4622,2.6897 0.9082,4.1751 3.8958,1.7168 9.5951,1.1029 12.995,-4.1751 z"
sodipodi:nodetypes="czcsc"
inkscape:connector-curvature="0" />
<path
id="path13699"
style="display:inline;overflow:visible;visibility:visible;opacity:0.9;fill:url(#radialGradient15234);fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.70164645;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
d="m 139.5,84.9691 c -2.1655,2.8069 -4.77,3.4667 -7.3852,3.4667 -2.6153,0 -5.8941,-0.4561 -6.4006,-3.4667 0.5495,-2.7528 1.9697,-4.4373 5.6172,-4.4686 3.986,-0.0341 5.9219,2.5117 8.1686,4.4686 z"
sodipodi:nodetypes="czcsc"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.4 KiB

View file

@ -0,0 +1,325 @@
<?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="150"
height="100"
id="icon"
sodipodi:version="0.32"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
version="1.0"
sodipodi:docname="track-enabled.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<title
id="doctitle">Icon: track-enabled</title>
<defs
id="defsz">
<linearGradient
inkscape:collect="always"
id="linearGradient14230">
<stop
style="stop-color:#555753;stop-opacity:1;"
offset="0"
id="stop14232" />
<stop
style="stop-color:#555753;stop-opacity:0;"
offset="1"
id="stop14234" />
</linearGradient>
<linearGradient
id="linearGradient13707">
<stop
id="stop13709"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0.55299991"
id="stop13711" />
<stop
id="stop13713"
offset="1"
style="stop-color:#a2a2a2;stop-opacity:1;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient13602">
<stop
style="stop-color:#888a85;stop-opacity:1;"
offset="0"
id="stop13604" />
<stop
style="stop-color:#888a85;stop-opacity:0;"
offset="1"
id="stop13606" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient14230"
id="linearGradient14931"
gradientUnits="userSpaceOnUse"
x1="1117.1925"
y1="1545"
x2="1123.9001"
y2="1545"
gradientTransform="translate(-983.9001,-1463)" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient13707"
id="radialGradient14937"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.3199975,0,0,0.9601076,-1333.8224,-1395.5357)"
cx="1110.5"
cy="1543"
fx="1110.5"
fy="1543"
r="6.1412096" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient13602"
id="linearGradient14940"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.998754,0,0,1,120.1049,79)"
x1="4.4194174"
y1="3.5226197"
x2="20.01996"
y2="3.5226197" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient14230"
id="linearGradient10612"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.375,0,0,1.375,-1426.3626,-2047.125)"
x1="1117.1925"
y1="1545"
x2="1123.9001"
y2="1545" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient13707"
id="radialGradient10618"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.8149966,0,0,1.3201479,-1907.5058,-1954.3616)"
cx="1110.5"
cy="1543"
fx="1110.5"
fy="1543"
r="6.1412096" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient13602"
id="linearGradient10621"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.3732868,0,0,1.375,91.644238,73.125)"
x1="4.4194174"
y1="3.5226197"
x2="20.01996"
y2="3.5226197" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="8"
inkscape:cx="75"
inkscape:cy="50"
inkscape:document-units="px"
inkscape:current-layer="artwork"
showgrid="false"
inkscape:snap-nodes="true"
inkscape:snap-bbox="true"
inkscape:snap-global="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1680"
inkscape:window-height="1031"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid13478"
visible="true"
enabled="true"
spacingx="0.5"
spacingy="0.5"
empspacing="2"
originx="0"
originy="0" />
</sodipodi:namedview>
<metadata
id="metadead">
<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>Icon: track-enabled</dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
<dc:creator>
<cc:Agent>
<dc:title>Joel Holdsworth</dc:title>
</cc:Agent>
</dc:creator>
<dc:publisher>
<cc:Agent>
<dc:title>Lumiera.org</dc:title>
</cc:Agent>
</dc:publisher>
<dc:description>prepared for Lumiera build :: Icon rendering</dc:description>
<dc:date>2008</dc:date>
<dc:identifier>icon:track-enabled</dc:identifier>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="artwork"
inkscape:label="artwork:track-enabled"
style="display:inline">
<g
inkscape:groupmode="layer"
id="layerp"
inkscape:label="plate#1"
style="display:none"
sodipodi:insensitive="true">
<rect
id="bbox24"
x="96"
y="68"
width="24"
height="24"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox22"
x="97"
y="69"
width="22"
height="22"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox16"
x="124"
y="76"
width="16"
height="16"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
</g>
<g
id="gicon24">
<path
id="path10062"
style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient10621);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.60000002;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
d="m 99.3672,82.810913 -1.65385,-0.730675 c 1.27449,-8.14275 9.73819,-14.052763 21.08026,-3.585175 l -0.20254,4.270337 -0.005,0.03314 c -3.13335,-2.689225 -5.83302,-6.140887 -11.39215,-6.140887 -6.38165,0.0847 -7.37701,4.966912 -7.82636,6.153263 z"
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0" />
<path
id="path10064"
style="display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient10618);fill-opacity:1;fill-rule:evenodd;stroke:#555753;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.60000002;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
d="m 118.25736,82.798537 c -2.99365,3.857288 -6.59409,4.763963 -10.20937,4.763963 -3.61543,0 -8.14798,-0.626725 -8.84813,-4.763963 0.75955,-3.783037 2.72278,-6.097849 7.76518,-6.140887 5.51017,-0.04689 8.18634,3.451662 11.29232,6.140887 z"
sodipodi:nodetypes="czcsc"
inkscape:connector-curvature="0" />
<circle
id="path10066"
r="4.81"
cx="107.437"
cy="82.065"
style="display:inline;overflow:visible;visibility:visible;fill:#204a87;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.66666889;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.60000002;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
<ellipse
id="path10068"
ry="2.4749756"
rx="2.7466187"
cx="106.75043"
cy="81.101677"
style="display:inline;overflow:visible;visibility:visible;fill:#3465a4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.66666889;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.60000002;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
<ellipse
id="path10070"
cx="106.0638"
cy="80.551476"
ry="1.1000504"
rx="1.3733999"
style="display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.40971795;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.60000002;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
<path
style="fill:none;fill-rule:evenodd;stroke:url(#linearGradient10612);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 97.825,82.0625 c 1.21866,-8.147975 10.42828,-15.018987 20.4875,-3.587375"
id="path10072"
sodipodi:nodetypes="cs"
inkscape:connector-curvature="0" />
</g>
<g
id="gicon16">
<path
id="path13575"
style="display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient14940);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.60000002;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
d="m 125.7216,86.0443 -1.2028,-0.5314 c 0.9269,-5.922 6.9005,-9.8111 15.3311,-2.6074 l -0.1473,3.1057 -0.004,0.0241 c -2.2788,-1.9558 -4.2422,-4.4661 -8.2852,-4.4661 -4.6412,0.0616 -5.3651,3.6123 -5.6919,4.4751 z"
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="czcsc"
id="path14269"
d="m 139.4599,86.0353 c -2.1772,2.8053 -4.7957,3.4647 -7.425,3.4647 -2.6294,0 -5.9258,-0.4558 -6.435,-3.4647 0.5524,-2.7513 1.9802,-4.4348 5.6474,-4.4661 4.0074,-0.0341 5.9537,2.5103 8.2126,4.4661 z"
style="display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient14937);fill-opacity:1;fill-rule:evenodd;stroke:#555753;stroke-width:1.00000012;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.60000002;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
inkscape:connector-curvature="0" />
<circle
id="path14276"
r="3.5"
cx="131.59055"
cy="85.501503"
style="display:inline;overflow:visible;visibility:visible;fill:#204a87;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.66666889;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.60000002;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
<ellipse
id="path13698"
cx="131.09123"
cy="84.80117"
ry="1.7999822"
rx="1.997541"
style="display:inline;overflow:visible;visibility:visible;fill:#3465a4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.66666889;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.60000002;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
<ellipse
id="path13700"
ry="0.80003661"
rx="0.99883622"
cx="130.59184"
cy="84.401024"
style="display:inline;overflow:visible;visibility:visible;fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.66666889;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.60000002;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
<path
sodipodi:nodetypes="cs"
id="path13565"
d="m 124.6,85.5 c 0.8863,-5.9258 7.5842,-10.9229 14.9,-2.609"
style="fill:none;fill-rule:evenodd;stroke:url(#linearGradient14931);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,411 @@
<?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="150"
height="100"
id="icon"
sodipodi:version="0.32"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
version="1.0"
sodipodi:docname="track-locked.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<title
id="doctitle">Icon: track-locked</title>
<defs
id="defsz">
<linearGradient
id="linearGradient9845">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop9847" />
<stop
style="stop-color:#ffffff;stop-opacity:0.49484536;"
offset="1.0000000"
id="stop9849" />
</linearGradient>
<linearGradient
id="linearGradient2092">
<stop
id="stop2094"
offset="0"
style="stop-color:#fff7b0;stop-opacity:1;" />
<stop
style="stop-color:#ffec41;stop-opacity:1.0000000;"
offset="0.20999999"
id="stop2098" />
<stop
id="stop43205"
offset="0.83999997"
style="stop-color:#e2cc00;stop-opacity:1;" />
<stop
id="stop2100"
offset="1"
style="stop-color:#c3af00;stop-opacity:1;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient12071">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop12073" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop12075" />
</linearGradient>
<linearGradient
id="linearGradient10672">
<stop
id="stop10674"
offset="0.0000000"
style="stop-color:#cad0c6;stop-opacity:1.0000000;" />
<stop
style="stop-color:#eaece9;stop-opacity:1.0000000;"
offset="0.5"
id="stop10676" />
<stop
id="stop10678"
offset="1.0000000"
style="stop-color:#c5cbc0;stop-opacity:1.0000000;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient12071"
id="linearGradient11588"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.9999999,0,0,0.1218105,123,80.320175)"
x1="11.5"
y1="20.579729"
x2="11.779029"
y2="14.259961" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient9845"
id="linearGradient11591"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.2913951,0,0,0.3423373,103.01101,72.677438)"
x1="10.907269"
y1="25.002281"
x2="30.875446"
y2="36.127281" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2092"
id="linearGradient11594"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.3442205,0,0,0.4285241,101.90469,69.427901)"
x1="75.809868"
y1="37.505707"
x2="99.050781"
y2="37.505707" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient12071"
id="linearGradient11597"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.6839207,0,0,0.2483044,121.36748,78.128618)"
x1="14.217941"
y1="6.8795347"
x2="17.859085"
y2="3.9566603" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient12071"
id="linearGradient11600"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.7816237,0,0,0.3586619,97.277125,71.741338)"
x1="14.217941"
y1="6.8795347"
x2="17.859085"
y2="3.9566603" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient10672"
id="linearGradient11603"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.382848,0,0,0.3862455,100.78214,69.859514)"
x1="16.894075"
y1="1.3346111"
x2="24.077082"
y2="19.134172" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient12071"
id="linearGradient11617"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.9999999,0,0,0.3654315,100,70.960525)"
x1="11.5"
y1="20.579729"
x2="11.779029"
y2="14.259961" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient9845"
id="linearGradient11620"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.2913951,0,0,0.3423373,101.01101,71.677437)"
x1="10.907269"
y1="25.002281"
x2="30.875446"
y2="36.127281" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2092"
id="linearGradient11623"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.3442205,0,0,0.4285241,99.90469,68.4279)"
x1="6.0871158"
y1="31.67173"
x2="40.94849"
y2="31.67173" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient12071"
id="linearGradient11626"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.7816237,0,0,0.3586619,95.277125,70.741337)"
x1="14.217941"
y1="6.8795347"
x2="17.859085"
y2="3.9566603" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient10672"
id="linearGradient11629"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.382848,0,0,0.3862455,98.78214,68.859513)"
x1="16.894075"
y1="1.3346111"
x2="24.077082"
y2="19.134172" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="8"
inkscape:cx="75"
inkscape:cy="50"
inkscape:document-units="px"
inkscape:current-layer="artwork"
showgrid="false"
inkscape:snap-nodes="true"
inkscape:snap-bbox="true"
inkscape:snap-global="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1680"
inkscape:window-height="1031"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid13478"
visible="true"
enabled="true"
spacingx="0.5"
spacingy="0.5"
empspacing="2"
originx="0"
originy="0" />
</sodipodi:namedview>
<metadata
id="metadead">
<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>Icon: track-locked</dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
<dc:creator>
<cc:Agent>
<dc:title>Joel Holdsworth</dc:title>
</cc:Agent>
</dc:creator>
<dc:publisher>
<cc:Agent>
<dc:title>Lumiera.org</dc:title>
</cc:Agent>
</dc:publisher>
<dc:description>prepared for Lumiera build :: Icon rendering</dc:description>
<dc:date>2008</dc:date>
<dc:identifier>icon:track-locked</dc:identifier>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="artwork"
inkscape:label="artwork:track-locked"
style="display:inline">
<g
inkscape:groupmode="layer"
id="layerp"
inkscape:label="plate#1"
style="display:none"
sodipodi:insensitive="true">
<rect
id="bbox24"
x="96"
y="68"
width="24"
height="24"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox22"
x="97"
y="69"
width="22"
height="22"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox16"
x="124"
y="76"
width="16"
height="16"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
</g>
<g
id="gicon24">
<path
sodipodi:nodetypes="cczcccczccc"
id="path10684"
d="m 103,79 v -3 c 0,-3.03985 0.875,-5 5,-5 4.125,0 5,1.9244 5,5 v 3 h -3 v -3 c -0.0512,-0.748137 -0.625,-2 -2,-2 -1.375,0 -2.01251,1.24595 -2,2 v 3 z"
style="display:inline;fill:#555753;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
style="display:inline;fill:url(#linearGradient11629);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 104,79 v -3 c 0,-3.03985 1.25,-4 4,-4 2.75,0 4,0.9244 4,4 v 3 h -1 v -3 c -0.0512,-0.748137 -0.25,-3 -3,-3 -2.75,0 -3.01251,2.24595 -3,3 v 3 z"
id="path10686"
sodipodi:nodetypes="cczcccczccc"
inkscape:connector-curvature="0" />
<path
style="display:inline;fill:url(#linearGradient11626);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 104,76 c 0,-2 0.5,-4 4,-4 -2.77434,0.380875 -3.5,1.646824 -3.5,4 0,0 0,3 0,3 H 104 Z"
id="path10688"
sodipodi:nodetypes="ccsccc"
inkscape:connector-curvature="0" />
<rect
style="display:inline;fill:url(#linearGradient11623);fill-opacity:1;fill-rule:evenodd;stroke:#745e00;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect10690"
width="13"
height="9"
x="101.5"
y="79.5"
rx="0.87449205"
ry="0.77890939" />
<rect
style="display:inline;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient11620);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.60109289"
id="rect10694"
width="11"
height="7"
x="102.5"
y="80.5"
rx="0.37336442"
ry="0.38806733" />
<rect
ry="0"
rx="0"
y="76"
x="111"
height="3"
width="1"
id="rect11552"
style="display:inline;fill:url(#linearGradient11617);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</g>
<g
id="gicon16">
<path
sodipodi:nodetypes="cczcccczccc"
id="path11522"
d="m 128,83.000001 v -1 c 0,-2.2108 1,-4 4,-4 3,0 4,1.7632 4,4 v 1 h -3 v -1 c -0.0372,-0.5441 0,-1 -1,-1 -1,0 -1.0091,0.4516 -1,1 v 1 z"
style="display:inline;fill:#555753;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
style="display:inline;fill:url(#linearGradient11603);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 129,83.000001 v -1 c 0,-2.2108 1,-3 3,-3 2,0 3,0.7632 3,3 v 1 h -1 v -1 c -0.0372,-0.5441 0,-2 -2,-2 -2,0 -2.0091,1.4516 -2,2 v 1 z"
id="path11524"
sodipodi:nodetypes="cczcccczccc"
inkscape:connector-curvature="0" />
<path
style="display:inline;fill:url(#linearGradient11600);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
d="m 129,82.000001 c 0.0753,-1.637 0,-3 3,-3 -2.0177,0.277 -2.4566,0.8767 -2.4566,2.5881 0,0 -0.0503,2.1212 -0.0503,2.1212 H 129 Z"
id="path11526"
sodipodi:nodetypes="ccsccc"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="ccsccc"
id="path11548"
d="M 129,81.769231 C 129,80.5 129.5,79 132.5,79 c -2.5,0 -3.0625,1.140109 -3.0625,2.769231 0,0 0,1.730769 0,1.730769 H 129 Z"
style="display:inline;fill:url(#linearGradient11597);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
inkscape:connector-curvature="0" />
<rect
style="display:inline;fill:url(#linearGradient11594);fill-opacity:1;fill-rule:evenodd;stroke:#745e00;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect11528"
width="9"
height="7.0001221"
x="127.5"
y="83.499878"
rx="0.6359942"
ry="0.56647956" />
<rect
style="display:inline;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient11591);stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.60109289"
id="rect11532"
width="7"
height="5"
x="128.5"
y="84.5"
rx="0.27153775"
ry="0.28223079" />
<rect
style="display:inline;fill:url(#linearGradient11588);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect11530"
width="1"
height="1"
x="134"
y="82"
rx="0"
ry="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -0,0 +1,398 @@
<?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="150"
height="100"
id="icon"
sodipodi:version="0.32"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
version="1.0"
sodipodi:docname="track-unlocked.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<title
id="doctitle">Icon: track-unlocked</title>
<defs
id="defsz">
<linearGradient
id="linearGradient9845">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop9847" />
<stop
style="stop-color:#ffffff;stop-opacity:0.49484536;"
offset="1.0000000"
id="stop9849" />
</linearGradient>
<linearGradient
id="linearGradient2092">
<stop
id="stop2094"
offset="0"
style="stop-color:#fff7b0;stop-opacity:1;" />
<stop
style="stop-color:#ffec41;stop-opacity:1.0000000;"
offset="0.20999999"
id="stop2098" />
<stop
id="stop43205"
offset="0.83999997"
style="stop-color:#e2cc00;stop-opacity:1;" />
<stop
id="stop2100"
offset="1"
style="stop-color:#c3af00;stop-opacity:1;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient12071">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop12073" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop12075" />
</linearGradient>
<linearGradient
id="linearGradient10672">
<stop
id="stop10674"
offset="0.0000000"
style="stop-color:#cad0c6;stop-opacity:1.0000000;" />
<stop
style="stop-color:#eaece9;stop-opacity:1.0000000;"
offset="0.5"
id="stop10676" />
<stop
id="stop10678"
offset="1.0000000"
style="stop-color:#c5cbc0;stop-opacity:1.0000000;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient9845"
id="linearGradient13842"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.2119237,0,0,0.2489726,128.917,78.6745)"
x1="10.907269"
y1="25.002281"
x2="30.875446"
y2="36.127281" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient12071"
id="linearGradient13845"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.9999999,0,0,0.2052368,120,78.4848)"
x1="11.5"
y1="20.579729"
x2="11.779029"
y2="14.259961" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2092"
id="linearGradient13848"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.2503422,0,0,0.3116539,128.1125,76.3112)"
x1="6.72682"
y1="32.161697"
x2="40.938126"
y2="32.161697" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient12071"
id="linearGradient13851"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.5684536,0,0,0.2215573,119.747,78.1453)"
x1="14.217941"
y1="6.8795347"
x2="17.859085"
y2="3.9566603" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient10672"
id="linearGradient13854"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.2784349,0,0,0.2809058,122.2961,76.6251)"
x1="16.894075"
y1="1.3346111"
x2="24.077082"
y2="19.134172" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient10672"
id="linearGradient12006"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.382848,0,0,0.3862455,93.78214,68.859513)"
x1="16.894075"
y1="1.3346111"
x2="24.077082"
y2="19.134172" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient12071"
id="linearGradient12008"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.7816237,0,0,0.3586619,90.277125,70.741337)"
x1="14.217941"
y1="6.8795347"
x2="17.859085"
y2="3.9566603" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient12071"
id="linearGradient12010"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.9999999,0,0,0.3654315,95,70.960525)"
x1="11.5"
y1="20.579729"
x2="11.779029"
y2="14.259961" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2092"
id="linearGradient12012"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.3442205,0,0,0.4285241,101.90469,68.4279)"
x1="6.0871158"
y1="31.67173"
x2="40.94849"
y2="31.67173" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient9845"
id="linearGradient12014"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.2913951,0,0,0.3423373,103.01101,71.677437)"
x1="10.907269"
y1="25.002281"
x2="30.875446"
y2="36.127281" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="8"
inkscape:cx="75"
inkscape:cy="50"
inkscape:document-units="px"
inkscape:current-layer="artwork"
showgrid="false"
inkscape:snap-nodes="true"
inkscape:snap-bbox="true"
inkscape:snap-global="true"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1680"
inkscape:window-height="1031"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid13478"
visible="true"
enabled="true"
spacingx="0.5"
spacingy="0.5"
empspacing="2"
originx="0"
originy="0" />
</sodipodi:namedview>
<metadata
id="metadead">
<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>Icon: track-unlocked</dc:title>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
<dc:creator>
<cc:Agent>
<dc:title>Joel Holdsworth</dc:title>
</cc:Agent>
</dc:creator>
<dc:publisher>
<cc:Agent>
<dc:title>Lumiera.org</dc:title>
</cc:Agent>
</dc:publisher>
<dc:description>prepared for Lumiera build :: Icon rendering</dc:description>
<dc:date>2008</dc:date>
<dc:identifier>icon:track-unlocked</dc:identifier>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
<cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="artwork"
inkscape:label="artwork:track-unlocked"
style="display:inline">
<g
inkscape:groupmode="layer"
id="layerp"
inkscape:label="plate#1"
style="display:none"
sodipodi:insensitive="true">
<rect
id="bbox24"
x="96"
y="68"
width="24"
height="24"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox22"
x="97"
y="69"
width="22"
height="22"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
<rect
id="bbox16"
x="124"
y="76"
width="16"
height="16"
style="fill:black;fill-opacity:0.5;stroke:#5a8fb2;stroke-opacity:1;stroke-width:0.1"
sodipodi:insensitive="true" />
</g>
<g
id="gicon24">
<g
id="g11991">
<path
inkscape:connector-curvature="0"
style="display:inline;fill:#555753;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 98,80 v -4 c 0,-3.03985 0.875,-5 5,-5 4.125,0 5,1.9244 5,5 v 4 h -3 v -4 c -0.0512,-0.748137 -0.625,-2 -2,-2 -1.375,0 -2.01251,1.24595 -2,2 v 4 z"
id="path10684"
sodipodi:nodetypes="cczcccczccc" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="cczcccczccc"
id="path10686"
d="m 99,79 v -3 c 0,-3.03985 1.25,-4 4,-4 2.75,0 4,0.9244 4,4 v 3 h -1 v -3 c -0.0512,-0.748137 -0.25,-3 -3,-3 -2.75,0 -3.01251,2.24595 -3,3 v 3 z"
style="display:inline;fill:url(#linearGradient12006);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccsccc"
id="path10688"
d="m 99,76 c 0,-2 0.5,-4 4,-4 -2.77434,0.380875 -3.5,1.646824 -3.5,4 0,0 0,3 0,3 H 99 Z"
style="display:inline;fill:url(#linearGradient12008);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="display:inline;fill:url(#linearGradient12010);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect11552"
width="1"
height="3"
x="106"
y="76"
rx="0"
ry="0" />
</g>
<rect
style="display:inline;fill:url(#linearGradient12012);fill-opacity:1;fill-rule:evenodd;stroke:#745e00;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect10690"
width="13"
height="9"
x="103.5"
y="79.5"
rx="0.87449205"
ry="0.77890939" />
<rect
style="display:inline;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient12014);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.60109289"
id="rect10694"
width="11"
height="7"
x="104.5"
y="80.5"
rx="0.37336442"
ry="0.38806733" />
</g>
<g
id="gicon16">
<path
style="fill:#555753;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 125,84 v -2 c 0,-2.2108 1,-4 4,-4 3,0 4,1.7632 4,4 v 1 h -3 v -1 c -0.0372,-0.5441 0,-1 -1,-1 -1,0 -1.0091,0.4516 -1,1 v 2 z"
id="path10680"
sodipodi:nodetypes="cczcccczccc"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="cczcccczccc"
id="path9982"
d="m 126,83 v -1 c 0,-2.2108 1,-3 3,-3 2,0 3,0.7632 3,3 v 1 h -1 v -1 c -0.0372,-0.5441 0,-2 -2,-2 -2,0 -2.0091,1.4516 -2,2 v 1 z"
style="fill:url(#linearGradient13854);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="ccsccc"
id="path9984"
d="M 126,81.5481 C 126.0753,80.1577 126,79 129,79 c -2.0177,0.2353 -2.4566,0.7447 -2.4566,2.1983 0,0 -0.0503,1.8017 -0.0503,1.8017 H 126 Z"
style="fill:url(#linearGradient13851);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
inkscape:connector-curvature="0" />
<rect
ry="0.56647956"
rx="0.6359942"
y="83.499878"
x="129.5"
height="7.0001221"
width="9"
id="rect9986"
style="fill:url(#linearGradient13848);fill-opacity:1;fill-rule:evenodd;stroke:#745e00;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
ry="0"
rx="0"
y="80.947632"
x="131"
height="2.0523682"
width="1"
id="rect9988"
style="fill:url(#linearGradient13845);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
ry="0.28223079"
rx="0.27153775"
y="84.5"
x="130.5"
height="5"
width="7.0000005"
id="rect9990"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient13842);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.60109289" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,467 @@
<?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="16"
height="16"
id="svg2677"
sodipodi:version="0.32"
inkscape:version="0.46"
sodipodi:docname="timeline-panel.svg"
version="1.0"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
inkscape:export-filename="/home/joel/workspace/lumiera/lumiera/icons/timeline.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="7.0051041"
inkscape:cy="8.0063517"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1263"
inkscape:window-height="839"
inkscape:window-x="6"
inkscape:window-y="46"
showguides="true"
inkscape:guide-bbox="true">
<inkscape:grid
type="xygrid"
id="grid3237"
visible="true"
enabled="true"
dotted="true"
originy="1px"
originx="1px"
spacingx="0.5px"
spacingy="0.5px"
empspacing="2"
empcolor="#ff00ff"
empopacity="0.25098039" />
<sodipodi:guide
orientation="1,0"
position="-4.7666573,8.4284603"
id="guide5650" />
</sodipodi:namedview>
<defs
id="defs2679">
<linearGradient
inkscape:collect="always"
id="linearGradient5654">
<stop
style="stop-color:#000000;stop-opacity:1"
offset="0"
id="stop5656" />
<stop
id="stop5664"
offset="0.12824202"
style="stop-color:#ffffff;stop-opacity:1" />
<stop
id="stop5662"
offset="0.87204576"
style="stop-color:#ffffff;stop-opacity:1" />
<stop
style="stop-color:#000000;stop-opacity:1"
offset="1"
id="stop5658" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient5633">
<stop
style="stop-color:#2e3436;stop-opacity:1"
offset="0"
id="stop5635" />
<stop
style="stop-color:#555753;stop-opacity:1"
offset="1"
id="stop5637" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient5580">
<stop
style="stop-color:#ad7fa8;stop-opacity:1"
offset="0"
id="stop5582" />
<stop
style="stop-color:#5c3566;stop-opacity:1"
offset="1"
id="stop5584" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient5572">
<stop
style="stop-color:#888a85;stop-opacity:1"
offset="0"
id="stop5574" />
<stop
style="stop-color:#555753;stop-opacity:1"
offset="1"
id="stop5576" />
</linearGradient>
<inkscape:perspective
id="perspective2685"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 526.18109 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5572"
id="linearGradient5578"
x1="0"
y1="4.5"
x2="16"
y2="4.5"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0,1)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5580"
id="linearGradient5586"
x1="5"
y1="5"
x2="11"
y2="10"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0,1)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5580"
id="linearGradient5590"
gradientUnits="userSpaceOnUse"
x1="5"
y1="5"
x2="11"
y2="10"
gradientTransform="translate(7,1)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5580"
id="linearGradient5594"
gradientUnits="userSpaceOnUse"
x1="5"
y1="5"
x2="11"
y2="10"
gradientTransform="translate(-7,1)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5633"
id="linearGradient5639"
x1="16"
y1="2.5"
x2="0"
y2="2.5"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0,1)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5654"
id="linearGradient5660"
x1="0"
y1="9"
x2="16"
y2="9"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5654"
id="linearGradient5682"
gradientUnits="userSpaceOnUse"
x1="0"
y1="9"
x2="16"
y2="9" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5654"
id="linearGradient5685"
gradientUnits="userSpaceOnUse"
x1="0"
y1="9"
x2="16"
y2="9" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5580"
id="linearGradient5687"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(7,1)"
x1="5"
y1="5"
x2="11"
y2="9.5" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5572"
id="linearGradient5689"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0,1)"
x1="0"
y1="4.5"
x2="16"
y2="4.5" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5580"
id="linearGradient5691"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-7,1)"
x1="5"
y1="5"
x2="11"
y2="10" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5633"
id="linearGradient5693"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0,1)"
x1="16"
y1="2.5"
x2="0"
y2="2.5" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5633"
id="linearGradient5696"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0,1)"
x1="16"
y1="2.5"
x2="0"
y2="2.5" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5580"
id="linearGradient5699"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-7,1)"
x1="5"
y1="5"
x2="11"
y2="10" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5580"
id="linearGradient5702"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(7,1)"
x1="5"
y1="5"
x2="11"
y2="9.5" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5572"
id="linearGradient5707"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.8888889,0,1.3333333)"
x1="0"
y1="4.5"
x2="16"
y2="4.5" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5580"
id="linearGradient5711"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(1,1)"
x1="5"
y1="5"
x2="11"
y2="9.5" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5580"
id="linearGradient5715"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-5,1)"
x1="5"
y1="5"
x2="11"
y2="9.5" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5580"
id="linearGradient5734"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(1,1)"
x1="5"
y1="5"
x2="11"
y2="9.5" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5580"
id="linearGradient5738"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-5,1)"
x1="5"
y1="5"
x2="11"
y2="9.5" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5654"
id="linearGradient5753"
gradientUnits="userSpaceOnUse"
x1="0"
y1="9"
x2="16"
y2="9" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5654"
id="linearGradient2427"
gradientUnits="userSpaceOnUse"
x1="0"
y1="9"
x2="16"
y2="9" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5580"
id="linearGradient2430"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-5,1)"
x1="5"
y1="5"
x2="11"
y2="9.5" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5580"
id="linearGradient2433"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(1,1)"
x1="5"
y1="5"
x2="11"
y2="9.5" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5633"
id="linearGradient2436"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0,1)"
x1="16"
y1="2.5"
x2="0"
y2="2.5" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5580"
id="linearGradient2439"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(7,1)"
x1="5"
y1="5"
x2="11"
y2="9.5" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5572"
id="linearGradient2444"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.8888889,0,1.3333333)"
x1="0"
y1="4.5"
x2="16"
y2="4.5" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5654"
id="linearGradient2467"
gradientUnits="userSpaceOnUse"
x1="0"
y1="9"
x2="16"
y2="9" />
<mask
maskUnits="userSpaceOnUse"
id="mask2463">
<rect
style="fill:url(#linearGradient2467);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:1, 1;stroke-dashoffset:0"
id="rect2465"
width="16"
height="16"
x="0"
y="0" />
</mask>
</defs>
<metadata
id="metadata2682">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Layer 1">
<g
id="g2456"
mask="url(#mask2463)">
<path
id="rect3249"
d="M 0 4 L 0 5 L 0 6 L 0 10 L 0 11 L 0 12 L 16 12 L 16 11 L 15 11 L 15 10 L 16 10 L 16 6 L 15 6 L 15 5 L 16 5 L 16 4 L 0 4 z M 1 5 L 2 5 L 2 6 L 1 6 L 1 5 z M 3 5 L 4 5 L 4 6 L 3 6 L 3 5 z M 5 5 L 6 5 L 6 6 L 5 6 L 5 5 z M 7 5 L 8 5 L 8 6 L 7 6 L 7 5 z M 9 5 L 10 5 L 10 6 L 9 6 L 9 5 z M 11 5 L 12 5 L 12 6 L 11 6 L 11 5 z M 13 5 L 14 5 L 14 6 L 13 6 L 13 5 z M 1 10 L 2 10 L 2 11 L 1 11 L 1 10 z M 3 10 L 4 10 L 4 11 L 3 11 L 3 10 z M 5 10 L 6 10 L 6 11 L 5 11 L 5 10 z M 7 10 L 8 10 L 8 11 L 7 11 L 7 10 z M 9 10 L 10 10 L 10 11 L 9 11 L 9 10 z M 11 10 L 12 10 L 12 11 L 11 11 L 11 10 z M 13 10 L 14 10 L 14 11 L 13 11 L 13 10 z "
style="fill:url(#linearGradient2444);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none" />
<rect
style="fill:url(#linearGradient2439);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none"
id="rect5588"
width="5"
height="4"
x="12"
y="6"
ry="0" />
<path
sodipodi:nodetypes="cccccccccc"
d="M 0,3 L 0,4 L 16,4 L 16,3 L 0,3 z M 0,12 L 0,13 L 16,13 L 16,12 L 0,12 z"
style="fill:url(#linearGradient2436);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path5616" />
<rect
ry="0"
y="6"
x="6"
height="4"
width="5"
id="rect5732"
style="fill:url(#linearGradient2433);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none" />
<rect
style="fill:url(#linearGradient2430);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none"
id="rect5736"
width="5"
height="4"
x="0"
y="6"
ry="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

15
doc/.gitignore vendored Normal file
View file

@ -0,0 +1,15 @@
*.html
user/**/*.html
devel/rfc*/**/*.html
devel/draw/**/*.png
user/**/*.html
/broken_links
/documentation
/css
/js
/page.conf
/images
/menu.html
.*
*~

2
doc/DIR_INFO Normal file
View file

@ -0,0 +1,2 @@
documentation
source for documentation and in some cases generated documentation in its own subdirs

16
doc/SConscript Normal file
View file

@ -0,0 +1,16 @@
# -*- python -*-
##
## SConscript - SCons buildscript for Documentation
##
Import('env')
doxydoc = env.Doxygen('devel/Doxyfile')
# env.Install(dir = '$DESTDIR/share/doc/lumiera$VERSION/devel', source=documentation)
env.Clean (doxydoc, doxydoc + ['devel/,doxylog','devel/doxygen-warnings.txt'])
Export('doxydoc')

1
doc/design/DIR_INFO Normal file
View file

@ -0,0 +1 @@
design and concepts

View file

@ -0,0 +1,148 @@
The Application : Start-up and Subsystems
=========================================
:Date: 2009
:Author: Ichthyo
//MENU: label Start-up
.the purpose of »Application-main«
Lumiera is envisioned as a heavyweight yet coherent »**Application**« -- not so much
as platform, framework or operating system. And, in accordance with this focus, we
place no emphasis on possible configuration changes and state transitions within
the running application _as a whole._ And, while in fact it is possible to close
and load a new Session, most of the time we assume the application just to be
``up and running'' -- all required services to be available and interfaces to
be accessible. Without doubt, these are simplifications, but serve us well
to cut down complexity -- yet still there needs to be one dedicated realm
to deal with these specific concerns of configuration, dependency and lifecyle.
The Application Realm
---------------------
So we treat all these concerns within a small and self contained structure, clearly
set apart from all the other layers, services and subsystems. This dedicated
_Application Realm_ is organised around the ``Application main object''.footnote:[
This is the singleton `lumiera::AppState`, which is triggered by the `main` function
of the Lumiera Application. The sourcecode is kept in a separate folder 'src/common'
and linked into the shared library 'liblumieracommon.so']
It serves the purpose of pulling up and tearing down the application in a controlled
fashion. And additionally, it provides the Interface and Config core services.
The act of building or tearing down this core realm and main object is what creates
the *Lifecycle* of the application. This is a succession of ``lifecycle phases'' --
and almost all activities happen within the _operational phase,_ when everything
is ``up and running'' or ``just available''.
Subsystems
~~~~~~~~~~
However, initially the application needs to be brought up, and at the end, all
parts need to be unwound cleanly. To organise this process, we identify a limited
number of *Subsystems* within the Application, which are more or less independent.
Each link:{ldoc}/design/architecture/Subsystems.html[Subsystem] is self contained
and groups some other parts and services, which typically work together and may
be mutually dependent. These subsystems represent a grouping, applied for the purpose
of starting and stopping the application in a regular way; they rather do not
correspond 1:1 to a layer, an interface, a class or a plugin. As a matter of fact,
they are _rather irrelevant_ outside the mentioned »Application realm«. A subsystem
may depend on other subsystems, which comprises a clear startup- and shutdown-ordering.
However, once the application is in normal operational mode, the subsystems turn
into a passive, guarding and managing role; the activities relevant for the
application's purpose rather rely on components, interfaces, services, all
aggregated into the three Layers »Stage«, »Steam« and »Vault«.
__We expect the following subsystems to be built eventually:__ +
Engine, Session, PlayOut, GUI, Script runner, Renderfarm node.
Organisation of Subsystems
^^^^^^^^^^^^^^^^^^^^^^^^^^
Not all subsystems need to be started for any use of the application. A script-driven
use, or a renderfarm node does not need a GUI. So there is an overall global operation
mode of the application, controlled through the launching options, and determined during
the startup phase. It is the responsibility of the _Application main object_ to
pull up required functionality, which in turn might result in pulling up
further subsystems as dependencies.
Subsystems are defined by implementing the interface `lumiera::Subsys`, which acts
as façade to conduct the lifecycle, find out about dependencies and shut down
the subsystem in the end. So this interface, together with the _Subsystem Runner,_
define a lifecycle protocol; each subsystem is free to implement this as it
sees fit. Typically, this façade will load plugins, register and provide further
_business interfaces,_ and especially set up the _Layer separation interfaces_
which canalise any communication going on between the layers.
The *GUI Façade* is special, while in compliance with this protocol. The actual
UI is loaded from a plug-in at runtime,footnote:[This corresponds to the vision
to allow for different Lumiera UI's -- maybe to support different working styles
or target audiences. If such is actually feasible remains to be clarified as of
2020; even while decoupled on a technical level, the session still needs to make
a lot of assumptions regarding the UI's capabilities and needs.]
and so the implementation of this façade needs to reside in the application core
realm; it will start a `GuiRunner` to load and activate the GUI plug-in, which
then in turn has to open the public _GUI Notification_ façade. The latter is
one of the _Layer separation interfaces_ and comprises the actual way for the
lower layers to activate and interact with the user interface.
Parallelism
~~~~~~~~~~~
Actually this scheme builds on the assumption that starting each subsystem will
not block the overall start/main/shutdown thread. Any subsystem is supposed
to spawn its own control/event threads if necessary. The Lumiera application
works fundamentally asynchronous. The user interface operates single threaded,
in accordance to long established best practices of UI programming. However,
any user interaction is translated into commands, sent down into the session
and handled there one by one. The result of processing such commands will be
pushed back up into the UI later and detached from the immediate interaction.
Likewise, the re-rendering caused by changes in the session is carried out
within the engine independently, relying on worker jobs and a thread pool.
Initialisation and Lifecycle
----------------------------
After some discussion,footnote:[See the
link:{ldoc}/devel/rfc/GlobalInitialization.html[GlobalInitialisation] RfC
from spring 2008. In the beginning, we all agreed to ``keep matters simple''
and build an `init()` function within one central piece of code everyone knows
and hooks into. However, while the outline of the application emerged, there
was a tension between the concern about _over-engineering_ versus the concern
about _tangled and unmanageable complexity._ At some point, an alternative
implementation based on lifecycle callbacks was elaborated, which then turned
into the solution described here. Lumiera then ceased to be the typical UI
application started by GTK, and the existing GTK code was retrofitted to
launch from within a plug-in.]
the design leaned toward loosely coupled parts and a formal lifecycle; which
saves us from investigating and coding up the various interdependencies
explicitly. Rather, the parts of the application have to comply to
link:{ldoc}/design/architecture/Subsystems.html#lifecycle[Lifecycle Phases],
and each part has to care for its own state transitions, invoked through
_lifecycle callbacks._ We can distinguish two distinct models how to deal
with lifecycle, and both are equally acceptable:
- Assuming that operations happen in response to some client's request,
this activation should go through a _service interface._ Interfaces
can be opened and closed in Lumiera, and this is accomplished by
hooking them up below some subsystem.
- However, some parts carry out continuous activities, and in that case
a _lifecycle hook_ should be registered, to limit activities to the
appropriate lifecycle phase.
Application Start
~~~~~~~~~~~~~~~~~
* some fundamental language-level facilities will be prepared during
_static initialisation._ At some point, execution enters `main(argc,arvv)`.
* `AppState::init()` brings up the plugin loader and opens the config-interface.
* ...followed by triggering *ON_GLOBAL_INIT*
* the main thread then pulls up the subsystems (`AppState::maybeStart(subsystem)`),
according to the command line options.
* within each subsystem, façade interfaces will be opened through the
interface/plug-in system.
* At this point, the GUI plug-in is loaded and launched, the windows created,
the UI event loop starts and the application becomes live.
* shutdown or failure of _any given subsystem_ initiates the shutdown sequence
by requesting all other running subsystems to terminate. In the typical case,
the UI subsystem will trigger this shutdown sequence, in response to closing
the main window.
* there is an *ON_GLOBAL_SHUTDOWN* event, which can be used for normal cleanup;
In case of an emergency exit, the *ON_EMERGENCY_EXIT* event is triggered alternatively.
* the AppState destructor tears down the core systems (config-interface and pluginloader).
* we establish a policy to _prohibit any non-local and non-trivial activities_ during the
tear-down phase after leaving the `main()` function.

View file

@ -0,0 +1,15 @@
Lumiera Design: Application and Session Configuration
=====================================================
*TODO* : 'write design document'
The Lumiera application uses two quite different sources for configuration
- individual __settings values__ can be loaded from an application- and user configuration in the conventional way
- various facilities, especially in the Steam-Layer, base the actual behavour on __queries__, which are
to be resolve employing a rules based system '(planned)'. Configuration rules will be provided by the
application (defaults), a session template and rules stored in the actual session.
-> see also the link:{ldoc}/technical/vault/ConfigLoader.html[Config Loader brainstorming from 2008] (implementation details)

View file

@ -0,0 +1,10 @@
Design Documents: Application Framework
=======================================
// Menu : prepend child ApplicationStart
* link:Config.html[Configuration]
* link:plugin_loader.html[Plugin Loader]
* link:ApplicationStart.html[Application Subsystems and Lifecycle]

View file

@ -0,0 +1,5 @@
Lumiera Design: Plugin system
=============================
Eventually, this will have design documentation for the Plugin system.

View file

@ -0,0 +1,36 @@
Lumiera Architecture: Executive Summary
=======================================
:Author: Hermann Voßeler
:Email: <Ichthyostega@web.de>
:Date: Sept 2010
//Menu: label Summary
.Three Layers
Besides the (obvious) separation in GUI frontend and render engine, editing core and application logic
are treated separately. Besides enforcing clearly defined interfaces, the ability for script driven
``headless'' operation and extensibility by plug-ins are deeply rooted in the overall design.
.Strong Separation
High-level and low-level realm remain cleanly separated, relying on a compiler-like translation mechanism.
This way, each part can be optimised for its purpose. The GUI exposes a feature-rich session model close
to the problem domain, while the engine operates on a performance optimised render nodes graph.
.Scheduling Micro Operations
High performance calculations in the engine are organised as micro tasks to be scheduled,
allowing for adaptation to current and future hardware, expected to operate increasingly parallelised.
.Intelligent IO
The engine is backed by an sophisticated frame cache and self adjusting I/O manager for maximising throughput
and bandwidth use.
.Stream Type System
Instead of relying on a single media framework, data streams are abstracted and classified, allowing to
handle most wiring, detection of possible connections and conversion automatically.
.Rules Based Configuration
Rather than driven by hard wired default behaviour or tedious manual operation, control flow is guided by
a set of rules shaped configuration, which scales better to large and complicated projects. Queries are
issued at decision points, allowing to build up a work environment customised and tailored for the needs
of specific projects.

View file

@ -0,0 +1,102 @@
External Tree Description
=========================
:Author: Ichthyostega
:Date: Fall 2015
****************
_to symbolically represent hierarchically structured elements, without actually implementing them._
****************
The purpose of this ``external'' description is to remove the need of a central data model to work against.
We consider such a foundation data model as a good starting point, yet harmful for the evolution of any
larger structure to be built. According to the *subsidiarity principle*, we prefer to turn the working
data representation into a local concern. Which leaves us with the issue of collaboration.
Any collaboration requires, as an underlying, some kind of common understanding.
And any formalised, mechanical collaboration requires to represent that common point of attachment --
at least as _symbolic representation._ The »External Tree Description« is shaped to fulfil this need:
_in theory,_ the whole field could be represented, symbolically, as a network of hierarchically
structured elements. Yet, _in practice,_ all we need is to conceive the presence of such a representation,
as a backdrop to work against. And we do so -- we work against that symbolic representation,
by describing *changes* made to the structure and its elements. Thus, the description of changes,
the link:{ldoc}/technical/library/DiffFramework.html[diff language], refers to and partially embodies
such symbolically represented elements and relations.
Elements, Nodes and Records
---------------------------
We have to deal with _entities and relationships._
Entities are considered the building blocks, the elements, which are related by directional links.
Within the symbolic representation, elements are conceived as *generic nodes* (`GenNode`),
while the directed relations are impersonated as being attached or rooted at the originating side,
so the target of a relation has no traces or knowledge of being part of that relation. Moreover, each
of our nodes bears a _relatively clear-cut identity._ That is to say, within the relevant scope in question,
this identity is unique. Together, these are the building blocks to represent any *graph*.
For practical purposes, we have to introduce some distinctions and limitations.
- we have to differentiate the generic node to be either a mere data element, or an *object-like record*
- the former, a mere data element, is considered to be ``just data'', to be ``right here'' and without
further meta information. You need to know what it is to deal with it.
- to the contrary, a Record has an associated, symbolic and typed ID, plus it can potentially be associated with
and thus relate to further elements, with the relation originating at the Record.
- and indeed we distinguish two different kinds of relations possibly originating from a Record:
* *attributes* are known by-name; they can be addressed through this name-ID as a key,
while the value is again a generic node, possibly even another record.
* *children* to the contrary can only be enumerated; they are considered to be within (and form)
the *scope* of the given record (``object'').
And there is a further limitation: The domain of possible data is fixed, even hard wired.footnote:[
Implementation-wise, this turns the data within the generic node into a »Variant« (typesafe union).]
Basically, this opens two different ways to _access_ the data within a given GenNode:
either you know the type to expect beforehand.footnote:[and the validity of this assumption
is checked on each access; please recall, all of this is meant for symbolic representation,
not for implementation of high performance computing]
Or we offer the ability for _generic access_ through a *double dispatch* (»Visitor«).
The latter includes the option to handle just some of the possible content types and
to ignore the other.footnote:[making the variant visitor a _partial function_ --
as in any non exhaustive pattern match]
data elements
~~~~~~~~~~~~~
Basically, we can expect to encounter the following kinds of fundamental data elements
- `int`, `int64_t`, `short`, `char`
- `bool`
- `double`
- `std::string`
- `time::Time`, `time::Offset`, `time::Duration`, `time::TimeSpan`
- `hash::LuidH` (to address and refer to elements known by ID)
- `diff::Record<GenNode>`
The last option is what makes our representation recursive.footnote:[Regarding the implementation,
all these data elements are embedded _inline,_ as values.
With the exception of the record, which, like any `std::vector` implicitly uses heap allocations
for the members of the collection.]
names, identity and typing
~~~~~~~~~~~~~~~~~~~~~~~~~~
It was a design decision that the generic node shall not embody a readable type field,
just a type selector within the variant to hold the actual data elements.
This decision more or less limits the usefulness of simple values as children to those cases,
where all children are of uniform type, or where we agree to deal with all children through variant visitation solely.
Of course, we can still use simple values as _attributes,_ since those are known and addressed by name.footnote:[As
an extension, we could use filtering by type to limit access to some children of type `Record`, since every record
does indeed embody a _symbolic_ type name, an attribute named `"type"`. It must be that way, since otherwise,
records would be pretty much useless as representation for any object like entity.]
The discriminating ID of any `GenNode` can serve as a name, and indeed will be used as the name of an attribute within a record.
This *entry-ID* of the node is comprised of a human readable symbolic part, and a hash ID (`LUID`). The calculation of the latter,
the hash, includes the symbolic ID _and_ a type information. This is what constitutes the full identity -- so two nodes with the
same name but different payload type are treated as different elements.
A somewhat related design question is that of ordering and uniqueness of children.
While attributes -- due to the usage of the attribute node's ID as name-key -- are bound to be unique within a given Record,
children within the scope of a record could be required to be unique too, making the scope a set. And, of course,
children could be forcibly ordered, or just retain the initial ordering, or even be completely unordered.
On a second thought, it seems wise not to impose any guarantees in that regard, beyond the simple notion of retaining
an initial sequence order, the way a ``stable'' sorting algorithm does. All these more specific ordering properties
can be considered the concern of some specific kinds of objects -- which then just happen to ``supply'' a list of children
for symbolic representation as they see fit.

View file

@ -0,0 +1,322 @@
Layers -- Subsystems -- Lifecycle
=================================
:Author: Hermann Voßeler
:Email: <Ichthyostega@web.de>
:Date: 2018
:Toc:
Terminology
-----------
Layer::
A conceptual realm within the application in order to group related topics and to build
high-level structures in terms of low-level structures. Layers are located above/below
each other and may depend _solely_ on lower layers. The Application may be operated in
a partial layer configuration with only some lower layers present. Each layer deals
with distinct topics and has its own style. In Lumiera, we distinguish three layers
+
* Stage Layer -> Interaction
* Steam Layer -> Processing
* Vault Layer -> Data manipulation
Subsystem::
A runtime entity which serves as anchor point and framework to maintain a well defined lifecycle.
While layers are conceptual realms, subsystems can actually be started and stopped, and their
dependencies are represented as data structure. A subsystem typically starts one or several
primary components, which might spawn a dedicated thread and instantiate further components
and services.
Service::
A component within some subsystem is called a _Service_
+
--
* provided that it exposes an interface with an associated contract
(informal rules about usage pattern and expectations)
* and given that it accepts invocations from arbitrary other components
without mutual interdependency or hard coded knowledge about that other part.
--
+
The service lifecycle is tied to the lifecycle of the related subsystem; whenever the subsystem is ``up and running'',
any contained services can be accessed and used. Within Lumiera, there is no _service broker_ or any similar kind
of elaborate _service discovery_ -- rather, services are accessed *by name*, where ``name'' is the _type name_
of the service interface.
Dependency::
A usage relation at implementation level and thus a local prerequisite of an individual component. A
dependency is something we need in order to complete the task at hand, yet a dependency lies beyond that
task and is satisfied by means outside the scope and theme of this actual task. Consequently, a dependency
is not introduced or provided by the local task or part of the task, rather the task at hand is the reason
why some other entity dealing with it needs to _request_ or _pull_ that dependency in to accomplish the
task at hand. So essentially, dependencies are accessed on-demand. Dependencies might be satisfied by
other components or services, and typically the user (consumer) of a dependency just relies on the
corresponding interface and remains agnostic with respect to the dependency's actual implementation,
data or lifecycle details.
Subsystems
----------
As a coherent part of the application, a subsystem can be started into running state. Several subsystems
can reside within a single layer, which leads to rather tight coupling. We do not define boundaries between
subsystems in a strict way (as we do with layers) -- rather some component is associated with a subsystem
when it relies on services of the subsystem to be ``just available''. However, the grouping into subsystems
is often also a thematic one, and related to a specific abstraction level. To give an example, the Player
deals with _calculation streams,_ while the engine handles individual _render jobs,_ which together form
a calculation stream. So there is a considerable grey area in between. Any code related with defining and
then dispatching frame jobs needs at least some knowledge about the presence of calculation streams; yet
it depends and relies on the scheduling service of the engine. In the end, it remains a question of
architecture to keep those dependency chains ordered in a way to form a one-way route: when we start
the engine, it must not instantiate a component which _requires the player_ in order to be operative.
Yet we can not start the player without having started the engine beforehand; if we do, its services
will throw exceptions on first use, due to missing dependencies.
However, subsystems as such are not dynamically configured. This was a clear cut design decision (and the
result of a heated debate within the Lumiera team at that time). We do _not expect_ to load just some plug-in
dynamically, inserted via an UI-action at runtime, which then installs a new subsystem and hooks it into the
existing architecture. The flexibility lies in what we can do with the _contents_ of the session -- yet the
application itself is not conceived as set of Lego(TM) bricks. Rather, we identify a small number of coherent
parts of the application, each with its own theme, style, relations and contingencies.
Engine
~~~~~~
The Engine performs small pieces of work known as _render jobs,_ oriented towards a deadline,
without much knowledge about the purpose of those jobs, or their further interconnections.
And thus the purpose of the *Engine Subsystem* is to provide a thread pool and activate
the scheduling mechanism. Consequently, this subsystem belongs into the »Vault Layer«
_[yellow-background]#this part of the system is barely drafted as of 2020#_
Player
~~~~~~
The *PlayOut Subsystem* is located above the Engine and belongs into the »Steam Layer« -- and contrary
to the Engie (which handles individual jobs), the player creates and organises _calculation streams._
_[yellow-background]#as of 2020, the actual components to form the player need to be worked out#_ +
_^however, a fair amount of the services for dispatching streams into jobs has been prototyped^_
Session
~~~~~~~
The user performs editing activities within the »Session« -- which is a data structure with associated
methods for manipulation. There is a `Session` object and a `SessionManager` to load and save session
data and conduct the _session lifecycle._ However, all of this needs to be distinguished from the
*Session Subsystem* -- which in essence is a dispatcher thread to receive, enqueue and finally
trigger the _session commands,_ as sent from the GUI or the script runner. These activities are
conducted and controlled by the `SteamDispatcher`, which also cares for triggering the _Builder,_
whenever new commands have been dispatched. Moreover, when instantiating the `DispatcherLoop`,
also the `SessionCommand` façade is opened, which is the primary »Steam Layer« interface.footnote:[
Note the relation between Session-the-datastructure and Session-the-subsystem is rather indirect:
the _dispatching_ of commands is blocked, unless there is also a session-datastructure loaded
and fully configured. However, a running dispatcher loop is not a prerequisite for opening
a session -- just without a running dispatcher, commands will queue up and nothing else will happen.]
_[green]#as of 2020, this subsystem is operative and commands can be dispatched#_ +
_^...while the session data structure as such is mostly still a skeleton...^_
User Interface
~~~~~~~~~~~~~~
The Lumiera GUI is loaded as self-contained plug-in, which is the task of the *GUI Subsystem*.
As can be expected, this is a rather convoluted process, while the actual name of the UI plug-in module
to load is configured in the 'setup.ini', which has been evaluated earlier, in the application init phase.
However, as it stands, Lumiera is built with a GTK-3 interface, and within the corresponding plug-in module
`gtk_gui.lum`, the class `GtkLumiera` serves as top-level guard to carry on all further activities,
when triggered from within the subsystem lifecycle to run in a dedicated GUI thread. It will establish
the _UI backbone_ by activating the _UI-Bus_ and building the _UI Manager_ controlling the UI global context.
After these systems are established and connected, the GTK windows can be created and finally control is handed
over to the GTK (GIO) event loop. Whenever this loop terminates, be it regularly, or by exception, application
shutdown is initiated.
The GUI Subsystem is special, insofar it not only attaches to the session interface, but also opens a
_Layer separation interface_ oriented downwards, to be used by the lower layers. This interface -- known
as GUI Notification façade -- serves to populate the UI with actual content, to mark and animate the
tangible elements visible to and manipulated by the user in turn. It is outfitted with a cross-thread
dispatcher mechanism, to forward any invocation as message onto the UI-Bus. This setup allows the
lower layers to address the tangible parts in the UI based on their ID, which previously was given
alongside with the content when populating the structures.
_[green]#as of 2020, this backbone is established and connected in both directions#_ +
_^...while the large part of the actual widgets still remains to be built...^_
Script Runner
~~~~~~~~~~~~~
One of the most fundamental design decisions for Lumiera is that everything can be done without GUI.
Conceptually, this would allow to instantiate a script execution environment with appropriate bindings,
either to conduct operations on an existing session, or to build and render a session from scratch.
Alternatively, also a CLI-style shell-like interface is conceivable.
_[maroon orange-background]#this is a concept without any detailed planning as of 2020#_
Net Node
~~~~~~~~
In variation to the script runner concept, it is conceivable to send instructions to a Lumiera
instance over the net. Expanding on that idea, it would be possible to define a protocol to
distribute the session definitions to slave nodes and then to launch distributed render tasks.
Since Lumiera is built as a self-contained bundle, it is well suited to run within a containerised
environment. However, in the light of current trends towards container orchestration frameworks
like Kubernetes, we should refrain from building to much process management functionality into
the application itself.
_[aqua teal-background]#this is a mere idea, and certainly not a priority as of 2020#_
....
....
Lifecycle
---------
Dependencies and abstraction through interfaces are ways to deal with complexity getting out of hand.
When done well, we can avoid adding _accidental complexity_ -- but essential complexity as such can not
be removed, yet with the help of abstractions it can be raised to another level.footnote:[Irony tags here.
There is a lot of hostility towards abstractions, because it is quite natural to conflate the abstraction
with the essential complexity it has to deal with. It seems compelling to kill the abstraction, in the hope
to kill the complexities as well -- a tremendously effective attitude, as it turns out, especially in practice...]
When components express their external needs by depending on an interface, the immediate tangling at the code level
is resolved. However, someone needs to implement that interface, and this other entity needs to be _available_.
The problem has been shifted, since it is now an architecture level challenge to get those dependency chains
satisfied. A clever way to circumvent this problem rather then to deal with it explicitly, is to rely on a
_lifecycle_ with several _phases._ This is the idea behind the subsystems and the subsystem runner.
. First we define an ordering between the subsystems. The most basic subsystem (the Engine) is started first.
. Within a subsystem, components may be mutually dependent. However, we establish a new rule, dictating that
during the _startup phase_ only local operations within a single component are allowed. Each component must
to be written in such a way, not to rely on the help of anything ``remote'' in order to get its inner workings
up and ready. The component may rely on its members and on other services it _created itself,_ or which it
_owns and manages._
. However, sometimes we _do need to rely_ on a more low-level service in another subsystem or in the
application core.footnote:[A typical example would be the reliance on threading, locking or application
configuration.] -- which then creates a hard dependency on _architecture level_
. Moreover, we ensure that all operational activity is generated by actual work tasks, and that such tasks
in turn may be initiated _solely through official interfaces._ Such interfaces are to be _opened explicitly_
at the end of the startup phase.
. In operational mode, any part of the system can now assume for its dependencies to be ``just available''.
. And finally we establish a further rule to _disallow extended clean-up._ Everything must be written in a
way such that when a task is done, it is _really done_ and settled. (Obviously there are some fine points
to consider here, like caching or elaborate buffer and I/O management). The rationale is that after leaving
the operational phase at the end of `main()` the application is able to unwind in any arbitrary way.
The problem with emergencies
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This concept has a weak spot however: A catastrophic failure might cause any subsystem to break down immediately.
The handler within the subsystem's primary component will hopefully detect the corresponding exception and signal
emergency to the subsystem runner. Yet the working services of that subsystem are already gone at that point.
And even before other subsystems might get the (emergency) shutdown trigger, some working parts may be failing
catastrophically due to their dependencies being dragged away suddenly.
Lumiera is not written for exceptional resilience or high availability. Our attitude towards such failures can
be summarised as ``Let it crash''. And this is another rationale for the ruling against extended clean-up.
Any valuable work done by the user should be accepted and recorded persistently right away. Actions on the
session are logged, like in a database. The user may still save snapshots, but basically any actual change
is immediately recorded persistently. And thus we may crash without remorse.
Static initialisation and shutdown
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A lot of fine points can be made about when precisely static objects in C\++ will be initialised or destroyed.
However, anything beyond the scope of `main()` is not meant to be used for regular application code. Extended
initialisation, dependency management and decommissioning -- when actually necessary -- should be part of the
application code proper.footnote:[this is established ``best practice'' for good reasons. The interplay of
static lifespan, various translation units and even dynamically loaded libraries together with shared access
tends to becomes intricate and insidious easily. And since, in theory, any static function could use some static
variable residing in another translation unit, it is always possible to construct a situation where objects
are accessed after being destroyed. Typically such objects do not even look especially ``dead'', since the
static storage remains in place and still holds possibly sane values. Static (global) variables, like raw
pointers, allow to subvert the deterministic automatic memory management, which otherwise is one of the
greatest strengths of C++. Whenever we find ourselves developing extended collaborative logic based on
several statics, we should consider to transform this logic into regular objects, which are easier to
test and to reason about. If it really can not be avoided to use such units of logic from a static
context, it should at least be packaged as a single object, plus we should ensure this logic can
only be accessed through a regular (non static) object as front-end. Packaged this way, the most
common and dangerous pitfalls with statics can be avoided.] And since Lumiera indeed allows
for link:{ldoc}/technical/library/Dependencies.html[lazily initialised dependencies], we
establish the policy that *destructors must not rely on dependencies*. In fact, they
should not do any tangible work at all, beyond releasing other resources.
anchor:lifecycle[]
Lifecycle Events
~~~~~~~~~~~~~~~~
The Application as a whole conducts a well defined lifecycle; whenever transitioning to the next phase,
a _Lifecycle Event_ is issued. Components may register a notification hook with the central _Lifecycle Manager_
(see 'include/lifecycle.h') to be invoked whenever a specific event is emitted. The process of registration
can be simplified by planting a static variable of type `lumiera::LifecycleHook`.
WARNING: A callback enrolled this way needs to be callable at the respective point in the lifecycle,
otherwise the application will crash.
`ON_BASIC_INIT`::
Invoked as early as possible, somewhere in the static initialisation phase prior to entering `main()`.
In order to install a callback hook for this event, the client must plant a static variable somewhere.
`AppState`::
This is the Lumiera »Application Object«. It is a singleton, and should be used by `main()` solely.
While not a lifecycle event in itself, it serves to bring up some very fundamental application services:
+
--
- the plug-in loader
- the application configuration
--
+
After starting those services within the `AppState::init()` function,
the event `ON_GLOBAL_INIT` is emitted.
`ON_GLOBAL_INIT`::
When this event occurs, the start-up phase of the application has commenced. The command line was already
parsed and the basic application configuration is loaded, but the subsystems are not yet initialised.
`Subsys::start()`::
By evaluation of the command line, the application object determines what subsystems actually need to
be started; those will receive the `start()` call, prompting them to enter their startup phase, to
instantiate all service objects and open their business façade when ready
`ON_SESSION_START`::
When this hook is activated, the session implementation facilities are available and the corresponding
interfaces are already opened and accessible, but the session itself is completely pristine and empty.
Basic setup of the session can be performed at that point. Afterwards, the session contents will be
populated.
`ON_SESSION_INIT`::
At this point, all specific session content and configuration has already be loaded. Any subsystems
in need to build some indices or to establish additional wiring to keep track of the session's content
should register here.
`ON_SESSION_READY`::
Lifecycle hook to perform post loading tasks, which require an already completely usable and configured
session to be in place. When activated, the session is completely restored according to the defaulted or
persisted definition, and any access interfaces are already opened and enabled. Scripts and the GUI might
even be accessing the session in parallel already. Subsystems intending to perform additional processing
should register here, when requiring fully functional client side APIs. Examples would be statistics gathering,
validation or auto-correction of the session's contents.
`ON_SESSION_CLOSE`::
This event indicates to cease any activity relying on an opened and fully operative session.
When invoked, the session is still in fully operative state, all interfaces are open and the render engine
is available. However, after issuing this event, the session shutdown sequence will be initiated, by detaching
the engine interfaces and signalling the scheduler to cease running render jobs.
`ON_SESSION_END`::
This is the point to perform any state saving, deregistration or de-activation necessary before
an existing session can be brought down. When invoked, the session is still fully valid and functional,
but the GUI/external access has already been closed. Rendering tasks might be running beyond this point,
since the low-level session data is maintained by reference count.
`Subsys::triggerShutdown()`::
While not a clear cut lifecycle event, this call prompts any subsystem to close external interfaces
and cease any activity. Especially the GUI will signal the UI toolkit set to end the event loop and
then to destroy all windows and widgets.
`ON_GLOBAL_SHUTDOWN`::
Issued when the control flow is about to leave `main()` regularly to proceed into the shutdown and
unwinding phase. All subsystems have already signalled termination at that point. So this is the right
point to perform any non-trivial clean-up, since, on a language level, all service objects (especially
the singletons) are still alive, but all actual application activity has ceased.
`ON_EMERGENCY_EXIT`::
As notification of emergency shutdown, this event is issued _instead of_ `ON_GLOBAL_SHUTDOWN`, whenever
some subsystem collapsed irregularly with a top-level exception.
NOTE: all lifecycle hooks installed on those events are _blocking_. This is intentionally so, since any
lifecycle event is a breaking point, after which some assumptions can or can not be made further on.
However, care should be taken not to block unconditionally from within such a callback, since this
would freeze the whole application. Moreover, implementers should be careful not to make too much
assumptions regarding the actual thread of invocation; we only affirm that it will be _that specific_
thread responsible for bringing the global lifecycle ahead at this point.

View file

@ -0,0 +1,212 @@
Time values and Time quantisation
=================================
:Author: Hermann Voßeler
:Email: <Ichthyostega@web.de>
:Date: Spring 2011
//Menu: label Time Quantisation
.Definitions
The term &raquo;Time&laquo; spans a variety of vastly different entities. +
Within a NLE we get to deal with various _flavours of time values._
continuous time::
without any additional assumptions, *points in time* can be specified with
arbitrary precision. The time values are just numbers; the point of reference
and the meaning is implicit. Within Lumiera, time is encoded as integral
number of _micro ticks,_ practically continuous
time distance::
a range of time, a *distance* on the time axis, measured with the same
arbitrary precision as time points. Distances can be determined by
_subtracting_ two time points, consequently they are _signed numbers._
offset::
a distance can be used to adjust (offset) a time or a duration: this means
applying a relative change. The _target_ of an offset operation is a time or
duration, while it's _argument_ is a distance (synonymous to offset).
duration::
the length of a time range yields a *time metric*.
+
the duration can be defined as the _absolute value_ of the offset between
start and endpoint of the time range. A duration always abstracts from the
time _when_ this duration or distance happens, the relation to any time scale
remains implicit
time span::
contrary to a mere duration, a *time interval* or time span is actually
_anchored_ at a specific point in time. It can be seen as a _special kind of
duration,_ which explicitly states the information _when_ this time span takes
place.
changing time::
Time values are _immutable,_ like numbers.
+
Only a *time variable* can be changed -- yet some of the special time entities
can recieve link:TimeMutation[mutation messages], allowing e.g. for
adjustments to a time interval selection from the GUI
''''
internal time::
While the basic continuous time values don't imply any commitment regarding
the time scale and origin to be used, actually, within the implementation of
the application, the meaning of time values is uniform and free of
contradictions. Thus effectively there is an *implementation time scale* --
but its scope of validity is _strictly limited to the implementation level of
a single application instance._ It is never exposed and never persisted. It
might not be reproducible over multiple instantiations of the application. The
implementation reserves the right to recalibrate this internal scale. Later,
when Lumiera gains the capability to run within a network of render nodes,
these instance connections will include a negotiation about the internal time
scale, which remains completely opaque to the outer world. This explains, why
`lumiera::Time` instances lack the ability to show their time value beyond
debugging purposes. This is to avoid confusion and to stress their opaque
nature.
wall clock and system time::
The core property of any external real world time is that it is _running_ --
we have to synchronise to an external time source. This implies the presence
of a _running synchronisation process,_ with the authority to adjust the time
base;
+
contrast this to the internal time, which is static and unconnected --
quantised time::
The *act of quantisation* transforms a continuous property into a *discrete*
structure. Prominent examples can be found in the domain of micro physics and
with digital information processing. In a broader sense, any measurement or
_quantification_ also encompasses a quantisation. Regarding time and time
measurement, quantisation means alignment to a predefined *time grid*.
Quantisation necessarily is an _irreversible process_ -- possible
additional information is discarded.
+
Note that quantisation introduces a *time origin* and a *reference scale*
frame count::
within the context of film and media editing, the specification of a *frame number*
is an especially important instance of quantisation.
+
all the properties of quantisation apply indeed to this special case: it is a
time measurement or specification, where the values are aligned to a grid, and
there is a reference time point where the counting starts (origin) and a
reference scale (frames per second). Handling of quantised time values in
Lumiera is defined such as to ensure the presence of all those bits of
information. Without such precautions, operating with bare frame numbers leads
itself to all kinds of confusions, mismatches, quantisation errors and
unnecessary limitations of functionality.
timecode::
Quantisation also is the foundation of all kinds of formalised time specifications
actually even a frame count is some kind of (informal) timecode -- other timecodes
employ a standardised format. //Every// presentation of time values and every
persistent storage and exchange of such values is based on time codes.
Yet quantisation and time code aren't identical: a given quantised time value
typically can be cast into multiple timecode formats.
Patterns for handling quantised time
------------------------------------
When it comes to actually handling quantised time values, several patterns are
conceivable for dealing with the quantisation operation and representing
quantised data. As guideline for judging these patterns, the general properties
of time quantisation, as detailed above, should be taken into account.
Quantising a time value means both _discarding information,_ while at the same
time _adding explicit information_ pertaining the assumptions of the context.
.casual handling
this is rather an frequently encountered *anti pattern*. When reading such
code, the most striking observation is the sense of general unawareness of the
problem, which is then ``discovered'' on a per case base, which leads to
numerous repetitions of the same basic undertakings, but done with individual
treatment of each instance (not so much copy-n-paste). +
Typical code smells:
* the rounding, modulo and subtract-base operations pertinent with scale
handling are seemingly inserted as bugfix
* local code path forks to circumvent or compensate for otherwise hard wired
calculations based on specific ways to invoke a function
* playing strikingly clever tricks or employing heuristics to "figure out" the
missing scale information from accessible context after the fact
* advertising support for some of the conceivable cases as special feature, or
adding it as plugin or extension module with limited scope
* linking parts of the necessary additional information to completely
unrelated other structures, thus causing code tangling and scattering
* result or behaviour of calculations depends on the way things are set up in
a seemingly contingent way, forcing users to stick to very specific procedures
and ordered steps.
.static typing
an analysis of the cases to be expected establishes common patterns and some
base cases, which are then represented by distinct types with well established
conversions. This can be combined with generic programming for the common parts.
Close to the data input, a factory establishes these statically typed values.
.Summary
****************************************************************************
Lumiera uses (fixed) static typing for the plain _time values_, with a class
wrapping a simple 64bit integer as common denominator. The strict typing is
used to enforce a sane conversion path to quantised time values. For these
grid alinged values, and especially for the common time codes, the principle
of _delayed quantisation_ is preferred; the implementation relies on runtime
typing with type erasure, but provides conversion to statically tagged values
for the most important special formats
image:{imgd}/uml.time-entities.png["Time and Time Quantisation in Lumiera"]
****************************************************************************
.tagged values
quantised values are explicitly created out of continuous values by a quantiser
entity. These quantised data values contain a copy of the original data,
adjusted to be exactly aligned with respect to the underlying time grid. In
addition, they carry a tag or ID to denote the respective scale, grid or
timecode system. This tag can be used later on to assess compatibility or to
recast values into another timecode system.
.delayed quantisation
with this approach, the information loss is delayed as long as possible.
Quantised time values are rather treated as promise for quantisation, while the
actual time data remains unaltered. Additionally, they carry a tag, or even a
direct link to the responsible quantiser instance. Effectively, these are
specialised time values, instances of a sub-concept, able to stand-in for
general time values, but exposing additional accessors to get a quantised value.
discussion
~~~~~~~~~~
For Lumiera, the static typing approach is of limited value -- it excels when
values belonging to different scales are actually treated differently. There are
such cases, but rather on the data handling level, e.g. sound samples are always
handled block wise. But regarding time values, the unifying aspect is more
important, which leads to prefering a dynamic (run time typed) approach, while
_erasing_ the special differences most of the time. Yet the dynamic and open
nature of the Lumiera high-level model favours the delayed quantisation pattern;
the same values may require different quantisation depending on the larger model
context an object is encountered in. This solution might be too general and
heavy weight at times though. Thus, for important special cases, the accessors
should return tagged values, preferably even with differing static type. Time
codes can be integrated this way, but most notably the *frame numbers* used
for addressing throughout the vault, can be implemented as such specifically
typed tagged values; the tag here denotes the quantiser and thus the underlying
grid -- it should be implemented as hash-ID for smooth integration with code
written in plain C.
At the level of individual timecode formats, we're lacking a common denominator;
thus it is preferrable to work with different concrete timecode classes through
_generic programming._ This way, each timecode format can expose operations
specific only to the given format. Especially, different timecode formats expose
different _component fields,_ modelled by the generic *Digxel* concept.
There is a common baseclass `TCode` though, which can be used as marker
or for _type erasure._
-> more on link:TimeUsage.html[usage situations]
////
// TODO integrate those cross links
+
-> Timecode link:TimecodeFormat[format and quantisation]
+
-> Quantiser link:QuantiserImpl[implementation details]
////

View file

@ -0,0 +1,186 @@
Time Usage Situations
=====================
:Author: Hermann Voßeler
:Email: <Ichthyostega@web.de>
:Date: Spring 2011
//Menu: label Time Usage
the following collection of usage situations helps to shape the details of the
time values and time quantisation design. +
-> see also link:TimeQuant.html[more about time quantisation]
time position of an object::
indeed the term ``time position'' encompasses two quite different questions
+
* a time or timing specification within the object
* determining the time point in reference to an existing scale
time and length of an object::
basically the same situation, +
but the length of a time span (duration) could be treated in two ways for quantisation
+
* having a precise specification and then quantise the start and endpoint
* quantise the start position and then establish an (independently quantised length)
moving and resizing an object::
this can in itself be done in two different ways, and each of them can be
applied in a quantised flavour, which sums up to 8 possible combinations,
considering that position and length are 2 degrees of freedom.
+
* a variable can be _changed_ by an offset
* a variable can be _defined_ to a new value
* another (hidden) degree of freedom lies in how to apply an quantised offset
to an unquantised value (and reversed), because this operation might be done
both in the quantised or non-quantised domain, and also the result might be
(un)quantised
updating the playback position::
this can be seen as a practical application of the above; basically we can
choose to show the wall clock time or we can advance the playback position in
frame increments, thus denoting the frame currently in display. For video,
these distinctions may look moot, but they are indeed relevant for precise
audio editing, especially when combined with loop playback (recall that audio
is processed block wise, but the individual sample frames and thus the
possible loop positions are way finer than the processing block size)
dispatching individual frames for calculation::
when a link:PlayProcess[render or playback process] is created, at some point
we need to translate this logical unit (``calculation stream'') into individual
frame job entries. This requires to break continuous time into individual
frames, and then ennumerating these frames.
displaying time intervals::
for display, time intervals get _re-quantised_ into display array
coordinates. While evidently the display coordinates are themselves quantised
and we obviously don't want to cancel out the effect of an quantisation of the
values or intervals to be displayed (which means, we get two quantisations
chained up after each other), there remains the question if the display array
coordinates should be aligned to the grid of the _elements to be displayed,_
and especially if the allowed zoom factors should be limited. This decision
isn't an easy one, as it has an immediate and tangible effect on what can be
showed, how reversible and reproducible a view is and (especially note this!)
on the actual values which can be set and changed through the GUI.
time value arithmetic::
Client code as well as the internal implementation of time handling needs to
do arithmetic operations with time values. Time values are additive and
totally ordered. Distance, as calculated by subtraction, can be made into a
metric. Another and quite different question is to what extent a quantised
variant of this arithmetics is required.
relative placement::
because of the divergence between quantised and unquantised values the
question arises, if placement relative to another object refers to the raw
position or the already quantised position. Basically all the variations
discussed for _time and length of an object_ also do apply here.
notable issues
--------------
*Direct quantisation of length is not possible*. This is due to the non-linear
nature of all but the most trivial time grids: Already such a simple addition
like a start offset destroys linearity, and this still the more is true within a
compound grid where the grid spacing changes at some point. Thus, the length has
to be re-established at the target position of an time interval after each
change involving quantisation. Regarding the _strategy_ to apply when
re-establishing the length, it seems more appropriate to treat the object as an
entity which is moved, which means to do quantisation in two steps, first the
position, then the endpoint (the second option in the description above). But it
seems advisable not to hard wire that strategy -- better put it into the
quantiser.
We should note that the problems regarding quantised durations also carry over
to _offsets:_ it is difficult to *define the semantics of a quantised offset*.
Seemingly the only viable approach is to have a _intended offset,_ and then
to apply a re-quantisation to the target after applying the (raw) offset.
*When to materialise a quantisation*. Because of the basic intention to retain
information, we prefer to delay the actual applicatio of the quantisation operation
to the values stored internally as much as possible. But not materialising
immediately at quantisation has the downside of possibly accumulating off-grid
values without that being evident. Most notably, if we apply the raw offsets
produced by GUI interactions, the object's positions and lengthes are bound to
accumulate spurious information never intended by the user.
Thus, an especially important instance of that problem is *how to deal with
updates in a quantised environment*. If we handle quantisation stictly as a
view employed on output, we run into the problems with accumulating spurious
information. On the other hand, allowing for quantised changes inevitably pulls
in all the complexity of mixing quantised and non-quantised values. It would be
desirable somehow to move these distinctions out of the scope of this design and
offload them onto the client (code using these time classes).
Another closely related problem is *when to allow mutations*, if at all (-> see
link:TimeMutation[more here...]). We can't completely do away with mutations,
simply because we don't have a pure functional language at our disposal. The
whole concept of _reference semantics_ doesn't play so well with immutable
objects. The Lumiera high-level (session) model certainly relies on objects
intended to be _manipulated._ Thus we need a re-settable length field in
`MObject` and we need a time variable for position calculations. Yet we
could make any _derived objects_ into immutable descriptor records, which
certainly helps with parallelism.
The *problem with playback position* is -- that indeed it's an attempt to
conceptualise a non-existing entity. There is no such thing like ``the'' playback
position. Yet most applications I'm aware off _do_ employ this concept. Likely
they got trapped by the metaphor of the tape head, again. We should do away with
that. On playback, we should show a _projection of wall-clock time onto the
expected playback range_ -- not more, not less. It should be acknowledged that
there is _no direct link to the ongoing playback processes,_ besides the fact
that they're assumed to sync to wall-clock time as well. Recall, typically there
are multiple playback processes going on in compound, and each might run on a
different update rate. If we really want a _visual out-of-sync indicator,_ we
should treat that as a separate reporting facility and display it apart of the
playback cursor.
An interesting point to note for the *frame dispatch step* is the fact that
in this case quantised values and quantisation are approached in the reverse
direction, compared with the other uses. Here, after establishing a start point
on the time scale, we proceed with ennumerating distinct frames and later on
need to access the corresponding raw time, especially to find out about the
link:Segmentation[timeline segment] to address, or for retrieving parameter
automation. -> link:FrameDispatcher[see frame dispatching].
Note that the *display window might be treated as just an independent instance
of quantisation*. This is similar to the approach taken above for modifying
quantised time span values. When following this line of thought, we should
provide a special kind of time grid, the display coordinates. The origin of
these is always defined to the left (lower) side of the interval to be
displayed, and they are gauged in screen units (pixels or similar, as used by
the GUI toolkit set). The rest is handled by the general quantisation
mechanisms. The problem of aligning the display should be transformed into a
general facility to align grids, and solved for the general case. Doing so
solves the remaining problems with quantised value changes and with *specifying
relative placements* as well: If we choose to represent them as quantised
values, we might (or might not) also choose to apply this _grid-alignment function._
the complete time value usage cycle
-----------------------------------
The way time value and quantisation handling is designed in Lumiera creates a
typical usage path, which actually is a one-way route. We might start out with a
textual representation according to a specific *timecode* format. Assumed we
know the implicit underlying *time grid* (coordinate system, framerate), this
timecode string may be parsed. This brings us (back) to the very origin, which
is a raw `TimeValue` (*internal time* value). Now, this time value might be
manipulated, compared to other values, combined into a *time span* (time point
and duration -- the most basic notion of an _object_ to be manipulated in the
Session). Anyway, at some point these time values need to be related to some
*time scale* again, leading to *quantised* time values, which -- finally --
can be cast into a timecode format for external representation again, thus
closing the circle.
substantial problems to be solved
---------------------------------
* how to link:TimeGridAlignment[align multiple grids]
* how to integrate link:TimeMutation[modifications of quantised values]. ([green]#✔ solved#)
* how to isolate the Time/Quantisation part from the grid MetaAsset in the
session -> we use the link:Advice[Advice] system ([green]#✔ solved#)
* how to design the relation of Timecode, Timecode formatting and Quantisation
-> link:TimecodeFormat[more here] [yellow-background]#WIP#

View file

@ -0,0 +1,26 @@
Design Documents: Lumiera Architecture
======================================
// Menu : sort children
// Menu : prepend child Subsystems
// Menu : prepend child ArchitectureSummary
// Menu : attach child TimeQuant after TimeUsage
This section will feature some rather high-level considerations regarding
the architecture of the application.
.Executive Summary
See link:ArchitectureSummary.html[here] for a short summary of the core architecture
ideas of the envisioned Lumiera Application.
.Rendering and Playback Control
This part of the architecture is concened with how to initiate, coordinate and control
the calculation processes necessary to generate visible / audible data from our source
media. This design is _not so much_ concerned with the actual calculations; indeed it
takes on an ``bird eye's view'', treating the actual render engine mostly just as an
opaque entity providing some service.
-> link:playRender.html[Design: Playback and Rendering]

View file

@ -0,0 +1,195 @@
Design: Playback and Render Control
===================================
:Author: Ichthyostega
:Date: 5/2011
//MENU: label Player subsystem
**************************************************************************************
This part of the architecture is concerned with how to initiate, coordinate and control
the calculation processes necessary to generate visible / audible data from our source
media. This design is _not so much_ concerned with the actual calculations; indeed it
takes a ``birds eye view'', treating the actual render engine mostly just like an
opaque entity providing some service.
**************************************************************************************
Collecting initial drafts
-------------------------
At the start of 2011, several design sketches emerged as an offspring of other
discussions and brainstorming sessions.
* the link:/documentation/devel/rfc_pending/EngineInterfaceOverview.html[Engine Interface draft]
contains some fundamental terms and definitions.
* discussions regarding time values and timecode handling shed some light on the requirements
to be fulfilled by a player subsystem
- link:http://article.gmane.org/gmane.comp.video.lumiera.general/2116[Timecode Widget and Framerates]
- link:http://article.gmane.org/gmane.comp.video.lumiera.general/2109[Time, Time-spans, Quatisation and Timecode]
- link:{l}/wiki/renderengine.html#TimeQuant[Definition of Time entities]
from the implementation notes in the TiddlyWiki
Reasoning Behind the Player Subsystem's Structure
------------------------------------------------
The name ``Player'' might seem surprising at first.
The full, complete and precise name would be something along
the lines of ``_render- and playback-process coordination subsystem_''.
However we need to shorten that into a single word. The more obvious
abbreviation (assuming importance of words to be the selection criteria) would be
_Render_, but that would be strikingly misleading, because everyone would take
that to refer to the render engine. Thus, we are left with _Player_. A second
consideration highlights similarities to the structure of a
typical software player -- the term we selected turns out to be suitably
aligned to the actual nature of that subsystem.
Influences and Requirements
~~~~~~~~~~~~~~~~~~~~~~~~~~~
In accordance with the spirit of modern software development, the analysis
starts by determining the _Service_ that is provided by such a
player. Examination of the Use Cases determines the fundamental forces
to be _multiplicity_, combined with _differentiation in detail_, all under
the government of _time-bound delivery_, combined with _live reconfiguration_.
The basic service turns out to be *performing of a preconfigured object model*.
This performance is *time based*. Multiple usage instances of this service can
be expected to coexist, each of which can be broken down into a set of *elementary
streams to be delivered in sync*. The parameters of delivery can be *reconfigured
on-the-fly*.
Modes of Operation
^^^^^^^^^^^^^^^^^^
Delivery can be either _free-wheeling_, so as to cover a predefined time interval
with fixed quality calculations (final render), and it can be _throttled_ for using
excess computation power (background rendering). Or -- alternatively -- delivery can
be _time-bound_ (for classical playback), following the projection of wall clock time
onto a predefined timeline interval (the so called ``playhead'' or ``playback cursor''
proceeding along a timeline).
Reconfiguration
^^^^^^^^^^^^^^^
Some of these operation modes need to be prepared to encounter an unpredictable live
reconfiguration driven by user interactions:
- any part of background rendering can be invalidated and restarted, while other parts
should be re-integrated, possibly with a re-adjusted position
- playback, which evolves in a linear manner, can be in one of any of these
states at any particular time :
* paused
* reversed in direction
* playback speed re-adjusted
- playback can be looped, with _unlimited_ adjustments of the loop boundaries at
any time.
Conclusions for the Design
~~~~~~~~~~~~~~~~~~~~~~~~~~
Based on these observations, the following design would appear to be pretty much obvious:
The overall player subsystem can be described as ``play/render-this''-service.
Given a suitable (high-level) object, the player has the ability to ``perform''
(play or render) the object.
- the standard operation is _playing a timeline_.
- it is conceivable that playing a selection of other objects would be
permitted, for example, directly playing a clip or even a media asset. In
these cases, it is the player's job to prepare the scaffolding that
is required on the fly.
Yet each such performance of an object is a _stateful instance_, a player application:
on application of the player service, the client obtains a front-end handle, a *play-controller*,
which is a _state machine_. This provides states and transitions such as 'play', 'pause', 'ffwd',
'rew', 'goto', 'step', 'scrub' and similar. Moreover, it maintains (or connects to) a distinct
playback location, and it can be hooked up to a play-control GUI widget
(or something simpler in the case of a render process, which is free wheeling).
Each play-controller, in turn, is then associated with several *play/render-processes*,
one for each independent media stream (channel) to be produced. Of course this
isn't an operating system process; rather, each such process is a compound of entries
in a registration table, which serves the purpose of tying several other services together,
which we initiate and use in order to make that render process happen.
Most notably, we'll use the services of the actual engine which provides us with
a kind of a *calculation stream service*: the ability to deliver a sequence of
calculated data frames in a timely fashion.
When a client requests such an instance of the player service, we build up these
parts providing that service, which cascades down to the individual elements.
At that point, we need to pull and combine two kinds of information:
- the ``what'' to render: this information stems from the session/model.
- the ``how'' to render: this information is guided by the derived output configuration.
Viewer and Output Connection
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Creating a player instance binds three partners together: a _timeline_, a _viewer_
and _the engine_. While the timeline provides the contents to play, the _viewer connection_
is crucial for working out the actual output sink(s) and, hence, the output format to use.
Thus, a viewer connection is a prerequisite in order to create a player instance.
Viewer connections exist as associations in the session/model -- which are entities separate
from the player. Usually, a timeline has (at least) one viewer connection. But in case
such a connection is (still) missing, building a player instance recurs to the session
to get a suitable viewer _allocated_. The viewer connection can't be broken during the
lifetime of that player instance (or putting it the other way: breaking that viewer
connection, e.g. by forcing a different connection or by shutting down the viewer,
immediately terminates the player.) This detaching works synchronously, i.e. it
blocks until all the allocated _output slots_ can be released.
Live switching
^^^^^^^^^^^^^^
While the viewer connection can be treated as fixed during the lifespan of a player
instance, several life switching and reconfiguration operations might happen at any time:
the _model port_ (the place where data is retrieved from calculation), the output characteristics
(framerate, direction) and the delivery goals (playback position, loop playing, scrubbing)
all may be changed during playback -- we need a way for the player to ``cancel'' and
reconfigure the vault layer services.
Frame quantisation
^^^^^^^^^^^^^^^^^^
link:../TimeQuant.html[Quantisation] is a kind of rounding; like any kind of rounding, quantisation is
a dangerous operation because it kills information content.
Thus, there are three fundamental guidelines when it comes to rounding:
. don't do it
. do it at most once
. do it as late as possible
These may guide the process of finding the right place for the Quantiser(s) to
apply. We need some information flows to be joined in order to be able to do
the quantisation, which leaves us with just a few possible junction points
where to place quantisation: the Vault, the GUI, the player and the session.
- putting it into the vault layer seems to be the most reasonable at first sight:
we can ``do away'' with nasty things soon, especially if they are technicalities,
``get a clean state soon'' -- and hasn't frame quantisation something to do
with media data, which is handled in the vault?
+
Well, actually, all of those are pitfalls to trap the unwary. About
cleanliness, well, sigh! Doing rounding soon will leave us with a huge
amount of degraded information flows throughout the whole system; as a
consequence, the general rule is to do it as late as possible. Uncrippled
information is an enablement. And last but not least: the frame quantisation is connected
to the _output_ format -- and the vault layer is likely within the whole
application the subsystem most remote and unaware of output requirements.
- rounding/quantising in the GUI is extremely common within media applications;
unfortunately there does not appear to be a single rational argument in
support of this habit. Most of all, it is a violation of the subsidiarity
principle.
Which leaves us with the player and the session. Both positions could
arguably be supported. Here, a more careful consideration shows, that
the ``act of frame rounding'' can be decomposed: into the _act of quantisation_
and the _frame grid_. Basically it is the session which has the ability
to form the *frame grid*, but it is lacking crucial information about
the output. Only when connecting both -- which is the essence of the
player -- frame quantisation can actually be performed. Thus, the
player is the natural location to perform that quantisation operation.

View file

@ -0,0 +1,68 @@
Design: Output Handling
=======================
:Date: June 2011
:Author: Ichthyostega
//Menu: label Output handling
The topic of proper output handling relates several subsystems and re-appears on
various levels of abstraction within the application design and implementation.
output format::
the availability of a specific output sink is prerequisite for supporting a
given format, configuration or frame rate. It might be desitable to prepare
the same edit for multiple output formats, which can be done by using the same
top-level sequence within several timelines with suitably output configuration.
number of output streams::
the concrete structure of objects within the session creates the ability to deliver
multiple streams of output data. On the other hand, using a given sequence as virtual
clip within another sequence creates the demand for a distinct number of output designations
actual system configuration::
working on the same edit on multiple systems creates the challenge to adapt to
different output possibilities. Since studio setups can be involved, we need to recall
a very special setup, even when it can not be used all the time on the current system.
adapting and transforming::
since the actual output designation is resolved in several steps, it might become necessary
to adapt or transform media streams to be rendered into a provided output sink. For example,
a sound panning device might become necessary to render one sound representation system
into another one. Since the resolution of output is driven by context information,
the necessity of such transformations can arise any time and might be treated
at a location remote from the actual source of the change.
timeline viewer connection::
any kind of playback requires the colaboration of some model content, a viewer device
and the render engine. For example, only after connecting a timeline to a viewer, an actual
playback position and play control becomes available.
viewer switch board::
the typical viewer in the GUI includes a switch board to choose between various probe points
and source during playback. Thus, establishing a timeline viewer connection both adds new
sources to the switch board and necessitates to build an additional output connection and
transformation network behind the scenes.
output sinks::
while each output provides some kind of destination to dispose buffers with prepared media data,
unfortunately, the various output systems and support libraries come with a wide array of often
incompatible assumptions and protocols for the client to comply.
playback modes::
supporting the various kinds of playback modes makes the engine require some support from the
actual output device, e.g. for freezing a frame, for treating delivery glitches gracefully, or
to inhibit further output during reconfiguration stages.
Basic design principles...
--------------------------
- abstract away the actual technology used for output
- have generic *output designations* and translate them into an *output slot*
- the OutputSlot interface can be designed to match the requirements of the Engine
- assume a mechanism to handle timeouts, glitches and skips within each concrete OutputSlot implementation
Please refer to the more technical and in-depth
link:/wiki/renderengine.html#OutputDesignation%20OutputSlot%20OutputManagement%20OutputMapping%20Wiring[
discussion in the TiddlyWiki]

View file

@ -0,0 +1,139 @@
Analysis: Modes of Playback
===========================
:Date: January 2013
:Author: Ichthyostega
The *player* -- shorthand for ``playback and render control subsystem''
is responsible for establishing and coordinating the processes and services
necessary for generating continuous output or rendered media. The actual calculations
take place within the render engine, while the player instructs the engine in case of
any modification regarding the _parameters_ of timed data delivery. More specifically,
there is a *play controller* (state machine) for each _instance_ of playback, managing
an allocated *output slot* with a set of *output sinks*, plus a number of *calculation streams*,
which in turn are cooperating with the *frame dispatcher* and the *scheduler interface*. The
latter acts as low-level interface to the actual rendering operations, since it allows to
schedule individual *frame jobs* together with their prerequisite dependencies. This
setup creates a pattern of cooperation, with the goal of delivering a continuous stream
of calculated data to the output sinks. Specific changes within the parametrisation of
that cooperation pattern result in an overall changed mode of playback or rendering.
Rendering of final results
--------------------------
The classic case of ``rendering the results'' is treated within this framework as a special
case of _generic play-back_: Any frames are to be delivered when done with the calculation,
without any timing constraints, while, on the other hand, no glitches or quality compromises
whatsoever are acceptable. Also, the play controller exposes only limited abilities: in case of
rendering, all we need is the ability to pause and abort the process, plus an progress indicator.
Regular playback
----------------
The *standard case of playback* delivers a sequence of media data frames at a given frame rate,
with simple _linear temporal progression_. Typically, there are multiple playback feeds
linked together, each delivering a specific kind of media at a specific frame or block rate,
while being coordinated by a single play controller and working to a common delivery time goal
(``play head''). Which means in turn, that each individual frame has to be delivered within
a pre planned time window. Lumiera employs an elaborate and precise timing control, based on
triggering small atomic chunks of work in a ``just in time'' manner -- there is _no_ generic
and built-in buffering beyond the low-level double buffering mechanisms utilised by most
output facilities. Generally speaking, we prefer precise beforehand planning and discarding
of untimely results over demand-driven and possibly blocking operations. Yet the buffer
management and frame cache provided by the vault for storing and passing of intermediary
and final results allows for a certain amount of leeway.
Non-standard playback modes
---------------------------
The requirements of a software player, especially in the context of an editing application,
call for support of several specific operation modes of playback -- which can be characterised
by breaking with the rule of simple and linear progression in timed delivery. The following
requirement analysis defines our understanding and implementation approach towards these
mandatory features.
Requirement analysis of playback modes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For the task of editing a piece of media, the following modes of playback presentation can be determined +
See also the more
link:wiki/renderengine.html#NonLinearPlayback%20PlayService%20PlayProcess%20CalcStream%20FrameDispatcher%20OutputManagement[
technical discussion of playback in the TiddlyWiki]
regular playback::
In this operation mode, some media or the arrangement on one of the timelines will be presented
in the intended order and with the nominal speed, possibly somewhat adjusted for the display
or monitoring device employed. There is a running time code display and an animated presentation
of the current nominal playback position (``play head'', ``cursor'', ``locator'') in the GUI.
Generally speaking, within Lumiera this playback position isn't incorporated as a specific
device -- rather it is treated as a conceptual mapping of nominal time to wall clock time.
jumping::
creates a discontinuity in _nominal time,_ while the progress of _real wall clock time deadlines_
remains unaffected. We need to distinguish two kinds of _jumps_ or _skips_:
+
* a _pre planned jump_ can be worked into the progression of frames just like in normal progression.
Such a jump might be due to a _skip mark_ in the timeline, or it may be used to implement looped playback.
* to the contrary, a _spontaneous re-adjustment of playback position_ is caused by unpredictable external
events, like e.g. user interaction or remote control. Such an unpredictable change in the playback plan
deprives the engine of any delivery headroom; to allow for catch-up to timed delivery, a configurable
_slippage offset_ can be added to the newly established real time deadlines after the skip, in order
to prevent drop-outs.
+
Since each skip might create an output discontinuity, a ``de-clicking'' or ``de-flickering'' device can be
expected to intercept on the individual output connections to improve the usage experience while exploring media.
looping::
In looped playback the nominal playback position jumps back to the starting point, after travelling over
a pre defined looping time span (``looping window''). This looping time span can be re-adjusted while in
playback, with immediate effect on the output. A fluid handling of loop playback is extremely important
for all kinds of fine tuning work. The loop boundaries may be chosen arbitrary, not necessarily aligned
to any frame grid (the fact this might cause some irregularities on the presented frame sequence is
acknowledged, yet it is deemed acceptable and preferred over employing any kind of additional
interpolation device not present in normal playback). +
Looped playback can be conceived as a series of regularly scheduled jumps.
pausing::
_paused playback_ represents a special state of the player and engine, where we expect playback to be able
to commence right away, with minimal latency. Contrast this to entering playback from stopped state, where
services need to be initiated and connected, leading to an noticeable pre-delay. Basically, each other
playback mode can be entered from paused state right away, and it is reasonable for the engine to
prepare for this through background pre rendering.
single stepping::
through user interaction, the current nominal playback position is moved to an adjacent frame,
while sending exactly this one frame to output as a still image. This is a critical operation for frame
accurate editing and should be reachable from any other playback mode with minimal latency. Lumiera treats
this mode of operation as an extension to _paused state_.
playback direction and speed::
while regular playback establishes a 1:1 relation between nominal time and wall clock time, a range of
other proportions need to be supported, like e.g. halved and doubled presentation speed both forwards and
backwards; it is conceivable to allow irregular fractions too. Support for speed adjustments in sound
playback is more involved as it might seem at first glance, so it is common to allow for a degraded
sound representation, or to fall back on fast-cueing.
fast cueing::
The purpose of cuing is to skip through a large amount of material to spot some specific parts.
For this to work, the presented material needs to be still recognisable in some way. Typically this is done
by presenting small continuous chunks of material interleaved with regular skips. For editing purposes, this
method is often perceived as lacking, especially by experienced editors. To the contrary, the former,
mechanical editing systems had the ability to run with actually increased frame rate, without skipping
any material.
+
* it is very common to employ speed acceleration in multiple steps to alleviate travelling to more distant
locations within the media
* to improve the editor's working experience, we might consider actually to raise the frame rate, given the
increased availability of high-framerate capable displays.
* another approach would be to apply some kind of granular synthesis, dissolving several consecutive segments
of material. The latter would prompt to include a specific buffering and processing device not present
in the render path for normal playback.
scrubbing::
this term relates to working with physical media, like magnetic tape or film strips the past: instead of using
the built-in transport device, the editor would spin the reels by hand in order to navigate to a desired position
intuitively. When translated to the world of digital media, the actual scrubbing facility is an interactive device,
typically even involving some kind of hardware control interface (``jog shuttle''). The playback engine needs to
support scrubbing, which translates into chasing a playback target, which is re-adjusted regularly. Again it
would be desirable to include some kind of acceleration strategy, especially to support a soft landing.

View file

@ -0,0 +1,6 @@
Design Documents: Renderengine
==============================
This section contains design documents regarding the overall workings of the Render Engine,
and the handling of output generation and output connections.

View file

@ -0,0 +1,15 @@
Governance Documents
====================
:Date: April 2023
Lumiera is developed as Free/OpenSource project under the GNU General Public License.
Source code is shared via Git, and ongoing development is publicly visible.
Discussions and contributions are welcome.
The vision and goals for the Lumiera application are far reaching and ambitious;
in the current phase the project has started to integrate concepts, structures
and subsystems developed over the course of several years, to create a coherent
architecture, able to support the vision.
-> link:integration.html[Integration effort]

View file

@ -0,0 +1,55 @@
Towards Integration
===================
:date: Spring 2023
:author: Ichthyostega
//Menu: label Integration
The Lumiera project creates innovative software, geared towards professional, high-quality work;
it aims at high flexibility, offering user-control over a broad spectrum of configurable parameters,
and with smooth workflows that scale well to larger and more intricate projects. Building such
software involves some degree of exploration and search for adequate methods to reconcile
conflicting goals. There is no ready-made blueprint that just needs implementation -- rather,
we have to resort to a sequence of integration efforts, aimed at establishing core tenets
of the envisioned architecture.
Vertical Slices
---------------
TIP: A »https://en.wikipedia.org/wiki/Vertical_slice[vertical slice]« is an integration effort
that engages all major software components of a software system. It is defined and used as
a tool to further and focus the development activity towards large scale integration goals.
Populate the Timeline in the UI
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
✔ link:https://issues.lumiera.org/ticket/1014[#1014 »TimelinePopulation«]: +
Send a description of the model structure in the form of a _population diff_ from the Session
in Steam-Layer up through the UI-Bus. When received in the UI-Layer, a new Timeline tab will be
allocated and populated with appropriate widgets to create a GUI-Timeline-View. The generated
UI structures will feature several nested tracks and some placeholder clips, which can be
dragged with the mouse. Moreover, the nested track structure is visualised by _custom drawing_
onto a _canvas widget,_ and the actual colours and shades for this drawing operations will be
picked up from the current desktop theme, in combination with an CSS application stylesheet.
Commands and State Messages via UI-Bus
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
✔ link:https://issues.lumiera.org/ticket/1099[#1014 »Demo GUI Roundtrip«]: +
Set up a test dialog in the UI, which issues test/dummy commands. These are propagated
to a dispatcher in Steam-Layer and by special rigging reflected back as _State Mark Messages_
over the UI-Bus, causing a visible state change in the _Error Log View_ in the UI.
Play a clip
~~~~~~~~~~~
🗘 link:https://issues.lumiera.org/ticket/1221[#1221 »PlaybackVerticalSlice«]: +
This vertical slice drives integration of Playback and Rendering.
While the actual media content is still mocked and hard wired, we get a simple playback control
in the GUI connected to some suitable display of video. When activated, an existing _ViewConnection_
is used to initiate a _Play Process_; the _Fixture_ data structure established between high-level-Model
(Session) and low-level-Model (Render nodes) will back a _Frame Dispatcher_ to generate _Render Jobs,_
which are then digested and activated by the _Scheduler_ in the Vault-Layer, thereby
_operating the render nodes_ to generate video data for display.

View file

@ -0,0 +1,14 @@
GUI Proposal by AkhIL
=====================
:Author: IL'dar AKHmetgaleev (»AkhIL«)
:Date: 2008-03-30
Wiring nodes within the timeline
--------------------------------
In fall 2007, rather then using an external node editor, AkhiL proposed to do wiring
of effect nodes directly within the timeline. He did the following Mockup:
image::{imgg}/AkhiL.proposal.png[]

View file

@ -0,0 +1,579 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg2"
sodipodi:version="0.32"
inkscape:version="0.46"
width="1052.5"
height="743.75"
xml:space="preserve"
sodipodi:docname="Proposal.Alcarinque.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
id="metadata7"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/" /><dc:title>Lumiera GUI proposal</dc:title><dc:creator><cc:Agent><dc:title>Francisco G. Rodriguez (»Alcarinque«)</dc:title></cc:Agent></dc:creator><dc:date>07.05.2008</dc:date><dc:description>passed in as part of the Lumiera GUI discussion.
Added to Lumiera Website 2/2011 by Ichthyostega</dc:description></cc:Work><cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/3.0/"><cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" /><cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" /><cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" /><cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" /><cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /><cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" /></cc:License></rdf:RDF></metadata><defs
id="defs5"><inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective9" /><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath17"><path
d="M 0,-0.3 L 842,-0.3 L 842,595 L 0,595 L 0,-0.3 z"
clip-rule="evenodd"
id="path19" /></clipPath></defs><sodipodi:namedview
inkscape:window-height="960"
inkscape:window-width="1428"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
guidetolerance="10.0"
gridtolerance="10.0"
objecttolerance="10.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
id="base"
showgrid="false"
inkscape:zoom="1.1021378"
inkscape:cx="536.31226"
inkscape:cy="422.53753"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:current-layer="g11" /><g
id="g11"
inkscape:groupmode="layer"
inkscape:label="ui_architecture"
transform="matrix(1.25,0,0,-1.25,0,743.75)"><g
id="g183"><path
d="M 99.2,382.4 L 113.4,382.4"
style="fill:none;stroke:none"
id="path185" /></g><g
id="g187"><path
d="M 155.9,382.4 L 170.1,382.4"
style="fill:none;stroke:none"
id="path189" /></g><g
id="g191"><path
d="M 212.6,382.4 L 226.8,382.4"
style="fill:none;stroke:none"
id="path193" /></g><g
id="g3939"
transform="matrix(0.5627991,0,0,0.5627991,0,260.13454)"><path
id="path21"
style="fill:#f5e7c3;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 0,595 L 841.9,595 L 841.9,150.05345 L 0,150.05345 L 0,595 z" /><path
id="path23"
style="fill:#c0c0c0;fill-opacity:1;fill-rule:evenodd;stroke:#439ee0;stroke-width:1.77683294;stroke-opacity:1"
d="M 269.3,240.7 L 28.3,240.7 L 28.3,439.1 L 510.2,439.1 L 510.2,240.7 L 269.3,240.7 z" /><g
id="g25"><path
id="path27"
style="fill:none;stroke:none"
d="M 269.3,240.7 L 28.3,240.7 L 28.3,439.1 L 510.2,439.1 L 510.2,240.7 L 269.3,240.7 z" /></g><g
id="g29"><text
id="text31"
transform="matrix(1,0,0,-1,325.4,253)"><tspan
id="tspan33"
sodipodi:role="line"
y="0"
x="0 12.996 23.004 32.903999 42.911999 47.897999 60.894001 70.902 85.896004 95.795998 105.804 114.804 118.71 123.786 133.686"
style="font-size:18px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Node Compositor</tspan></text>
</g><path
id="path35"
style="fill:#ccffff;fill-opacity:1;fill-rule:evenodd;stroke:#5216df;stroke-width:1.77683294;stroke-opacity:1"
d="M 240.9,481.6 L 42.5,481.6 L 42.5,566.7 L 439.4,566.7 L 439.4,481.6 L 240.9,481.6 z" /><g
id="g37"><path
id="path39"
style="fill:none;stroke:none"
d="M 240.9,481.6 L 42.5,481.6 L 42.5,566.7 L 439.4,566.7 L 439.4,481.6 L 240.9,481.6 z" /></g><g
id="g41"><text
id="text43"
transform="matrix(1,0,0,-1,351.3,487.7)"><tspan
id="tspan45"
sodipodi:role="line"
y="0"
x="0 10.494 14.4 29.393999 39.402 43.307999 47.304001 57.312"
style="font-size:18px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Timeline</tspan></text>
</g><path
id="path47"
style="fill:#ffff99;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 170.1,254.8 L 42.5,254.8 L 42.5,424.9 L 297.6,424.9 L 297.6,254.8 L 170.1,254.8 z" /><g
id="g49"><path
id="path51"
style="fill:none;stroke:none"
d="M 170.1,254.8 L 42.5,254.8 L 42.5,424.9 L 297.6,424.9 L 297.6,254.8 L 170.1,254.8 z" /></g><g
id="g53"><text
id="text55"
transform="matrix(1,0,0,-1,117.3,273.2)"><tspan
id="tspan57"
sodipodi:role="line"
y="0"
x="0 12.906 22.914 32.922001 42.821999 47.807999 51.804001 61.812 70.505997 80.514 90.522003 95.508003 100.494"
style="font-size:18px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Node layout I</tspan></text>
</g><path
id="path59"
style="fill:#ff9966;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 148.8,524.1 L 85,524.1 L 85,538.3 L 212.6,538.3 L 212.6,524.1 L 148.8,524.1 z" /><g
id="g61"><path
id="path63"
style="fill:none;stroke:none"
d="M 148.8,524.1 L 85,524.1 L 85,538.3 L 212.6,538.3 L 212.6,524.1 L 148.8,524.1 z" /></g><g
id="g65"><text
id="text67"
transform="matrix(1,0,0,-1,130.4,526.3)"><tspan
id="tspan69"
sodipodi:role="line"
y="0"
x="0 9.2959995 13.286 17.976 21.07 28.854 32.844002"
style="font-size:14px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Strip I</tspan></text>
</g><path
id="path71"
style="fill:#ff9966;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 255.1,495.8 L 198.4,495.8 L 198.4,510 L 311.8,510 L 311.8,495.8 L 255.1,495.8 z" /><g
id="g73"><path
id="path75"
style="fill:none;stroke:none"
d="M 255.1,495.8 L 198.4,495.8 L 198.4,510 L 311.8,510 L 311.8,495.8 L 255.1,495.8 z" /></g><g
id="g77"><text
id="text79"
transform="matrix(1,0,0,-1,234.7,498)"><tspan
id="tspan81"
sodipodi:role="line"
y="0"
x="0 9.3800001 13.272 17.962 21.056 28.84 32.830002 36.82"
style="font-size:14px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Strip II</tspan></text>
</g><path
id="path83"
style="fill:#ff9966;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 347.2,538.3 L 297.6,538.3 L 297.6,552.5 L 396.9,552.5 L 396.9,538.3 L 347.2,538.3 z" /><g
id="g85"><path
id="path87"
style="fill:none;stroke:none"
d="M 347.2,538.3 L 297.6,538.3 L 297.6,552.5 L 396.9,552.5 L 396.9,538.3 L 347.2,538.3 z" /></g><g
id="g89"><text
id="text91"
transform="matrix(1,0,0,-1,324.9,540.5)"><tspan
id="tspan93"
sodipodi:role="line"
y="0"
x="0 9.2959995 13.286 17.976 21.07 28.854 32.745998 36.736 40.627998"
style="font-size:14px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Strip III</tspan></text>
</g><path
id="path95"
style="fill:#99ccff;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 78,354.1 L 56.7,354.1 L 56.7,410.7 L 99.2,410.7 L 99.2,354.1 L 78,354.1 z" /><g
id="g97"><path
id="path99"
style="fill:none;stroke:none"
d="M 78,354.1 L 56.7,354.1 L 56.7,410.7 L 99.2,410.7 L 99.2,354.1 L 78,354.1 z" /></g><g
id="g101"><text
id="text103"
transform="matrix(1,0,0,-1,72.1,385.4)"><tspan
id="tspan105"
sodipodi:role="line"
y="0"
x="0 3.892"
style="font-size:14px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">In</tspan></text>
</g><g
id="g107"><text
id="text109"
transform="matrix(1,0,0,-1,61.9,369.7)"><tspan
id="tspan111"
sodipodi:role="line"
y="0"
x="0 10.192 13.286 16.379999 24.164 28.153999"
style="font-size:14px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Clip I</tspan></text>
</g><path
id="path113"
style="fill:#99ccff;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 78,283.2 L 56.7,283.2 L 56.7,339.9 L 99.2,339.9 L 99.2,283.2 L 78,283.2 z" /><g
id="g115"><path
id="path117"
style="fill:none;stroke:none"
d="M 78,283.2 L 56.7,283.2 L 56.7,339.9 L 99.2,339.9 L 99.2,283.2 L 78,283.2 z" /></g><g
id="g119"><text
id="text121"
transform="matrix(1,0,0,-1,72.1,314.5)"><tspan
id="tspan123"
sodipodi:role="line"
y="0"
x="0 3.892"
style="font-size:14px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">In</tspan></text>
</g><g
id="g125"><text
id="text127"
transform="matrix(1,0,0,-1,63.2,298.8)"><tspan
id="tspan129"
sodipodi:role="line"
y="0"
x="0 10.192 17.598 21.49 25.48"
style="font-size:14px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">NL II</tspan></text>
</g><path
id="path131"
style="fill:#99ccff;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 134.6,354.1 L 113.4,354.1 L 113.4,410.7 L 155.9,410.7 L 155.9,354.1 L 134.6,354.1 z" /><g
id="g133"><path
id="path135"
style="fill:none;stroke:none"
d="M 134.6,354.1 L 113.4,354.1 L 113.4,410.7 L 155.9,410.7 L 155.9,354.1 L 134.6,354.1 z" /></g><g
id="g137"><text
id="text139"
transform="matrix(1,0,0,-1,116.7,385.4)"><tspan
id="tspan141"
sodipodi:role="line"
y="0"
x="0 9.3800001 13.076 16.968 24.752001 31.836"
style="font-size:14px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Effect</tspan></text>
</g><g
id="g143"><text
id="text145"
transform="matrix(1,0,0,-1,132.7,369.7)"><tspan
id="tspan147"
y="0"
x="0"
style="font-size:14px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">I</tspan></text>
</g><path
id="path149"
style="fill:#99ccff;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 191.3,354.1 L 170.1,354.1 L 170.1,410.7 L 212.6,410.7 L 212.6,354.1 L 191.3,354.1 z" /><g
id="g151"><path
id="path153"
style="fill:none;stroke:none"
d="M 191.3,354.1 L 170.1,354.1 L 170.1,410.7 L 212.6,410.7 L 212.6,354.1 L 191.3,354.1 z" /></g><g
id="g155"><text
id="text157"
transform="matrix(1,0,0,-1,173.4,385.4)"><tspan
id="tspan159"
sodipodi:role="line"
y="0"
x="0 9.2959995 13.09 16.982 24.766001 31.85"
style="font-size:14px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Effect</tspan></text>
</g><g
id="g161"><text
id="text163"
transform="matrix(1,0,0,-1,187.4,369.7)"><tspan
id="tspan165"
sodipodi:role="line"
y="0"
x="0 3.99"
style="font-size:14px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">II</tspan></text>
</g><path
id="path167"
style="fill:#99ccff;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 248,354.1 L 226.8,354.1 L 226.8,410.7 L 269.3,410.7 L 269.3,354.1 L 248,354.1 z" /><g
id="g169"><path
id="path171"
style="fill:none;stroke:none"
d="M 248,354.1 L 226.8,354.1 L 226.8,410.7 L 269.3,410.7 L 269.3,354.1 L 248,354.1 z" /></g><g
id="g173"><text
id="text175"
transform="matrix(1,0,0,-1,236.7,377.5)"><tspan
id="tspan177"
sodipodi:role="line"
y="0"
x="0 10.892 18.676001"
style="font-size:14px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Out</tspan></text>
</g><g
id="g179"><path
id="path181"
style="fill:none;stroke:none"
d="M 99.2,311.5 L 191.3,311.5 L 191.3,354.1" /></g><g
id="g195"><path
id="path197"
style="fill:none;stroke:none"
d="M 248,410.7 L 248,467.2 L 148.8,467.2 L 148.8,524.1" /></g><path
id="path199"
style="fill:#ffff99;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 396.9,396.6 L 311.8,396.6 L 311.8,424.9 L 481.9,424.9 L 481.9,396.6 L 396.9,396.6 z" /><g
id="g201"><path
id="path203"
style="fill:none;stroke:none"
d="M 396.9,396.6 L 311.8,396.6 L 311.8,424.9 L 481.9,424.9 L 481.9,396.6 L 396.9,396.6 z" /></g><g
id="g205"><text
id="text207"
transform="matrix(1,0,0,-1,341.5,404.5)"><tspan
id="tspan209"
sodipodi:role="line"
y="0"
x="0 12.996 23.004 32.903999 42.804001 47.880001 51.875999 61.776001 70.578003 80.585999 90.486 95.472 100.548 105.534"
style="font-size:18px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Node layout II</tspan></text>
</g><g
id="g211"><path
id="path213"
style="fill:none;stroke:none"
d="M 396.9,424.9 L 396.9,460.1 L 255.1,460.1 L 255.1,495.8" /></g><path
id="path215"
style="fill:#ffff99;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 411,354.1 L 326,354.1 L 326,382.4 L 496.1,382.4 L 496.1,354.1 L 411,354.1 z" /><g
id="g217"><path
id="path219"
style="fill:none;stroke:none"
d="M 411,354.1 L 326,354.1 L 326,382.4 L 496.1,382.4 L 496.1,354.1 L 411,354.1 z" /></g><g
id="g221"><text
id="text223"
transform="matrix(1,0,0,-1,353.2,362)"><tspan
id="tspan225"
sodipodi:role="line"
y="0"
x="0 12.906 22.914 32.922001 42.821999 47.807999 51.804001 61.812 70.505997 80.514 90.522003 95.508003 100.494 105.57 110.556"
style="font-size:18px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Node layout III</tspan></text>
</g><g
id="g227"><path
id="path229"
style="fill:none;stroke:none"
d="M 411,382.4 L 411,467.6 L 347.2,467.6 L 347.2,538.3" /></g><path
id="path231"
style="fill:#ffcc99;fill-opacity:1;fill-rule:evenodd;stroke:#c81941;stroke-width:1.77683294;stroke-opacity:1"
d="M 666.1,254.8 L 538.6,254.8 L 538.6,424.9 L 793.7,424.9 L 793.7,254.8 L 666.1,254.8 z" /><g
id="g233"><path
id="path235"
style="fill:none;stroke:none"
d="M 666.1,254.8 L 538.6,254.8 L 538.6,424.9 L 793.7,424.9 L 793.7,254.8 L 666.1,254.8 z" /></g><g
id="g237"><text
y="-263.10001"
x="678.19312"
id="text239"
transform="scale(1,-1)"><tspan
id="tspan241"
sodipodi:role="line"
y="-263.10001"
x="678.19312 692.98907 702.8891 712.89709 716.89313 726.79309 731.86908 741.7691 745.76508 755.77313 761.67712 771.68512 777.67908"
style="font-size:18px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Media Library</tspan></text>
</g><path
id="path243"
style="fill:#94bd5e;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 630.7,354.1 L 609.4,354.1 L 609.4,410.7 L 652,410.7 L 652,354.1 L 630.7,354.1 z" /><g
id="g245"><path
id="path247"
style="fill:none;stroke:none"
d="M 630.7,354.1 L 609.4,354.1 L 609.4,410.7 L 652,410.7 L 652,354.1 L 630.7,354.1 z" /></g><g
id="g249"><text
id="text251"
transform="matrix(1,0,0,-1,612.7,377.5)"><tspan
id="tspan253"
sodipodi:role="line"
y="0"
x="0 10.192 13.286 16.379999 24.164 28.153999 32.046001"
style="font-size:14px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Clip II</tspan></text>
</g><path
id="path255"
style="fill:#94bd5e;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 574,354.1 L 552.8,354.1 L 552.8,410.7 L 595.3,410.7 L 595.3,354.1 L 574,354.1 z" /><g
id="g257"><path
id="path259"
style="fill:none;stroke:none"
d="M 574,354.1 L 552.8,354.1 L 552.8,410.7 L 595.3,410.7 L 595.3,354.1 L 574,354.1 z" /></g><g
id="g261"><text
id="text263"
transform="matrix(1,0,0,-1,557.9,377.5)"><tspan
id="tspan265"
sodipodi:role="line"
y="0"
x="0 10.192 13.286 16.478001 24.261999 28.153999"
style="font-size:14px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Clip I</tspan></text>
</g><path
id="path267"
style="fill:#94bd5e;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 687.4,354.1 L 666.1,354.1 L 666.1,410.7 L 708.7,410.7 L 708.7,354.1 L 687.4,354.1 z" /><g
id="g269"><path
id="path271"
style="fill:none;stroke:none"
d="M 687.4,354.1 L 666.1,354.1 L 666.1,410.7 L 708.7,410.7 L 708.7,354.1 L 687.4,354.1 z" /></g><g
id="g273"><text
id="text275"
transform="matrix(1,0,0,-1,667.4,377.5)"><tspan
id="tspan277"
sodipodi:role="line"
y="0"
x="0 10.192 13.286 16.379999 24.164 28.153999 32.046001 36.035999"
style="font-size:14px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Clip III</tspan></text>
</g><path
id="path279"
style="fill:#ffff99;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 581.1,283.2 L 552.8,283.2 L 552.8,339.9 L 609.4,339.9 L 609.4,283.2 L 581.1,283.2 z" /><g
id="g281"><path
id="path283"
style="fill:none;stroke:none"
d="M 581.1,283.2 L 552.8,283.2 L 552.8,339.9 L 609.4,339.9 L 609.4,283.2 L 581.1,283.2 z" /></g><g
id="g285"><text
id="text287"
transform="matrix(1,0,0,-1,562.3,314.5)"><tspan
id="tspan289"
sodipodi:role="line"
y="0"
x="0 10.192 17.976 25.76 33.543999"
style="font-size:14px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Node </tspan></text>
</g><g
id="g291"><text
id="text293"
transform="matrix(1,0,0,-1,558.5,298.8)"><tspan
id="tspan295"
sodipodi:role="line"
y="0"
x="0 3.0940001 10.878 17.780001 25.563999 33.264 37.254002 41.243999"
style="font-size:14px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">layout I</tspan></text>
</g><path
id="path297"
style="fill:#ffff99;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 652,283.2 L 623.6,283.2 L 623.6,339.9 L 680.3,339.9 L 680.3,283.2 L 652,283.2 z" /><g
id="g299"><path
id="path301"
style="fill:none;stroke:none"
d="M 652,283.2 L 623.6,283.2 L 623.6,339.9 L 680.3,339.9 L 680.3,283.2 L 652,283.2 z" /></g><g
id="g303"><text
id="text305"
transform="matrix(1,0,0,-1,633.2,314.5)"><tspan
id="tspan307"
sodipodi:role="line"
y="0"
x="0 10.192 17.976 25.76 33.543999"
style="font-size:14px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Node </tspan></text>
</g><g
id="g309"><text
id="text311"
transform="matrix(1,0,0,-1,627.4,298.8)"><tspan
id="tspan313"
sodipodi:role="line"
y="0"
x="0 3.0940001 10.878 17.681999 25.466 33.25 37.240002 41.132 45.122002"
style="font-size:14px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">layout II</tspan></text>
</g><path
id="path315"
style="fill:#ffff99;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 722.8,283.2 L 694.5,283.2 L 694.5,339.9 L 751.2,339.9 L 751.2,283.2 L 722.8,283.2 z" /><g
id="g317"><path
id="path319"
style="fill:none;stroke:none"
d="M 722.8,283.2 L 694.5,283.2 L 694.5,339.9 L 751.2,339.9 L 751.2,283.2 L 722.8,283.2 z" /></g><g
id="g321"><text
id="text323"
transform="matrix(1,0,0,-1,704,314.5)"><tspan
id="tspan325"
sodipodi:role="line"
y="0"
x="0 10.192 17.976 25.76 33.543999"
style="font-size:14px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Node </tspan></text>
</g><g
id="g327"><text
id="text329"
transform="matrix(1,0,0,-1,696.2,298.8)"><tspan
id="tspan331"
sodipodi:role="line"
y="0"
x="0 3.1919999 10.976 17.780001 25.563999 33.348 37.338001 41.23 45.220001 49.209999"
style="font-size:14px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">layout III</tspan></text>
</g><g
id="g333"><path
id="path335"
style="fill:none;stroke:none"
d="M 78,283.2 L 78,269 L 652,269 L 652,283.2" /></g><g
id="g337"><path
id="path339"
style="fill:none;stroke:none"
d="M 574,354.1 L 574,347.5 L 78,347.5 L 78,354.1" /></g><path
id="path341"
style="fill:#ff3333;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 215.4,481.6 L 212.6,481.6 L 212.6,566.7 L 218.3,566.7 L 218.3,481.6 L 215.4,481.6 z" /><g
id="g343"><path
id="path345"
style="fill:none;stroke:none"
d="M 215.4,481.6 L 212.6,481.6 L 212.6,566.7 L 218.3,566.7 L 218.3,481.6 L 215.4,481.6 z" /></g><path
id="path347"
style="fill:#9999cc;fill-opacity:1;fill-rule:evenodd;stroke:#592e85;stroke-width:1.77683294;stroke-opacity:1"
d="M 659.1,439.1 L 538.6,439.1 L 538.6,566.7 L 779.5,566.7 L 779.5,439.1 L 659.1,439.1 z" /><g
id="g349"><path
id="path351"
style="fill:none;stroke:none"
d="M 659.1,439.1 L 538.6,439.1 L 538.6,566.7 L 779.5,566.7 L 779.5,439.1 L 659.1,439.1 z" /></g><g
id="g353"><text
id="text355"
transform="matrix(1,0,0,-1,624.5,547)"><tspan
id="tspan357"
sodipodi:role="line"
y="0"
x="0 11.7 15.606 25.614 38.214001 48.113998 58.122002 64.115997"
style="font-size:18px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Viewport</tspan></text>
</g><path
id="path359"
style="fill:#99ccff;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 722.8,467.4 L 680.3,467.4 L 680.3,538.3 L 765.4,538.3 L 765.4,467.4 L 722.8,467.4 z" /><g
id="g361"><path
id="path363"
style="fill:none;stroke:none"
d="M 722.8,467.4 L 680.3,467.4 L 680.3,538.3 L 765.4,538.3 L 765.4,467.4 L 722.8,467.4 z" /></g><g
id="g365"><text
id="text367"
transform="matrix(1,0,0,-1,693.6,496.6)"><tspan
id="tspan369"
sodipodi:role="line"
y="0"
x="0 12.906 16.902 25.902 35.801998 39.798 49.806"
style="font-size:18px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Display</tspan></text>
</g><path
id="path371"
style="fill:#99ccff;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 609.4,467.4 L 566.9,467.4 L 566.9,538.3 L 652,538.3 L 652,467.4 L 609.4,467.4 z" /><g
id="g373"><path
id="path375"
style="fill:none;stroke:none"
d="M 609.4,467.4 L 566.9,467.4 L 566.9,538.3 L 652,538.3 L 652,467.4 L 609.4,467.4 z" /></g><g
id="g377"><text
id="text379"
transform="matrix(1,0,0,-1,574.7,522.7)"><tspan
id="tspan381"
sodipodi:role="line"
y="0"
x="0 4.1849999 12.57 16.754999 25.139999 30.135 38.52 46.110001 50.294998 53.685001 60.990002"
style="font-size:15px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Interactive</tspan></text>
</g><g
id="g383"><text
id="text385"
transform="matrix(1,0,0,-1,577.9,506)"><tspan
id="tspan387"
sodipodi:role="line"
y="0"
x="0 4.1849999 12.57 16.754999 25.139999 30.225 34.41 42.794998 50.294998 58.68"
style="font-size:15px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Interface </tspan></text>
</g><g
id="g389"><text
id="text391"
transform="matrix(1,0,0,-1,594.7,489.3)"><tspan
id="tspan393"
sodipodi:role="line"
y="0"
x="0 8.3850002 16.77 25.155001"
style="font-size:15px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">and </tspan></text>
</g><g
id="g395"><text
id="text397"
transform="matrix(1,0,0,-1,581.4,472.7)"><tspan
id="tspan399"
sodipodi:role="line"
y="0"
x="0 10.8 19.094999 27.584999 31.77 36.764999 45.150002 48.540001"
style="font-size:15px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#555555;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:ArialMT;-inkscape-font-specification:ArialMT">Controls</tspan></text>
</g><g
id="g401"><path
id="path403"
style="fill:none;stroke:#ff3333;stroke-width:5.02843714;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="M 218.3,524.1 L 449.3,524.1 L 449.3,453.2 L 722.8,453.2 L 722.8,467.4" /></g><g
id="g405"><path
id="path407"
style="fill:none;stroke:#000000;stroke-width:5.02843714;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
d="M 510.2,339.9 L 524.4,339.9 L 524.4,502.9 L 566.9,502.9" /></g></g></g></svg>

After

Width:  |  Height:  |  Size: 31 KiB

View file

@ -0,0 +1,171 @@
GUI Proposal by Alcarinque
==========================
:Author: Francisco G. Rodriguez
:Date: 2008-05-07
This are some of my ideas for the interface of Lumiera. Some of this ideas are
just things I saw in the GUI brainstorm and my intent is to bring them together.
I will be adding images and more ideas, but I need some feedback because maybe
this gui is only good at the work I'm used to. If you find this is no good for
you, please write me telling me why so I can think a better way to do it.
General
-------
* The GUI must be configurable. A lot of different tasks can be done using a
NLE, and we cannot make all of them accesible at the same time. This means allow
changing keybindings, windows/tiles positions, and colors. Just like ct wrote,
saving them in the project file, etc.
* If we use a custom api for the gui, we should allow themes(or changing colors
from a preferences dialog), and if we use gtk or qt, each user could use the
program with his custom theme. (Done)
* We could provide presets for keybindings/UI copying the behaviour of others
programs. For example make it behave like cinelerra 2.0.
* If we use tiles and multiple windows, we should allow these to be created
while using the program, like blender. Each tile should have a little icon to
allow changing the module the tile is showing, and clicking on a border would
allow to divide/merge.
* All icon shortcuts, and toolbars can be hidden alowing a workflow using keybindings.
The Gui has to be divided into indepent parts or modules that will communicate
each other. Each module can be developed separately, making easy correct bugs,
and add new functions. Of course this modules I am talking about, are not the
modules described in the architecture overview. This is the gui, which is an
abstraction of the real program.
image::{imgg}/Alcarinque.proposal.png[Alcarinque's GUI proposal]
Here I made a sample of the architecture of the UI. Please don't take this too
seriously, it is just a draft so you can understand the workflow. I haven't
thought how this will communicate with the proc layer or backend.
Modules
-------
* Main Menu
- It doesn't have to be a menu.
- Contains a a way to manage proyects, render as movie, setup the preferences,
customize the UI, manage the others modules, and capture a footage.
* Node Compositor
- This is a new feature that I think is very important because it allows a lot
of new special effects.
- Also it will bring a lot user contribution with the sharing of _node presets_.
. Just think of this... I have a footage of a kid playing with some red stick.
. I add this as an _In_ node. Then connect its output to a _Glow_ node.
Also connect the output of the _In_ node to a _RGB Curves_ node which I use
to filter a certain tone of red. The output to the curves is sent to the
alpha input of the glow node. The output of glow is sent to an _Out_ node.
. I save this node layout as a preset, a file called `lightsaber.np`. I go
to the Lumiera's site and share it so everyone can use it, improve it.
- Lumiera would just provide basic but poweful nodes, which would be useful
to construct very complex effects.
- There are audio and video nodes some of them can interact. See below.
- Nodes could be gruped and used as another node. A group of nodes is a
_Node layout_. When created, it appears in a tab in the media library.
Each node layout has one or more _In_ and _Out_ nodes, that let it
communicate with the others objects.
. The In node brings an input from a file and converts it into an audio/video stream.
. The Out node transforms a stream into an image drawable into the ``canvas''.
It has options like transform(position, scale, rotation) and opacity. Also
it saves a In/Out positions, relative to the internal node layout time. This
is to be able to have multiple instances of the same node layout but showing
different parts of the stream.
- Transform trayectory is shown in the interactive interface of the visor. Of course if the strip/node layout is selected.
- Opacity keys and level is shown above the strip(like cinelerra).
- If it is an audio out node, the variables are volumes for each channel.
- Each node has some parameters, these are keyable. When selecting a node,
curves for each parameter are shown in the node options module.
- Nodes should be easily programmed, and adding them should not require
recompilation of the whole program. Maybe there will be an exception to
this for the In/out nodes, etc.
- Nodes can also generate, for example a FractalExplorer node, a waveform
node (to convert audio to video), oscilators, noise, etc. For example, we
could drive a brightness/contrast node with a one dimension noise generator,
to obtain an scene with lightnings or broken lamps like “doom”
* Sound
* Media Library:
- It can be tabbed or grupped to make organization easier.
- When selecting files, the images sequences like `image0000.jpg`,
`image0001.jpg`, `image0002.jpg`, etc should show like +image[0-3000].jpg+.
- It should display the properties of the media, like resolution, fps,
bitrate, etc. Maybe in each clip or in a container.
- Be able to select for a list or a thumbnail or waveform preview.
- In each clip there is a preview button.
- Maybe add an option to “make a new clip from this clip” to change things
like fps, size, codec, etc. Just a wrapper for ffmpeg or something.
- You can drop the clip in the node compositor as _In_ node, or in the
timeline as a stripe. Doing the latter, will create a node group with the name
of the clip, that will have an “In” node(pointing to the file) connected to an
_Out_ so that the file is seen by the timeline.
- When we import a clip it should create a proxy. We don't use the original
clip anymore until render.
* Timeline
- Should provide a palette with tools like knife, in/out points, etc that can
be hidden. This could be achieved using a ``no header'' option like... again...
blender. I'm open to new ideas about this
- Scaling the clips vertically could be a good idea, especcially when working
with too many tracks. Using an amplifier tool could do the magic.
- Should allow tabbing, to have more than a timeline at in a project. We can
create a +{scene-1, scene-2, scene-3}+ timelines and then mix them in a
fourth timeline called ``film'' as if they were simple strips...
* Viewport
- The viewport should be interactive. Maybe a key toggle to allow panning and
zooming. Clicking on it should make the clicked clip to transform. Being able
to keys in the current keyframe to things like rotation, translation, and
scale. Maybe opacity with the mouse wheel.
- Clicking on the clip the first time, will add a transform node before its
out node. This transform node, has as input a time curve node, which will
be keyframmed.
- Should allow seeing the result of the current timeline, or a custom media
library element.
- Should allow setting In/out points to allow inserting in the timeline.
- Transform trayectory is shown in the interactive interface of the visor.
Of course if the strip/node layout is selected.
* Palette
- For custom common tasks, like Maya's toolbar.
* Effects and Transitions
- A section where we can drag and drop nodes and transitions to the node
compositor/timeline
- Transitions can be added in both, timeline and node editor. I'm open to
new ideas about this
- Droping a node on a stripe would add it before its out node, Using the
nodes, default connections. This way the program can be used as a normal
NLE or a compositor in a seamless way.
* Options
- Shows the options for the current node layout the one selected in current
timeline. What happens when we have two timelines modules showing different
timelines? Each options modules has a bar to select what timeline is using.
I don't understand why someone would want two timelines modules running
different timelines, maybe when selecting in one module the others could
switch inmmediatly, but maybe it is useful in some case.
- It would be divided into three parts.
. A list of nodes into the node layout
. The options of the selected node in the list.
. A curve timeline. A list for of the node parameters and curves for it.
Just like Blender's IPO curves.

View file

@ -0,0 +1,31 @@
GUI Proposal by Clay Barnes
===========================
:Author: R. Clayton Barnes (»rcbarnes«)
:Date: 2008-05-21
-> https://www.hci-matters.com/blog/2008/05/21/archives/41/[original blog entry]
.About the Author
***********************************************************************************************************
*Clay Barnes* holds a B.S. in Computer Science and a B.A. in Linguistics from the University of Arizona,
and an M.S. in Human-Computer Interaction from Rensselaer Polytechnic Institute.
For the last year and a half, he was the User Interface Architect in GE Energys Software Innovation Team.
He previously worked for Intrigo as a User Experience Designer while living in Tucson.
***********************************************************************************************************
Ive pulled together some drafts of my ideas for the design of the timeline portion
of the Lumiera non-linear video editor (hopefully, the successor to http://cinelerra-cv.wikidot.com[Cinelerra]).
The un-annotated version::
image:{imgg}/Barnes.proposal.png[
"Lumiera UI proposal",width=300,
link="{imgg}/Barnes.proposal.png"] +
(click to enlarge)
The annotated version::
(explaining some of the finer points)
image:{imgg}/Barnes.proposal-annotated.png[
"Lumiera UI proposal (annotated)",width=300,
link="{imgg}/Barnes.proposal-annotated.png"]

View file

@ -0,0 +1,28 @@
GUI Proposal by Richard Spindler
================================
:Author: Richard Spindler
:Date: 2008-03-30
Node Graph proposal
-------------------
'on 2/6/2008 Richard Spindler wrote:'
I've made a little Picture about how I think the User Interface of a
yet to be named Video Editor could be presented. There is no central
notion of the camera/projector Model, which I think could be added
anywhere in the Graphs as a Node with an unlimited Number of inputs.
Automations are not yet part of the Mockup, but could be added.
Cross Bus connections would likely not be represented by Arrows in a
real UI, but rather the Bus would be adressed by Name.
The dotted Lines mean that one element expands to a different View,
for example in a new Window.
The same goes for the rectangles with the slashed outline, they
represent another View, and the connection from the timeline to the
compositing nodes will be by Name, and not by arrows. Default Names
would be "Video Track #1", etc.
image::{imgg}/RichardSpindler.proposal.png[]

View file

@ -0,0 +1,13 @@
GUI Concept Proposals
=====================
//Menu: sort children
Over time, we got several UI proposals and design contributions.
Since webpages tend to disappear after some time, we took the liberty
to incorporate some of these contributions in our documentation tree.
* link:AkhiL.html[AkhIL]
* link:Alcarinque.html[Alcarinque]
* link:Barnes.html[Clay Barnes]
* link:RichardSpindler.html[Richard Spindler]

View file

@ -0,0 +1,317 @@
GUI Brainstorming Reviewed
==========================
:Author: JoelHoldsworth
:Date: 2009-01-24
State of the GUI
----------------
image:{l}/media/img/design.gui/screenshot090124-resources.jpg[Screenshot 090124]
Updated 18/01/09
Done
~~~~
// AsciiDoc doesn't support strikethrough text so I left this as is -- daylife
* Tiled Windows +
One Window can be tiled (horizontally/vertically) giving areas where screen elements can be placed (see blender)
* Multiple windows +
Can open multiple windows on one head and (optionally) tile them as above
-- link:ct[] [[DateTime(2008-02-07T20:42:54Z)]]
* My personal preference would be to produce the GUI in C++ with Gtkmm. Gnome is the most popular desktop for Linux, and GTK now has good support both for Win32, Mac and KDE (except that GTK on Mac still needs X11, probably for some more time)
* This sketch shows the GTK docking system, as seen in Anjuta (and to some extent in Inkscape). The GTK docking system is like a tiling window manager in a window. This allows the layout of panels to be totally rearranged, or even detached into floating windows. These floating panels can be stuck together in a single child window. This would be a perfect way to span the workflow across 2 screens. For me, it's this feature that most attracts me to GTK.
Reviewed Ideas
--------------
High Priority
~~~~~~~~~~~~~
* IMHO it's much better to make an interface out of standard bits (controls, fonts, colours) wherever possible. We really want to make Lumiera "like other apps", rather than making our own unique GUI elements just for this project - the way Cinelerra does. This makes it quicker for new users to begin work, and feel comfortable.
* Tango style icons mean the Lumiera will look consistent with Gnome, Windows, Mac and KDE - and the rest of the free desktop applications.
* Stealing ideas from Windows Movie Maker, it seems better to display transitions and filters in a way that shows the user what the filter will _do_ to the video/audio, rather than using metaphors: like George Bush=Unsharp in Cinelerra.
* A good entry level gui together with an advanced key driven system like about blender (not so much the ui)
- Yes Blender's UI isn't that great a model to follow (though there is some good stuff in there). I agree about good keyboard support. A good place to start would be the standard <Modkeys>+<Letter> accelerators, as well as context menu mnemonics. We should be able cover the entire command set with the these. I don't see us needing anything more advanced than that.
-- link:JoelHoldsworth[] [[DateTime(2008-07-22T20:48:03Z)]]
Medium Priority
~~~~~~~~~~~~~~~
* Fullscreen Support +
Windows can be made fullscreen with no decorations (but tiling left intact)
-- link:ct[] [[DateTime(2008-02-07T20:42:54Z)]]
- Comment: This can be done with relative ease. We should add this feature.
-- link:joelholdsworth[] [[DateTime(2008-07-21T21:58:48Z)]]
* Work well with tiling window managers +
I propose that the future Lumiera GUI is designed without too much (or anything) about the user's screen apart from what is acceptable based on the X11 protocol(?) in order to work well with tiling window managers. The main problem to watch out for is assuming specific dimensions. The nature of tiling window managers is that most of the time, the windows without focus are dramatically downsized in one or two dimensions. This causes poorly designed GUIs to behave strangely, sometimes as bad as constantly jumping between layouts and thus causing unnecessary CPU load.
-- link:MichaelPloujnikov[] [[DateTime(2008-04-14T22:29:12Z)]]
- Comment: As much as anything this is a case for good testing on tiling window managers. People who use them need to do this, and file bugs, or better yet patches. It would be good for me to start using one as well, I think.
-- link:joelholdsworth[] [[DateTime(2008-07-21T21:58:48Z)]]
* Window configurations can be stored/restored in customizable presets and are part of the project (see blender again)
* Jog feature +
A jog tool is a sliding ui element that when clicked and held, will play the video at a certain rate as the mouse drags left or right. As the mouse drags the the left the video plays forward faster (It should advance very slowly at first.). It acts the same way when the mouse drags to the right, except that the video plays in reverse. Again, it can be tedious trying to make frame-accurate cuts to long video files. Without a jog tool it makes it more tedious to get to the exact frame you want to cut on because you must scan through, then click the next frame button half a dozen times. A jog tool would remedy this because one could easily vary the playback rate, even reverse it, zeroing in on the frame much more quickly. Together these two features could really increase the speed at which one can edit precisely in Cinelerra.
- Comment: This idea seems feasible, it could be worked together with cehteh shuttle slider proposal.
-- link:joelholdsworth[] [[DateTime(2008-07-19T19:42:04Z)]]
* most numeric value entries (sliders, spinbuttons) can be changed when hovering the mouse over it and turn the scroll wheel (maybe with an additional modifier key?) -- The scroll wheel is accelerated depending on how fast it is operated by the user, snapping it slowly gives frame/interval precise increments, turning it faster will exponentially increases the increment (2,4,8.. frames per click)
-- link:ct[] [[DateTime(2008-02-07T20:42:54Z)]]
* "Render AS" +
The *process for creating a DVD* where Video and Audio have to be rendered separately is laborious. A script could easily handle this, and make the use of the program so much easier, attractive, inviting, productive, time efficient, bla bla. All the user needs to do is set the parameters and file name (once) and then "do". Many commonly used formats for saving could be saved as presets that completely avoid all the questions (say in the "File" drop down menu, as a customizable "Render AS" choice). This could also be done for HDTV, iPod, Ringtones, VCD, Various formats that give the best performance for uploading to Youtube and all the other video sharing sites.
+
When a whole magazine article(s) can be written about the task of exporting a file to make a DVD, you know the process is a long one. mmm ... Any well paid journalists out there want to sponsor programmed task efficiency? - "NO?" - oh well.
-- link:Tree[] [[DateTime(2008-05-07T16:44:00Z)]]
- This could probably be solved by having a series of format presets in the Render dialog. The default set could contain settings for the values you mention. We could even allow the user to save their own presets. Cinelerra already has this functionality - these are called profiles, but it doesn't come with a default set at all.
-- link:JoelHoldsworth[] [[DateTime(2008-07-24T16:13:28Z)]]
* Reduced quality previews +
There needs to be a way of giving the user the choice to see the movie at full quality - computationally expensive, or at reduced quality for times when full framerate would be impossible.
* Track View Height +
Let the user have more flexibility over the track view height. Some tracks can be set to minimal, others to visible (but basically iconic), others enough to see features, and one or two to good resolution. Some may even be blanked.
+
The track view height could be individually selectable , for example, by changing the "draw media" icon from toggle mode to drop down menu. The drop down selection options could include "don't show", followed by track sizes as per the drop down menu at the bottom of track view.
-- link:Tree[][[DateTime(2008-05-07T17:30:00NZ)]]
- Comment: Yes, I was thinking about this idea myself. At first I was thinking of just allowing the user to expand or collapse the track with a +/- button. But then I wondered if it would be good to have the track completely sizable. My current thinking is the best way would be to have it sizable but with a kind of snap-to-grid behaviour so the whole thing doesn't become really messy.
-- link:JoelHoldsworth[] [[DateTime(2008-08-04T16:03:24Z)]]
+
--
* Ardour provides an example for this: the track height can be changed (by buttons or with the mouse wheel + modifyer key), but there is only a fixed set of possible track heights, some of which have a preconfigured layout. For example, in "smallest" size the track head shows only the track label without any buttons and the track is reduced to a tiny waveform.
-- link:Ichthyostega[] [[DateTime(2008-08-08T15:18:31Z)]]
--
Low Priority
~~~~~~~~~~~~
* Multi Head +
Can open Windows on different heads of the same server, and is aware of the existence of different physical monitors (ie. Xinerama-aware)
- Comment: Xinerama seems to be a decreasingly popular way of doing multi-monitor. This probably could be implemented, but I don't have a Xinerama based setup, and I've never talked to anyone who does. I use link:TwinView[], and it seems like a more practical way of doing dual screen to me. Surely RandR based multi-monitor is the main need today.
-- link:joelholdsworth[] [[DateTime(2008-07-21T21:58:48Z)]]
+
--
* Multi-Head != Xinerama ... This is very important and quite common, We want to support monitors driven at the native Video Format (resolution, framerate, interlacing, overscan, ....). For a professional setup this is really required!
-- link:ct[] [[DateTime(2008-07-22T07:11:11Z)]] +
Xinerama and twinView test comparison http://www.phoronix.com/scan.php?page=article&item=387&num=1[]
--
* Automatic Clip Creation based on video content. +
When scanning through an hour long video clip, it can be tedious to go through it all making clips. It would allow the user to get right to work if Lumiera could split the video into clips based on scene changes. Each clip would begin at precisely the frame the current shot begins and end at the last frame before the next shot. As long as the user could then edit these clips on the timeline, this would decrease the time spent sifting through the raw footage.
- Comment: This seems like a good idea, and quite easy to implement. I think that when we get the video-capture and media manager code working this would a be a good subproject for someone to take on.
-- link:joelholdsworth[] [[DateTime(2008-07-19T19:42:04Z)]]
* Import and Export SMIL files +
Many current cinelerra users probably use kino for their capturing of DV. it uses less resources, so less system demand during capture. Good display monitor while capturing. Open Movie Editor is a good multitrack editor that can share Kino's SMIL files. A good progression in complexity of editing is start with kino, move to OME, then cinelerra (lumiera). A really convenient way to assist stepping up from Kino is to handle the SMIL files.
+
Automatic scene detection is a great feature in Kino. The simpler editors make it easy for less skilled people to look after the selection of preliminary clips, while lumiera is used by the folks who put it all together, and finish it off.
--link:Tree[][[DateTime(2008-05-09T15:10:00NZ)]] .
- Comment: SMIL is quite cool technology. It's not just a Kino thing. It'd be quite good to be able to import this standard format.
-- link:JoelHoldsworth[] [[DateTime(2008-07-24T16:41:02Z)]]
More Discussion Needed
~~~~~~~~~~~~~~~~~~~~~~
Timeline
^^^^^^^^
* Sparse Timeline +
Make the timeline view _sparse_, that means the time on top is not continuous anymore but \'boring' sequences get omitted and \'interesting' sequences get displayed, probably even stretched to cover at least a single thumbnail.
+
This needs an ui (menu or whatever) to turn this feature on and some selection which events the user is interested in (scene cuts, transitions begin/end/mids, keyframes (begin/mid), labels, ...)
-- link:ct[] [[DateTime(2008-05-21T13:46:51Z)]]
- Comment: Do you think we could use view splitting to accomplish this? You can see this sort of thing OpenOffice.org calc. Where you drag a splitter out from the ends of the scrollbar, this allows you compare 2 or 4 parts of a big spreadsheet at the same time. Implementing something like that might be reasonably doable. But if you're talking about hiding periods on the timeline, that sounds a lot less easy to me, and it feels like a bit a bit of an odd thing to do. What do you think ct?
-- link:joelholdsworth[] [[DateTime(2008-07-21T21:58:48Z)]]
+
--
* No, view-splitting is something different, usually one splits the timeline to few places (2 or 3). Managing those splits requires a lot manual interaction (resizing the splits, zooming into the right time resolution, scrolling to the desired range, ...). In contrast this 'sparse' timeline does that all automatically by possibly adding hundreds of those split points (there should be no split bar on the gui). One just has to select POI's with some menu or such. Well and the timeline ruler needs to adapt to it, that might be tricky
-- link:ct[] [[DateTime(2008-07-22T07:11:11Z)]]
--
* "Sparse Timeline" is in Trackview" - see Track view section lower down the page +
This is the kind of features I have suggested in the Trackview section lower down the page. I like the name you give it - "Sparse" because it allows the user to not have to bother viewing OR scrolling past all the stuff in between two end points (or more items) just to tweak the ends of a segment. But I would emphasize that instead of reducing the width of the timeline because of the narrow time span needs for the one task, that more tasks can be carried out in the same view. This is because the view just misses out all the stuff in between, for each task.
+
I am playing around with a few thoughts and maybe might attach an image of how it might work. But in conjunction with "tabbed views" it would result in the convenient ability to display all the work areas in a concentrated display, meaning a whole lot less scrolling around, and clicking to bring windows to the foreground.
-- link:Tree[][[DateTime(2008-05-23T16:59:00NZ)]]
- Comment: See above. With regards to tabbed based UI in the timeline view, I do have this in mind, and it seems reasonably straightforward to allow two tabs which contain views of the same timeline - just scrolled to different places.
-- link:joelholdsworth[] [[DateTime(2008-07-21T21:58:48Z)]]
* Clip Mode +
This would be a clone of the clip mode in Apple's iMovie. In this mode, users would be working with discreet (read untrimable) clips. Dragging a new clip into the sequence would cause it to be inserted between two clips, not overwriting them. Once all of the clips are layed out to the users satisfaction, they could then switch to the normal multitrack mode and trim the heads and tails of the clips from there. -- link:rexbron[]
+
The advantage to this sort of work flow is that it allows an editor to very quick create an assembly cut of a film. During this phase of editing, the editor and director are examining the takes and deciding on which ones they like best. As such, it makes sense to be able to easily change the order of clips and add new ones to see how the shots fit together.
- Comment: This sounds a bit odd in some ways. But I'd be interested to find out more. I'll probably do some research into it at some stage. Maybe you can post some screenshots.
-- link:joelholdsworth[] [[DateTime(2008-07-21T21:58:48Z)]]
* I propose an assembly system where the source material is left untouched where effects are added on the fly similar to html and dtp packages. In this system the system is linked together using an node system similar to gstreamer and jack.
- Comment: Yes the core of lumiera will work on a scen graph of connected nodes, and we want to provide the user with a way of using that power. We need to discuss how node wiring and the timeline-track tree go together. Note that node wiring only seems to make good UI when the node graph is fixed for the duration of the whole project timeline. We need to work out how this fits together with the timeline tree, and if metaclips help this problem at all.
-- link:joelholdsworth[] [[DateTime(2008-07-21T21:58:48Z)]]
Comment to all those sparse timeline and clip mode proposals: The benefits of those are obvious, as they directly correspond to the working with storyboards. Almost every serious movie uses storyboards to quite some extent. But for the implementation, I'd propose not to see it as an alternative view/mode of the timeline. Rather, I'd treat it like a media/asset folder. Probably we'll have the ability for the user to group the media asset into various "bins" (virtual sub folders). Moreover, pre-cut clips appear as clip assets as well (similar in Cinelerra and most other video editors). Thus, we just need a function to "play" such a clip bin. It could be implemented by defining a ordering on the clips in the bin (from top to bottom and from left to right?). Then, this function would create an transient EDL on-the-fly, containing just these clips, and hand it over to the engine for building/playback. Thus, the user can see his "draft-cut" played back in real time, and thats all what is really needed. When satisfied, he could mark the clips in the bin and drag them to the timeline, which would add them in the same order starting at the current position. I don't think we need to go though all the pain of creating an separate, dedicated UI for this purpose.
-- link:Ichthyostega[] [[DateTime(2008-07-27T23:20:19Z)]]
Widgets
^^^^^^^
* Generalized Fader
+
image:images/fader.png[fader.png]
+
All faders are the same kind of custom widget, that is:
a. a slider to adjust the value with the mouse
.. a level indicator (progress bar?) reflecting the actual level of the signal
.. a spinbutton/text entry to add a value with the keyboard
.. a label showing the measurement unit and other information
.. a popup menu to configure this widget itself
+
--
* enable/disable the things above
* set start and end values (the application gives an absolute allowed range)
* change the measurement unit (byte, percent, dB, ...)
* change between linear/logarithmic behavior
* snap at specific intervals
* horizontal/vertical slider/level
* adaptive scroll wheel (see below)
--
+
for the application all faders provide a float (or double) value, nothing else.
-- link:ct[] [[DateTime(2008-02-07T20:42:54Z)]]
- Comment: I think making some kind standardized fader widget is probably going to be necessary for this project. We need a good way of combining together the artistic "genstural" elements of a slider widget with the precise numerical behavior of an edit widget, and it needs to be compact - the UI will have a lot of these. I'm not sure how often we'll need to see a level meter with these. Most of the time a control is either an input or a readout - very rarely both. Generally speaking I'm against the idea of having a popup menu to configure this widget. I believe that it should be configured to work in a way which is user friendly by default. There may be many of these widgets and asking the user to configure each of these before they behave well seems a bit unfair to me.
-- link:joelholdsworth[] [[DateTime(2008-07-21T21:58:48Z)]]
+
--
* I agree, the defaults should be reasonable set per-item, that will be that the meter is in most cases off and the spinner will be off on many cases too. I tried to show whats needed for the most generic case with all bells and whistles. When we generalize this we need to support all eventualities even if turned off by default. Note that some things could be done in tooltips, see below "about tooltips and statusbar", the above fader is just an early proposal/brainstorm
-- link:ct[] [[DateTime(2008-07-23T09:41:25Z)]]
--
* Magnifying Glass for the Faders +
Faders should have a "magnifying glass" mode, which can be activated by a key combination or modifier key. When activated, you can fine tune the current value: The step increment is lowered ideally to the real limit of the underlaying parameter, or, if this is too much, at least it should be much smaller than anything you get by dividing the possible value range by the fader length in screen pixels. In this mode, the fader doesn't cover the whole range, rather it is centered at the current value. Changing the value by these small increments should give an obvious visible feedback. Ideally, an accompanying automation curve display will switch to the extreme vertical zoom as well. And it's important that you don't have to zoom, you enter/leave with one keypress.
+
Partially, this is covered by the Adaptive Mouse Wheel too; but, especially when working with sound, the problem is that the parameter range cover several orders of magnitude. For example, even 16bit PCM sound has a volume parameter which can be adjusted in 32768 steps, and yes, there are situations when these fine steps make an audible difference, while most software faders give you not much more then a view hundred subdivisions even under optimal circumstances.
-- link:Ichthyostega[] [[DateTime(2008-02-07T22:34:08Z)]]
- Comment: This is definitely a problem we need a solution to. Is modifier keys the most discoverable way of doing it - I'm not sure. We need ideas for this (see below).
-- link:joelholdsworth[] [[DateTime(2008-07-21T21:58:48Z)]]
- This concept of "magnifying faders", is well explained in http://thorwil.wordpress.com/2007/05/01/fan-sliders/[Thorsten Wilms Fan-sliders Article], the Article also links to an implementation.
-- link:oracle2025[] [[DateTime(2008-02-08T00:40:05Z)]]
- Comment: In one sense this is bad because it's so incredibly non-standard. Bun in other ways it seems to me like a rather ingenious solution to the problem. Aparently Ardour has these. I must investigate.
-- link:joelholdsworth[] [[DateTime(2008-07-21T21:58:48Z)]]
Scripting
^^^^^^^^^
* Usability (ease of use) - mouse clicks and motions, inputs decisions, etc required to achieve tasks. Macros are really handy for allowing the user to speed up repetitive tasks that the program designers have not anticipated and made easy to do from the outset. Macros can be shared on a central web site. Plus developers can look and see what the macros are being used for, as this gives a very important indication of where vital tasks are.
-- link:Tree[][[DateTime(2008-05-07T16:44:00NZ)]]
- Comment: We need to have some discussion about scripting. To do macro scripting we'll need to implement a DOM interfaces etc. into 2 or even all 3 layers of the system. If we want to do this, then we'll need to begin planning for it early. We have talked already about making scripting the movie itself AviSynth style. Both are worth talking about.
-- link:JoelHoldsworth[] [[DateTime(2008-07-22T21:58:22Z)]]
+
- See also rcbarnes compound filters proposal.
-- link:JoelHoldsworth[] [[DateTime(2008-07-24T16:25:57Z)]]
Others
^^^^^^
* Time estimates for lengthy Tasks before committing to the action. +
Handy to have time estimates for lengthy task indicated even before committing to the task. Also an estimate for the % increase or reduction in time of adjusting parameters. So you can make a good tradeoff between the result and and the time taken to get it. When a task is carried out, measurements are made to improve the accuracy of future guesses.
--link:Tree[][[DateTime(2008-05-07T21:34:00NZ)]]
- Comment: This would be quite a nice feature if we can do it. Though it's often hard to know how long something will take until you start doing it. For example estimating the time to render a 1000 frame animation might involve rendering the first 10 frames, then multiplying that time by 100. Problem is that could potentially be quite complex to set up - especially when we're working with render farms. The backend guys would need to think about this I think.
-- link:JoelHoldsworth[] [[DateTime(2008-07-24T16:24:50Z)]]
Joelholdsworth is Skeptical
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Multi server +
Display GUI components on different Xservers, some critical components (GL rendering etc) might be only supported on local displays
-- link:ct[] [[DateTime(2008-02-07T20:42:54Z)]]
- Comment: This doesn't seem like a very common use case. I can't see any immediate advantage in doing this, and I'm struggling to think of a scenario where this would be helpful.
-- link:joelholdsworth[] [[DateTime(2008-07-21T21:58:48Z)]]
+
--
* Having more than one workstation each driving a display on its own, getting more bang. But I agree this is not a important feature and rather a corner case.
-- link:ct[] [[DateTime(2008-07-22T07:11:11Z)]]
--
* 3x3 Menus +
Have a mostly quadratic 3x3 dialpad like popup menu poping up so that the center is the mouse position (adjusted when near screen corners). The middle field is always the close/cancel functionality and the 8 fields around offer the menu entries. Navigation can be done by mouse, cursor keys or numpad! Menu entries can open 3x3 submenus again, either incremental so that closing brings you up to the higher menu or exclusive that closing aborts the whole menu.
-- link:ct[] [[DateTime(2008-02-07T20:42:54Z)]]
- Comment: Cehteh really want this feature. Personally I'm skeptical. It seems clumsy and non-standard to me, and not good in terms of command discoverability, so I don't want to implement it. But then he does seem to want it pretty badly, so I'm a bit cautious about putting it straight in the "Won't Implement" category.
-- link:joelholdsworth[] [[DateTime(2008-07-21T21:58:48Z)]]
+
--
* not only me, but ichthyo and simav too and anyone i talked with liked this idea but you
-- link:ct[] [[DateTime(2008-07-22T07:11:11Z)]]
--
* User Precautions get built out of user interface and into program.+
When attaching such and such effect to a track, disable "play" before attaching it, then re-enable play aft attaching it. (we don't tell you this before hand, and we never will, unless you ask the question and search the net, then you might find out in the "secrets manual", And you'll have to remember this (always)!! If there are circumstances that apply to an effect (or for that matter any other part of the program), then the feature could have a flag in it that warns the system to take note of it, and it then reports what its requirement or tweak feature is, so the system can automatically handle it the best way. (A sort of OO process handler). This not only saves potential lengthy wastes of time, but saves concentration on sideline issues, speeds up work, adds to reliability and good time user experience.
--link:Tree[][[DateTime(2008-05-07T21:34:00NZ)]]
- Comment: I'm not sure I quite understand what this is about. Your explanation is a bit hard to read.
-- link:JoelHoldsworth[] [[DateTime(2008-07-24T16:24:50Z)]]
+
--
* I wouldn't even be skeptical, I am against such a proposal. Any feature we add should just work, without crashing the application and trashing the users efforts. If a feature doesn't work, it needs to be fixed, instead of automatically warning the user that this feature is broken. The fact that for Cinelerra you need the "secrets" tells quite a lot about the state of affairs regarding Cinelerra, and because we wanted to change this, Lumiera was born. ;-)
-- link:Ichthyostega[] [[DateTime(2008-07-27T23:04:42Z)]]
--
May Implement Some Day
~~~~~~~~~~~~~~~~~~~~~~
* Widget overlay/Fullscreen +
Some Widgets can be made half transparent and overlay video giving a head up display editing while the video is at native resolution in background.
Window configurations can be stored/restored in customizable presets and are part of the project (see blender again)
-- link:ct[] [[DateTime(2008-02-07T20:42:54Z)]]
- Comment: This is difficult to do. XVideo and Gtk don't really mix. But I can't think of any controls that need to be overlaid.
-- link:joelholdsworth[] [[DateTime(2008-07-21T21:58:48Z)]]
+
--
* Would be nice but not a primary feature. I'd rather think about some some special on-screen-menu overlay, not necessary gtk (libosd?) maybe this can be implemented with OpenGL overlay or so. As noted before, having a monitor which runs on the native Video resolution is a requirement. Giving this Monitor some (limited) GUI features, like mask editing or other simple manipulations gains extra points. Not a primary/important feature but I'd rather like it seen as "Will implement _someday_" The window configuration customization should be its own point, I think thats easy with GTK (Gimp does that) adding a small Configuration management GUI shouldn't be hard.
-- link:ct[] [[DateTime(2008-07-22T07:11:11Z)]]
--
Won't Implement
~~~~~~~~~~~~~~~
-> link:GuiBrainstormingWontImplement.html[Review of features we won't implement...]

View file

@ -0,0 +1,147 @@
GuiBrainstorming Reviewed - Won't Implement
===========================================
:Author: JoelHoldsworth
:Date:2008-07-23
* Help feedback for quality management +
Sometimes help files and tutorials are improvable. Keeping track of which help is to which amount useful for a majority of users will provide data about which help files are improvable. It will also provide data about which features most often users use help and might be candidate for usability consideration. like: []solved my problem []got me on the right way []needed to find help elsewhere []problem not solved
- This is surprisingly hard to implement (I think), and in a sense it's already obvious to us whether the docs are quality - filled with nice graphics, simple steps, and lots of clear information or whether they need improvement. This feature might have some use on the website.
-- link:JoelHoldsworth[] [[DateTime(2008-07-23T20:47:35Z)]]
* Suggest an improvement Feature - for users to help improvement +
Just like the "Help" feature suggested elsewhere, in which the user can edit the help file as they go, so could the user be able to make suggestions to improve the program. Able to get a panel or window grab, and draw arrows lines to show "where" they are talking about. Online linking - There could also be the facility to click on an email link to send a request for help (want to engage in dialog, rather than just notify - without need for response). Or a relevant search is automatically generated for the forum, chat room, faqs, helpdesk, documentation. Or get sent to a link:BrainStorming[] page like this one (specifically for the panel they were in).
-- link:Tree[][[DateTime(2008-05-26T12:01:00NZ)]]
- This isn't really a GUI issue - much of this is more for the website, which the GUI will probably link to from an item in the help menu.
-- link:JoelHoldsworth[] [[DateTime(2008-07-23T20:45:00Z)]]
* Help System - rolling tips and tutorials +
Sometimes, when a beginner is using the program, they just sit back and look at the general picture. It's a behaviour that gets down naturally. It looks like a "break", but going through their minds are questions like ; "Am I doing this efficiently?", "What would make this easier, and is there already an easy way to do it in the program?", "How long do I think this will take, and what can I do to make it in time?", and much more. Sit back, look at the whole screen, maybe cruise around the menu, conceptualise the project and steps involved - it's a kind of task oriented learning - on the job (self) training.
+
The closest thing so far to something which takes the opportunity to make use of this "looking at the wider picture", is the tips that come up at the start - a kind of "while you are doing something - we thought you might find this helpful".
+
Because of the creative effort needed when composing video projects, there is quite a bit of vision based thinking. It is during these times that a help or instructional item could be presented to the user. (I am not talking pop-up advertising). Then user could set aside space for a window that scrolls help text, flashes tips, plays video tutorials or help. This help function could be optionally set to go on all the time, begin after x seconds of inactivity, or be manually triggered. It might even be a kind of screen saver - leave it running while having a coffee break. But what it does, is run a whole heap of options and new information past the user, in a low prompting mode, to a degree that they are prepared to have the minor distraction.
+
If it was context sensitive, then it would provide relevant information, similar to having a tutor or an expert leaning over your shoulder, explaining further possibilities and applications.
+
Video tips and Tutorials could be available via Youtube, which also doubles as promotion for the project. Users could choose to download groups of videos on selected topics.
-- link:Tree[][[DateTime(2008-06-11T17:04:00NZ)]]
- If the user stops to thing I think we should give them some peace while they get their thoughts together. I'm sure if they want help they'll ask for it. Remember how annoying Clippy was in MS Office? :-P
-- link:JoelHoldsworth[] [[DateTime(2008-07-23T20:45:00Z)]]
* Help and visual prompts use GIFs for visual cue as to time behaviour of feature. +
Icons are handy when they portray some sort of cue for the task that they do. A number of tasks in video editing are time related. It would be handy to have some form of visual que as to what the time related task does. Since Gifs can show motion, they would be very good for this task. PNGs could also do it it they were timed to cycle through their images. Example uses would be to show the difference between "track" and "stabilise" in motion tracker - a strip showing a pogo stick going along a footpath would be suitable to show the differences between track and stabilise (and could also be used to show the differences between the forms of vector calculation. GIFs could also be used to show editing functions that involve several important steps.
--link:Tree[][[DateTime(2008-05-26T08:45:00NZ)]]
- If we did want animated icons we'd be better off with MNG or a PNG image strip because then we'd get transparency. There are 2 reasons why I think this is a bad idea. 1. There's an aweful lot of drawing to be done. We already need to produce perhaps 100 high quality tango style icons for the user interface. If they're animate someone would have to draw 1000s of these, with all the quality control problems that go with it. 2. I'm not sure it's something people will find very helpful. Even if the animation only begins when we hover over the icon, it could even be quite annoying and distracting.
-- link:JoelHoldsworth[] [[DateTime(2008-07-23T20:39:36Z)]]
* Help System - available for user improvement +
_Similar to tool tip and status bar suggestion above._ A *"hover" hint / help* facility would be a major bonus. Just make the function available, the box can start with an index number, and users can type in their own help comments (either in a *help text entry management* section, or directly into the pop-up hover box - in optional help edit mode).
+
These can be pooled at a central web site in to languages, and brevity/completeness (options to links to further help, links to examples, links to video tutorials). So the developers do not have to spend time writing help files - just make it possible for the users to. The developers might like to add a few comments to the verbose files at some later point, or clear up inaccuracies. translators can also do the work for other languages. Very quickly the supporting documentation's usefulness would add to the attractiveness of the program.
-- link:Tree[][[DateTime(2008-05-07T16:44:00NZ)]]
- A wiki style approach is often an effective way to get community input on documentation. This may be a good way to get people working on it. But it's best for us to publish a tidied up documentation set and ship that, instead of creating a complex editable help system - which is vulnerable to vandalism.
-- link:JoelHoldsworth[] [[DateTime(2008-07-23T20:29:25Z)]]
* User selectable Experience Level - Task Oriented Layout +
The user could be asked to choose their experience level, and more complex options then get greyed out. The user could be asked the common tasks that the want to do, and other options could be greyed out. They can choose whether they want "grayed" out options to be available, or viewable, or not. The options which are advanced (or 2 levels greater than their current expertise level) could be "dark grayed" out and the user could have similar choices about their display).
--link:Tree[][[DateTime(2008-05-09T20:50:00NZ)]]
- Comments: I can't see any good reason for this. The user interface ought to be usable for everyone. The problem is that we want to enable everyone to be an "expert" by making power intuitively available even to beginners. The other problems is that light users might use only 10% of the functionality - but different light users use a different 10% from each other. So hiding things doesn't actually help make things simpler. It's much better to have things tidily arranged with clear descriptions etc. to help the user understand what a command might do - rather than hiding the command from them.
-- link:JoelHoldsworth[] [[DateTime(2008-07-22T22:25:58Z)]]
* SVG-based GUI elements (buttons and chevrons) could allow for easy GUI skinning and function calls since one would just have to mod an xml file to create new skins. It also means you could use code from the Webkit project for rendering the interface maybe. My practical reasoning is that if the devs wanted to work on the refining cinelerra/lumeira core technology or add plug-ins to extend its functionality, adding the GUI elements of those plug-ins might be less of a chore. It also may be a practical image format for a node-based compositing interface(if desired) because it supports embedded grouping of vector expressions. It could also be used as the basis for drawing things like masks and vector objects in the compisitor and the xml vector-values of those drawn objects could be communicated back to the programs core for updating events. (Similar to the way some more popular editor/compositors use PostScript to draw objects and place values.) It also the SVG spec supports transparency bluring and the ability to interpolate these events over time...things that can be incorperated into program beyond the the gui. Sorry for the long post...felt I needed to explain my reasoning better.
-- jb [[DateTime(2008-07-21T21:58:48Z)]]
- Comment: I am hoping that we can implement a simple set of skins for Lumiera. But we will be using the GTK based styles system, which is the standard. This allows theming to be done with a simple script file. These styles files are the more natural choice for UI theming, because WebKit is designed primarily for web, and would add a lot of unnecessary bloat to the app. Icons will be drawn as SVGs; a good choice for drawing the graphics, but these will be prerendered into PNGs at compile time as is standard practice for most free-desktop apps.
-- link:joelholdsworth[] [[DateTime(2008-07-21T21:58:48Z)]]
* Client / Server Model +
The server process will act as the master coordinator for the system, and will accept input from multiple GUI clients, and dictate tasks to multiple slave processes (even on separate physical servers). The GUI client application could be multi-platform. File transfer and communication could take place over SSH and make use of SVN for project management. Proxy editing will be the norm, due to the higher resolutions of final videos (the RED Epic will handle 5K). The entire system could easily work on a single Linux workstation, for easy adaptibility from handling home videos to expand to editing cinema films (which could benefit from dedicated GUIs to handle video, sound, etc.).
- Comment: Because the different parts of a project are so tightly integrated, it won't be possible to have one instance of the GUI that only has audio, and another that only does video etc. Moreover, the controller PC will hold the source video data. It is true that we plan to make a distributed backend, but the core and GUI layers will remain on the controller PC. It's very hard to make a distributed GUI, and even harder to make lumiera have both a distributed front and backend.
-- link:joelholdsworth[] [[DateTime(2008-07-21T21:58:48Z)]]
* Navigation Systems +
There may be several methods to make menu selections, and other choices. The Gui could be made quite adaptable/customisable. Using a "skin" approach to the Gui, would provide a system for users who are not programmers, to help develop improved user interfaces. Mouse "gestures" (may be patent considerations) are another option. The way that options are communicated with the program functions could be made so that even as yet undesigned "user chooser systems" can be added.
-- link:Tree[] [[DateTime(2008-05-14T08:40:00NZ)]]
- Comment: Allowing customization is good in some ways. But every customization has a cost; in terms of development effort, debugging, maintenance, user support etc. so one must weight up the cost/benefit of allowing the user to reprogram the UI. IMO it's better for the UI to be right rather than to allow the user to reprogram it. If there's something sub-optimal about the UI then it should be fixed - for everyone. So we should be encouraging users with programming skills to contribute the code to us rather than them all making their own little customizations for themselves. That way lumiera becomes better for everyone!
-- link:joelholdsworth[] [[DateTime(2008-07-21T21:58:48Z)]]
+
--
* I completely agree, while I have to add that we can't know about all possible workflow scenarios. In sense of workflow Lumiera should be customizeable/scriptable somehow. This might be more intrusive/costly than just customizing a theme but should be less than hacking in the C++ source and have to o recompile.
-- link:ct[] [[DateTime(2008-07-22T07:11:11Z)]]
--
* Burst frames to graphics card. +
I am not sure how the current video play system works, but speed might be increased if several frames got sent to the video card at once. The video card can act as a video cache and play them as required. The number of interrupts to the process is reduced, to much less than one per frame, freeing up more CPU time for calculating the effects etc..
--link:Tree[][[DateTime(2008-07-18T18:18:00NZ)]].
- Comment: Good idea, but not really necessarily. Firstly because XVideo is pretty fast, and the bottle neck is in rendering not drawing. Second, we can't get direct access to video RAM anyway because X abstracts it away.
-- link:joelholdsworth[] [[DateTime(2008-07-19T19:42:04Z)]]
* GUI development - flexible approach - using "Skin Methods" +
In developing a GUI, the approach would normally be for the developers to design the Gui as the project progresses, and it comes out at the end. This is not bad, especially as there is a GUI to be had. But if there is a desire (which there appears to be a healthy desire here) to try new things, and look at options, then it would be quite useful to have a development method that allows for experimentation with options, side by side comparisons and assessments. Assessments by users and developers.
+
GUI design could be available for release for whoever wants to do a spin-off project re-GUI. So a GUI gets made by default by the development team, but the _skin kit_, and _methods of activating/interaction with the "engine"_ are made available. Users can then run their own tests and some sort of concensus arrived at later as to what is considered to work well, in what sorts of different user situations (newbie, small, large/expert).
+
If there is vibrant enthusiasm for teams to work on alternative GUIs, then the developers may even avoid the need to do much of the work on GUI, and just announce what the interface requirements are - the (choices of) GUIs for some sections could be ready before the program is finished. The GUIs could be developed and discussed concurrently (or advance of) the respective program code. On the other hand the GUIs could lag behind the developemnt of the engine, but not hold the engine up. Some GUI groups could be ahead of others in some parts of the program and behind in others - the user could even choose to the GUI (widget appearance) from one theme for one part of the interface, and GUI from another theme for other parts.
+
There could be agreement between GUI teams working on different themes, to cover separate parts of the interface first, so that there is at least some type of theme for the GUI for the whole program ASAP.
--link:Tree[] [[DateTime(2008-06-05T20:33:00NZ)]]
- Comment: To achieve that sort of thing one would normally expect the project to be forked. If our architecture is any good (and I think it will be), then a Lumiera fork would have no problem attaching a different UI to the system because there will be clear separation between the layers. But I can't see any good reason to help people fragment the project. If there are problems with the standard UI then we should fix them for everyone. If people want to write code for better UI they should contribute it patches. We really don't want to encourage people to fork any part of Lumiera.
-- link:JoelHoldsworth[] [[DateTime(2008-07-22T20:56:07Z)]]
* About Tooltips and Statusbar +
Tooltips are really valuable items, they should not be wasted for simple things like brief help texts. Instead they might display the actual state of the underlying widget in a textual form (numeric+unit) with _maybe_ some hints. Long time ago I proposed for Cinelerra to add a special mode to make tooltips editable, that is with a shortcut the actual tooltip becomes a small text input field where the user can enter exact values for some things, this value is committed with the return key and leaving this mode should be really easy (as simple as just moving the mouse, ESC key).
+
The Status bar can show more information but isn't directly in the users view, here we may play help infos like available options on the mouse buttons, important keyboard shortcuts etc. take a look at \'qcad' .. xfig has also static area where it shows available (mouse) options, just not a status bar but in the upper right of the screen.
+
This might be a bit different to some common other user interfaces (M$...) but I think this is much more valuable.
-- link:ct[] [[DateTime(2008-04-08T01:26:06Z)]]
- Comment:The thing about tooltips is that one usually uses them to aid the user in figuring out what a toolbar button (which would otherwise be a crytic icon bitmap) actually does - and so in this sense they're not a waste - they help users figure out how the application works. Users expect to find those hints in tooltips, and so it's rather unkind to the user to do something different and unexpected, and so we should avoid breaking the norms if we can. The actual state of the widget should be visible to see straight off and editing that value should be allowed straight off. That functionality should not be hidden inside a tooltips. People will find it really counter-intuitive to have to edit a value inside a tooltip in order to make a change.
-- link:JoelHoldsworth[] [[DateTime(2008-07-22T21:42:32Z)]]
+
--
* My argument is, that the \'figure out' thing could be done in the status bar, thats slightly less convinient but a user who searches for help will discover it (xfig, qcad and other programs do such kinds of dedicated help places instead tooltips). Popping up Tooltips only help _very_ early beginners, for someone who is even marginally used to the programm they don't add any value anymore, yet to be at a very prominent screenspace, right at your cursor. I think thats really a waste. I want interactive tips and help, but please where they are disciverable for help, but don't waste screen estate with information one might not really need. In contrast, the numeric value of a fader is a very important thing to know, at least when you want to alter it (cinelerra does that with its round knobs). And having a direct enter mode would be even more powerful for experienced users while not disturb anyone else. This might only complement the 'generalized fader' fader above, means when the fader is configured to show only a small scroller entry (to safe screen space) then displaying the numeric value and/or offer to edit it in a tooltip would be a good way to make it precise, without needing to reconfigure the fader, taking more screen space.
-- link:ct[] [[DateTime(2008-07-23T09:41:25Z)]]
--
* Default settings after install set to most reliable and least requirements +
The program may be tweaked to get performance on PC with great graphics systems, plenty of Ram and good hard drive speed. For people with lower spec'd gear, there may be some tuning needed, just to get going. There is the likelihood that people with low spec'd gear are not so able or inclined to read up on their hardware, and "search" for help on their video editor, to find out the solution to a problem (which they may not even have much idea of what the problem is). Consequently, they are likely to give up and not use the program.
+
Everybody enjoys a program that can be easily installed, and is ready to run. Few are upset by a program that is easy to install, setup, and is ready to run. But quite a few have nothing but disappointment with a program that is relatively easy to install, no idea how to set up, won't run or crashes, and not much clue about where to get help which is much further away than a click.
+
So it would do the program a great service to be able to run on just about any gear, straight away. This means using setup defaults which are general and as universal as possible, unless the program is given some sort of intelligent hardware detection function (not a big priority at this stage as it would require more programming work and folks are busy on more important tasks).
+
The tweaking could be left for the experts to get speed, rather than the noobies.
+
The tweak options could have say three general default settings, that progressively ramp up the performance demands, so the user can try the settings to very quickly get an idea of their gears trade-off between speed and reliability. each section of settings that has options, could be laid out so that increasingly demanding options are lower down the choices or colour coded for System requirement.
+
Colour coding may be red for heavy loadings and risk, yellow for low demands, and a colour blend between. The saturation of the colour may also indicate the preference to reach at least that level with your gear, so you know how to "trade off" between parameters that your are going to tweak up. This makes it a little more intuitive for how to drive your gear up to "red line" level.
+
A similar colour coding for speed could be used ; blue for low speed, green for high speed.
+
This colour coding for the two parameters (reliability and speed) means that when new driver/setup options are available that provide a speed increase, (yet are unreliable or unknown reliability at the time), the user has a very easy visual prompt to help them make decisions, and adapt their trial and error path to optimisation.
+
Feature to save different hardware settings, with notes in the hardware specs, and share them. Upload to Lumiera web site, so that better first guesses for new users are available. And if an intelligent system is used for hardware detection in future, then the information for best choices will already be available.
-- link:Tree[] [[DateTime(2008-05-28T09:41:00NZ)]]
- Comment: The problem is that unlike games, in movie editors there isn't very much that can be done in the way of tweaking. With video editing, by and large there are no shortcuts. So the calculations that must take place to render a video on a Quad Core workstation are the same as the ones that need to happen on an EeePC. Lumiera needs to be intelligent about how much RAM it uses etc. but that sort of thing ought to be automatic. The only thing that this could apply to is reduced quality previews, which I've put in the blueprint list.
-- link:JoelHoldsworth[] [[DateTime(2008-07-24T16:34:20Z)]]
* Menu Bar disconnectable from track view +
The menu bar could be made disconnected from the track view. This would allow the track view to be covered by a window, but the menu still kept on top. The menu bar could by default start at the top left and run across the screen. It could remain on top view. It could include easy single click tabs to jump from one window view to another.
+
The menu items that are specific to track view could be separated out and left as dedicated menu attached to the top of the track view.
-- link:Tree[][[DateTime(2008-05-07T21:06:00NZ)]]
- Comment: Actually if you look at the state-of-ui you can see that the menu bar will be shown at the top of workspace. We might make it detachable, but actually it's not very useful to be able to attach the menu bar to the sides or bottoms of windows.
-- link:JoelHoldsworth[] [[DateTime(2008-07-24T16:47:08Z)]]

Some files were not shown because too many files have changed in this diff Show more