summaryrefslogtreecommitdiffstats
path: root/share/extensions/other
diff options
context:
space:
mode:
Diffstat (limited to 'share/extensions/other')
-rw-r--r--share/extensions/other/clipart/LICENSE.txt674
-rw-r--r--share/extensions/other/clipart/MANIFEST.in9
-rw-r--r--share/extensions/other/clipart/README.md12
-rw-r--r--share/extensions/other/clipart/import_sources.py272
-rw-r--r--share/extensions/other/clipart/import_web_image.inx12
-rwxr-xr-xshare/extensions/other/clipart/import_web_image.py395
-rw-r--r--share/extensions/other/clipart/import_web_image.svg239
-rw-r--r--share/extensions/other/clipart/import_web_image.ui934
-rwxr-xr-xshare/extensions/other/clipart/import_web_image_cli.py22
-rw-r--r--share/extensions/other/clipart/licenses/asl.svg343
-rw-r--r--share/extensions/other/clipart/licenses/bsd.svg343
-rw-r--r--share/extensions/other/clipart/licenses/cc-by-nc-sa.svg346
-rw-r--r--share/extensions/other/clipart/licenses/cc-by-nc.svg340
-rw-r--r--share/extensions/other/clipart/licenses/cc-by-nd.svg340
-rw-r--r--share/extensions/other/clipart/licenses/cc-by-sa.pngbin0 -> 2275 bytes
-rw-r--r--share/extensions/other/clipart/licenses/cc-by-sa.svg340
-rw-r--r--share/extensions/other/clipart/licenses/cc-by.svg334
-rw-r--r--share/extensions/other/clipart/licenses/cc0.svg334
-rw-r--r--share/extensions/other/clipart/licenses/gpl.svg347
-rw-r--r--share/extensions/other/clipart/licenses/mit.svg308
-rw-r--r--share/extensions/other/clipart/licenses/perm-by.svg93
-rw-r--r--share/extensions/other/clipart/licenses/perm-nc.svg100
-rw-r--r--share/extensions/other/clipart/licenses/perm-nd.svg92
-rw-r--r--share/extensions/other/clipart/licenses/perm-ne.svg90
-rw-r--r--share/extensions/other/clipart/licenses/perm-notice.svg82
-rw-r--r--share/extensions/other/clipart/licenses/perm-pd.svg87
-rw-r--r--share/extensions/other/clipart/licenses/perm-sa.svg84
-rw-r--r--share/extensions/other/clipart/licenses/unknown.svg340
-rw-r--r--share/extensions/other/clipart/pyproject.toml19
-rw-r--r--share/extensions/other/clipart/sources/bioicons.py97
-rw-r--r--share/extensions/other/clipart/sources/bioicons.svg145
-rw-r--r--share/extensions/other/clipart/sources/inkscape-web.py74
-rw-r--r--share/extensions/other/clipart/sources/inkscape-web.svg569
-rw-r--r--share/extensions/other/clipart/sources/ocal.py97
-rw-r--r--share/extensions/other/clipart/sources/ocal.svg132
-rw-r--r--share/extensions/other/clipart/sources/reactome.py64
-rw-r--r--share/extensions/other/clipart/sources/reactome.svg111
-rw-r--r--share/extensions/other/clipart/sources/wikimedia.py76
-rw-r--r--share/extensions/other/clipart/sources/wikimedia.svg92
-rw-r--r--share/extensions/other/gcodetools/.darglint3
-rw-r--r--share/extensions/other/gcodetools/.pylintrc374
-rw-r--r--share/extensions/other/gcodetools/LICENSE.txt340
-rw-r--r--share/extensions/other/gcodetools/MANIFEST.in2
-rw-r--r--share/extensions/other/gcodetools/README.md45
-rw-r--r--share/extensions/other/gcodetools/TESTING.md104
-rwxr-xr-xshare/extensions/other/gcodetools/gcodetools.py5930
-rw-r--r--share/extensions/other/gcodetools/gcodetools_about.inx52
-rw-r--r--share/extensions/other/gcodetools/gcodetools_area.inx133
-rw-r--r--share/extensions/other/gcodetools/gcodetools_dxf_points.inx79
-rw-r--r--share/extensions/other/gcodetools/gcodetools_engraving.inx91
-rw-r--r--share/extensions/other/gcodetools/gcodetools_graffiti.inx120
-rw-r--r--share/extensions/other/gcodetools/gcodetools_lathe.inx113
-rw-r--r--share/extensions/other/gcodetools/gcodetools_orientation_points.inx57
-rw-r--r--share/extensions/other/gcodetools/gcodetools_path_to_gcode.inx93
-rw-r--r--share/extensions/other/gcodetools/gcodetools_prepare_path_for_plasma.inx59
-rw-r--r--share/extensions/other/gcodetools/gcodetools_tools_library.inx62
-rwxr-xr-xshare/extensions/other/gcodetools/genpofiles.sh7
-rw-r--r--share/extensions/other/gcodetools/setup.cfg2
-rw-r--r--share/extensions/other/gcodetools/tests/data/refs/gcodetools__--active-tab__orientation__--Zsurface__0__00000000000001e-5__--Zdepth__-9__71445146547012e-17__--orientation-points-count__3.out41
-rw-r--r--share/extensions/other/gcodetools/tests/data/refs/gcodetools__06eec9617e749f35cb949d850415f68d.out30
-rw-r--r--share/extensions/other/gcodetools/tests/data/refs/gcodetools__2bf3b298fa730dafb8c6fd51921078f0.out40
-rw-r--r--share/extensions/other/gcodetools/tests/data/refs/gcodetools__4a9fb751baf0533eadd4d394957c966d.out0
-rw-r--r--share/extensions/other/gcodetools/tests/data/svg/default-inkscape-SVG.svg37
-rw-r--r--share/extensions/other/gcodetools/tests/data/svg/shapes.svg284
-rw-r--r--share/extensions/other/gcodetools/tests/dev_requirements.txt11
-rw-r--r--share/extensions/other/gcodetools/tests/test_gcodetools.py65
-rw-r--r--share/extensions/other/gcodetools/tests/test_inkex_inx.py114
-rw-r--r--share/extensions/other/gcodetools/tox.ini14
-rw-r--r--share/extensions/other/inkman/MANIFEST.in6
-rw-r--r--share/extensions/other/inkman/inkman/__init__.py5
-rw-r--r--share/extensions/other/inkman/inkman/archive.py120
-rw-r--r--share/extensions/other/inkman/inkman/backfoot.py84
-rw-r--r--share/extensions/other/inkman/inkman/data/__init__.py0
-rw-r--r--share/extensions/other/inkman/inkman/data/gui.ui736
-rw-r--r--share/extensions/other/inkman/inkman/data/info.ui338
-rw-r--r--share/extensions/other/inkman/inkman/data/package.json20
-rw-r--r--share/extensions/other/inkman/inkman/data/pixmaps/__init__.py0
-rw-r--r--share/extensions/other/inkman/inkman/data/pixmaps/core_icon.svg112
-rw-r--r--share/extensions/other/inkman/inkman/data/pixmaps/default.svg75
-rw-r--r--share/extensions/other/inkman/inkman/data/pixmaps/default_icon.svg71
-rw-r--r--share/extensions/other/inkman/inkman/data/pixmaps/docs.pngbin0 -> 54648 bytes
-rw-r--r--share/extensions/other/inkman/inkman/data/pixmaps/icon.svg79
-rw-r--r--share/extensions/other/inkman/inkman/data/pixmaps/module_icon.svg82
-rw-r--r--share/extensions/other/inkman/inkman/data/pixmaps/not-found.pngbin0 -> 42907 bytes
-rw-r--r--share/extensions/other/inkman/inkman/data/pixmaps/orphan_icon.svg88
-rw-r--r--share/extensions/other/inkman/inkman/data/pixmaps/star-lots.svg95
-rw-r--r--share/extensions/other/inkman/inkman/data/pixmaps/star-none.svg95
-rw-r--r--share/extensions/other/inkman/inkman/data/pixmaps/star-some.svg95
-rw-r--r--share/extensions/other/inkman/inkman/factory.py199
-rw-r--r--share/extensions/other/inkman/inkman/gui/__init__.py32
-rw-r--r--share/extensions/other/inkman/inkman/gui/info.py105
-rw-r--r--share/extensions/other/inkman/inkman/gui/main.py371
-rw-r--r--share/extensions/other/inkman/inkman/package.py330
-rw-r--r--share/extensions/other/inkman/inkman/remote.py153
-rw-r--r--share/extensions/other/inkman/inkman/target.py375
-rw-r--r--share/extensions/other/inkman/inkman/targets.py20
-rw-r--r--share/extensions/other/inkman/inkman/utils.py166
-rw-r--r--share/extensions/other/inkman/manage_extensions.inx12
-rwxr-xr-xshare/extensions/other/inkman/manage_extensions.py69
-rw-r--r--share/extensions/other/inkman/pyproject.toml19
100 files changed, 20642 insertions, 0 deletions
diff --git a/share/extensions/other/clipart/LICENSE.txt b/share/extensions/other/clipart/LICENSE.txt
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/share/extensions/other/clipart/LICENSE.txt
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. 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
+them 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 prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. 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.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey 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;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU 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 that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ 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.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+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.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ 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
+state 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) <year> <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 3 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, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program 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, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU 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 Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/share/extensions/other/clipart/MANIFEST.in b/share/extensions/other/clipart/MANIFEST.in
new file mode 100644
index 0000000..c1201be
--- /dev/null
+++ b/share/extensions/other/clipart/MANIFEST.in
@@ -0,0 +1,9 @@
+include import_web_image.ui
+include import_web_image.py
+include import_web_image.inx
+include import_web_image.svg
+include import_sources.py
+include README.md
+include LICENSE.txt
+include sources/*.py
+include sources/*.svg
diff --git a/share/extensions/other/clipart/README.md b/share/extensions/other/clipart/README.md
new file mode 100644
index 0000000..5443006
--- /dev/null
+++ b/share/extensions/other/clipart/README.md
@@ -0,0 +1,12 @@
+# Import Web Image (inkscape extension)
+
+This Inkscape extension allows inkscape users to import graphics into Inkscape from a selection of internet sources.
+
+It is a graphical user interface which allows the searching for, and selection of both svg and raster images and these are then inserted into the current document.
+
+# Sources
+
+New sources can be added at any time. They should include an icon, and a python file with the same name and should allow the user to search and download resources from the target website or platform.
+
+Please see existing python files for examples.
+
diff --git a/share/extensions/other/clipart/import_sources.py b/share/extensions/other/clipart/import_sources.py
new file mode 100644
index 0000000..d98aab3
--- /dev/null
+++ b/share/extensions/other/clipart/import_sources.py
@@ -0,0 +1,272 @@
+#
+# Copyright 2021 Martin Owens <doctormo@gmail.com>
+# Copyright 2022 Simon Duerr <dev@simonduerr.eu>
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>
+#
+"""
+Base module for all import web search source modules.
+"""
+
+import re
+import os
+import sys
+import logging
+import requests
+import importlib
+
+from cachecontrol import CacheControl, CacheControlAdapter
+from cachecontrol.caches.file_cache import FileCache
+from cachecontrol.heuristics import ExpiresAfter
+
+from inkex.command import CommandNotFound, ProgramRunError, call
+from collections import defaultdict
+
+LICENSE_ICONS = os.path.join(os.path.dirname(__file__), 'licenses')
+
+LICENSES = {
+ "cc-0": {
+ "name": "CC0",
+ "modules": ["nocopyright"],
+ "url": "https://creativecommons.org/publicdomain/zero/1.0/",
+ "overlay": "cc0.svg",
+ },
+ "cc-by-3.0": {
+ "name": "CC-BY 3.0 Unported",
+ "modules": ["by"],
+ "url": "https://creativecommons.org/licenses/by/3.0/",
+ "overlay": "cc-by.svg",
+ },
+ "cc-by-4.0": {
+ "name": "CC-BY 4.0 Unported",
+ "modules": ["by"],
+ "url": "https://creativecommons.org/licenses/by/4.0/",
+ "overlay": "cc-by.svg",
+ },
+ "cc-by-sa-4.0": {
+ "name": "CC-BY SA 4.0",
+ "modules": ["by", "sa"],
+ "url": "https://creativecommons.org/licenses/by-sa/4.0/",
+ "overlay": "cc-by-sa.svg",
+ },
+ "cc-by-sa-3.0": {
+ "name": "CC-BY SA 3.0",
+ "modules": ["by", "sa"],
+ "url": "https://creativecommons.org/licenses/by-sa/3.0/",
+ "overlay": "cc-by-sa.svg",
+ },
+ "cc-by-nc-sa-4.0": {
+ "name": "CC-BY NC SA 4.0",
+ "modules": ["by", "sa", "nc"],
+ "url": "https://creativecommons.org/licenses/by-nc-sa/4.0/",
+ "overlay": "cc-by-nc-sa.svg",
+ },
+ "cc-by-nc-sa-3.0": {
+ "name": "CC-BY NC SA 3.0",
+ "modules": ["by", "sa", "nc"],
+ "url": "https://creativecommons.org/licenses/by-nc-sa/3.0/",
+ "overlay": "cc-by-nc-sa.svg",
+ },
+ "cc-by-nc-3.0": {
+ "name": "CC-BY NC 3.0",
+ "modules": ["by", "nc"],
+ "url": "https://creativecommons.org/licenses/by-nc/3.0/",
+ "overlay": "cc-by-nc.svg",
+ },
+ "cc-by-nd-3.0": {
+ "name": "CC-BY ND 3.0",
+ "modules": ["by", "nd"],
+ "url": "https://creativecommons.org/licenses/by-nd/3.0/",
+ "overlay": "cc-by-nd.svg",
+ },
+ "gpl-2": {
+ "name": "GPLv2",
+ "modules": ["retaincopyrightnotice", "sa"],
+ "url": "https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt",
+ "overlay": "gpl.svg",
+ },
+ "gpl-3": {
+ "name": "GPLv3",
+ "modules": ["retaincopyrightnotice", "sa"],
+ "url": "https://www.gnu.org/licenses/gpl-3.0.txt",
+ "overlay": "gpl.svg",
+ },
+ "agpl-3": {
+ "name": "AGPLv3",
+ "modules": ["retaincopyrightnotice", "sa"],
+ "url": "https://www.gnu.org/licenses/agpl-3.0.txt",
+ "overlay": "gpl.svg",
+ },
+ "mit": {
+ "name": "MIT",
+ "modules": ["retaincopyrightnotice"],
+ "url": "https://mit-license.org/",
+ "overlay": "mit.svg",
+ },
+ "asl": {
+ "name": "Apache License",
+ "modules": ["retaincopyrightnotice"],
+ "url": "https://www.apache.org/licenses/LICENSE-2.0.txt",
+ "overlay": "asl.svg",
+ },
+ "bsd": {
+ "name": "BSD",
+ "modules": ["retaincopyrightnotice", "noendorsement"],
+ "url": "https://opensource.org/licenses/BSD-3-Clause",
+ "overlay": "bsd.svg",
+ },
+}
+
+
+class RemotePage:
+ """Lazy access to paging systems"""
+
+ icon = "sources/next_page.svg"
+ string = property(lambda self: "Next Page")
+
+ def __init__(self, remote, func):
+ self.func = func
+ self.remote = remote
+
+ def get_next_page(self):
+ for info in self.func():
+ yield self.remote.result_to_cls(info)
+
+
+class RemoteFile:
+ """Lazy access to remote files"""
+
+ icon = property(lambda self: self.remote.to_local_file(self.info["thumbnail"]))
+ get_file = lambda self: self.remote.to_local_file(self.info["file"])
+
+ def __init__(self, remote, info):
+ for field in ("name", "thumbnail", "license", "file"):
+ if field not in info:
+ raise ValueError(f"Field {field} not provided in RemoteFile package")
+ self.info = info
+ self.remote = remote
+
+ @property
+ def string(self):
+ return self.info["name"]
+
+ @property
+ def license(self):
+ return self.info["license"]
+
+ def get_overlay(self):
+ return self.license_info["overlay"]
+
+ @property
+ def license_info(self):
+ return LICENSES.get(self.license, {
+ "name": "Unknown",
+ "url": self.info.get("descriptionurl", ""),
+ "modules": [],
+ "overlay": "unknown.svg",
+ })
+
+ @property
+ def author(self):
+ return self.info["author"]
+
+
+class RemoteSource:
+ """A remote source of svg images which can be searched and downloaded"""
+
+ # These are the properties that should be overridden in your class
+ name = None
+ icon = None
+ file_cls = RemoteFile
+ page_cls = RemotePage
+ is_default = False
+ is_enabled = True
+
+ @classmethod
+ def load(cls, name):
+ """Load the file or directory of remote sources"""
+ if os.path.isfile(name):
+ sys.path, sys_path = [os.path.dirname(name)] + sys.path, sys.path
+ try:
+ importlib.import_module(os.path.basename(name).rsplit(".", 1)[0])
+ except ImportError:
+ logging.error(f"Failed to load module: {name}")
+ sys.path = sys_path
+ elif os.path.isdir(name):
+ for child in os.listdir(name):
+ if not child.startswith("_") and child.endswith(".py"):
+ cls.load(os.path.join(name, child))
+
+ def search(self, query, tags=[]):
+ """
+ Search for the given query and yield basic informational blocks t hand to file_cls.
+
+ Required fields per yielded object are: name, license, thumbnail and file.
+ Optional fields are: id, summary, author, created, popularity
+ """
+ raise NotImplementedError(
+ "You must implement a search function for this remote source!"
+ )
+
+ sources = {}
+
+ def __init_subclass__(cls):
+ if cls != RemoteSource:
+ cls.sources[cls.__name__] = cls
+
+ def __init__(self, cache_dir):
+ self.session = requests.session()
+ self.cache_dir = cache_dir
+ self.session.mount(
+ "https://",
+ CacheControlAdapter(
+ cache=FileCache(cache_dir),
+ heuristic=ExpiresAfter(days=5),
+ ),
+ )
+
+ def __del__(self):
+ self.session.close()
+
+ def file_search(self, query):
+ """Search for extension packages"""
+ for info in self.search(query):
+ yield self.result_to_cls(info)
+
+ def result_to_cls(self, info):
+ if callable(info):
+ return self.page_cls(self, info)
+ return self.file_cls(self, info)
+
+ def to_local_file(self, url):
+ """Get a remote url and turn it into a local file"""
+ filepath = os.path.join(self.cache_dir, url.split("/")[-1])
+ headers = {"User-Agent": "Inkscape"}
+ try:
+ remote = self.session.get(
+ url, headers=headers
+ ) # needs UserAgent otherwise many 403 or 429 for wiki commons
+ except requests.exceptions.RequestException as err:
+ return None
+ except ConnectionError as err:
+ return None
+ except requests.exceptions.RequestsWarning:
+ pass
+
+ if remote and remote.status_code == 200:
+ with open(filepath, "wb") as fhl:
+ # If we don't have data, return None (instead of empty file)
+ if fhl.write(remote.content):
+ return filepath
+ return None
diff --git a/share/extensions/other/clipart/import_web_image.inx b/share/extensions/other/clipart/import_web_image.inx
new file mode 100644
index 0000000..53bea25
--- /dev/null
+++ b/share/extensions/other/clipart/import_web_image.inx
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
+ <name>Import Web Image...</name>
+ <id>org.inkscape.import_web_image</id>
+ <effect implements-custom-gui="true">
+ <object-type>all</object-type>
+ <effects-menu hidden="true"/>
+ </effect>
+ <script>
+ <command location="inx" interpreter="python">import_web_image.py</command>
+ </script>
+</inkscape-extension>
diff --git a/share/extensions/other/clipart/import_web_image.py b/share/extensions/other/clipart/import_web_image.py
new file mode 100755
index 0000000..5c8c8d8
--- /dev/null
+++ b/share/extensions/other/clipart/import_web_image.py
@@ -0,0 +1,395 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright 2021 Martin Owens <doctormo@gmail.com>
+# Copyright 2022 Simon Duerr <dev@simonduerr.eu>
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>
+#
+"""
+Import images from the internet, inkscape extension (GUI)
+"""
+
+__version__ = '1.0'
+__pkgname__ = 'inkscape-import-web-image'
+
+import os
+import sys
+import logging
+import warnings
+warnings.filterwarnings("ignore")
+
+from collections import defaultdict
+from base64 import encodebytes
+from appdirs import user_cache_dir
+
+import inkex
+from inkex import Style
+from inkex.gui import GtkApp, Window, IconView, asyncme
+from inkex.gui.pixmap import PixmapManager, SizeFilter, PadFilter, OverlayFilter
+from inkex.elements import (
+ load_svg, Image, Defs, NamedView, Metadata,
+ SvgDocumentElement, StyleElement
+)
+from gi.repository import Gtk
+
+from import_sources import RemoteSource, RemoteFile, RemotePage
+
+SOURCES = os.path.join(os.path.dirname(__file__), 'sources')
+LICENSES = os.path.join(os.path.dirname(__file__), 'licenses')
+CACHE_DIR = user_cache_dir('inkscape-import-web-image', 'Inkscape')
+
+class LicenseOverlay(OverlayFilter):
+ pixmaps = PixmapManager(LICENSES)
+
+ def get_overlay(self, item=None, manager=None):
+ if item is None: # Default image
+ return None
+ return self.pixmaps.get(item.get_overlay())
+
+
+class ResultsIconView(IconView):
+ """The search results shown as icons"""
+ def get_markup(self, item):
+ return item.string
+
+ def get_icon(self, item):
+ return item.icon
+
+ def setup(self):
+ self._list.set_markup_column(1)
+ self._list.set_pixbuf_column(2)
+ crt, crp = self._list.get_cells()
+ self.crt_notify = crt.connect('notify', self.keep_size)
+ super().setup()
+
+ def keep_size(self, crt, *args):
+ """Hack Gtk to keep cells smaller"""
+ crt.handler_block(self.crt_notify)
+ crt.set_property('width', 150)
+ crt.handler_unblock(self.crt_notify)
+
+
+class ImporterWindow(Window):
+ """The window that is in the glade file"""
+ name = 'import_web_image'
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ self.widget('dl-searching').hide()
+
+ # Add each of the source services from their plug-in modules
+ self.source = self.widget('service_list')
+ self.source_model = self.source.get_model()
+ self.source_model.clear()
+
+ RemoteSource.load(SOURCES)
+ pix = PixmapManager(SOURCES, size=150)
+ for x, (key, source) in enumerate(RemoteSource.sources.items()):
+ if not source.is_enabled:
+ continue
+ # We add them in GdkPixbuf, string, string format (see glade file)
+ self.source_model.append([pix.get(source.icon), source.name, key])
+ if source.is_default:
+ self.source.set_active(x)
+
+ pixmaps = PixmapManager(CACHE_DIR, filters=[
+ SizeFilter(size=150),
+ PadFilter(size=(0, 150)),
+ LicenseOverlay(position=(0.5, 1))
+ ])
+ self.select_func = self.gapp.kwargs['select']
+ self.results = ResultsIconView(self.widget('results'), pixmaps)
+ self.pool = ResultsIconView(self.widget('pool'), pixmaps)
+ self.multiple = False
+
+ self.widget("perm-nocopyright").set_message_type(Gtk.MessageType.WARNING)
+
+ def select_image(self, widget):
+ """Callback when clicking on an image in the result list"""
+ for item_path in self.widget("results").get_selected_items():
+ item_iter = self.results._model.get_iter(item_path)
+ item = self.results._model[item_iter][0]
+ self.show_license(item)
+ self.update_btn_import()
+
+ def show_license(self, item):
+ """Display the current item's license information"""
+ self.widget("perms").foreach(lambda w: w.hide())
+ info = item.license_info
+ for mod in info['modules']:
+ self.widget("perm-" + mod).show()
+
+ def get_selected_source(self):
+ """Return the selected source class"""
+ _iter = self.source.get_active_iter()
+ key = self.source_model[_iter][2]
+ return RemoteSource.sources[key](CACHE_DIR)
+
+ def img_multiple(self, widget):
+ """Enable multi-selection"""
+ widget.hide()
+ self.widget('btn-single').show()
+ self.widget('multiple-box').show()
+ self.widget('multiple-buttons').show()
+ self.multiple = True
+ self.update_btn_import()
+
+ def img_single(self, widget):
+ """Enable single-selection"""
+ widget.hide()
+ self.widget('btn-multiple').show()
+ self.widget('multiple-box').hide()
+ self.widget('multiple-buttons').hide()
+ is_selected = bool(list(self.results.get_selected_items()))
+ self.pool.clear()
+ self.multiple = False
+ self.update_btn_import()
+
+ def img_add(self, widget=None):
+ """Add an item from the search to the multi-pool"""
+ self.pool.add(self.results.get_selected_items())
+ self.update_btn_import()
+
+ def img_remove(self, widget=None):
+ """Remove any selected items from the multi-pool"""
+ for item in self.pool.get_selected_items():
+ self.pool.remove_item(item)
+ self.update_btn_import()
+
+ def update_btn_import(self):
+ """Set the import button to enabled or disabled"""
+ enabled = False
+ if self.multiple:
+ enabled = bool(list(self.pool))
+ else:
+ enabled = bool(list(self.results.get_selected_items()))
+ self.widget('btn-import').set_sensitive(enabled)
+
+ def result_activate(self, widget=None):
+ """Search results double click"""
+ if self.multiple:
+ self.img_add()
+ else:
+ self.img_import()
+
+ def img_import(self, widget=None):
+ """Apply the selected image and quit"""
+ items = []
+ if not self.multiple:
+ items.extend(self.results.get_selected_items())
+ else:
+ items.extend([item for item,*_ in self.pool])
+
+ to_exit = True
+ for item in items:
+ self.select_func(item.get_file())
+ # XXX This pagination control is not good. Replace it with normal controls.
+ #elif isinstance(item, RemotePage):
+ if to_exit:
+ self.exit()
+
+ def search(self, widget):
+ """Remote search activation"""
+ query = widget.get_text()
+ if len(query) > 2:
+ self.search_clear()
+ self.search_started()
+ self.async_search(query)
+
+ @asyncme.run_or_none
+ def async_search(self, query):
+ """Asyncronous searching in PyPI"""
+ for resource in self.get_selected_source().file_search(query):
+ self.add_search_result(resource)
+ self.search_finished()
+
+ @asyncme.mainloop_only
+ def add_search_result(self, resource):
+ """Adding things to Gtk must be done in mainloop"""
+ if isinstance(resource, RemotePage):
+ return self.set_next_page(resource)
+
+ self.results.add_item(resource)
+
+ def search_clear(self, widget=None):
+ """Remove previous search"""
+ self.results.clear()
+ self.update_btn_import()
+ self.next_page_item = None
+ self.widget('btn-next-page').hide()
+
+ def search_started(self):
+ """Set widgets to stun"""
+ self.widget('dl-search').set_sensitive(False)
+ self.widget('dl-searching').start()
+ self.widget('dl-searching').show()
+
+ @asyncme.mainloop_only
+ def search_finished(self):
+ """After everything, finish the search"""
+ self.widget('dl-search').set_sensitive(True)
+ self.widget('dl-searching').hide()
+ self.widget('dl-searching').stop()
+
+ def set_next_page(self, item):
+ self.next_page_item = item
+ self.widget('btn-next-page').show()
+
+ def show_next_page(self, widget=None):
+ item = self.next_page_item
+ if item:
+ self.search_clear()
+ self.search_started()
+ self.async_next_page(item)
+
+ @asyncme.run_or_none
+ def async_next_page(self, item):
+ for resource in item.get_next_page():
+ self.add_search_result(resource)
+ self.search_finished()
+
+
+class App(GtkApp):
+ """Load the inkscape extensions glade file and attach to window"""
+ glade_dir = os.path.join(os.path.dirname(__file__))
+ app_name = 'inkscape-import-web-image'
+ windows = [ImporterWindow]
+
+class ImportWebImage(inkex.EffectExtension):
+ """Import an svg from the internet"""
+ selected_filename = None
+
+ def merge_defs(self, defs):
+ """Add all the items in defs to the self.svg.defs"""
+ target = self.svg.defs
+ for child in defs:
+ if isinstance(child, StyleElement):
+ continue # Already appled in merge_stylesheets()
+ target.append(child)
+
+ def merge_stylesheets(self, svg):
+ """Because we don't want conflicting style-sheets (classes, ids, etc) we scrub them"""
+ elems = defaultdict(list)
+ # 1. Find all styles, and all elements that apply to them
+ for sheet in svg.getroot().stylesheets:
+ for style in sheet:
+ xpath = style.to_xpath()
+ for elem in svg.xpath(xpath):
+ elems[elem].append(style)
+ # 1b. Clear possibly conflicting attributes
+ if '@id' in xpath:
+ elem.set_random_id()
+ if '@class' in xpath:
+ elem.set('class', None)
+ # 2. Apply each style cascade sequentially
+ for elem, styles in elems.items():
+ output = Style()
+ for style in styles:
+ output += style
+ elem.style = output + elem.style
+
+ def import_svg(self, new_svg):
+ """Import an svg file into the current document"""
+ self.merge_stylesheets(new_svg)
+ for child in new_svg.getroot():
+ if isinstance(child, SvgDocumentElement):
+ yield from self.import_svg(child)
+ elif isinstance(child, StyleElement):
+ continue # Already applied in merge_stylesheets()
+ elif isinstance(child, Defs):
+ self.merge_defs(child)
+ elif isinstance(child, (NamedView, Metadata)):
+ pass
+ else:
+ yield child
+
+ def import_from_file(self, filename):
+ if not filename or not os.path.isfile(filename):
+ return
+ with open(filename, 'rb') as fhl:
+ head = fhl.read(100)
+ if b'<?xml' in head or b'<svg' in head:
+ new_svg = load_svg(head + fhl.read())
+ # Add each object to the container
+ objs = list(self.import_svg(new_svg))
+
+ if len(objs) == 1 and isinstance(objs[0], inkex.Group):
+ # Prevent too many groups, if item aready has one.
+ container = objs[0]
+ else:
+ # Make a new group to contain everything
+ container = inkex.Group()
+ for child in objs:
+ container.append(child)
+
+ # Retain the original filename as a group label
+ container.label = os.path.basename(filename)
+ # Apply unit transformation to keep things the same sizes.
+ container.transform.add_scale(self.svg.unittouu(1.0) \
+ / new_svg.getroot().unittouu(1.0))
+
+
+ else:
+ container = self.import_raster(filename, fhl)
+
+ self.svg.get_current_layer().append(container)
+
+ # Make sure that none of the new content is a layer.
+ for child in container.descendants():
+ if isinstance(child, inkex.Group):
+ child.set("inkscape:groupmode", None)
+
+ def effect(self):
+ def select_func(filename):
+ self.import_from_file(filename)
+
+ App(start_loop=True, select=select_func)
+
+ def import_raster(self, filename, handle):
+ """Import a raster image"""
+ # Don't read the whole file to check the header
+ handle.seek(0)
+ file_type = self.get_type(filename, handle.read(10))
+ handle.seek(0)
+
+ if file_type:
+ # Future: Change encodestring to encodebytes when python3 only
+ node = Image()
+ node.label = os.path.basename(filename)
+ node.set('xlink:href', 'data:{};base64,{}'.format(
+ file_type, encodebytes(handle.read()).decode('ascii')))
+ return node
+
+ @staticmethod
+ def get_type(path, header):
+ """Basic magic header checker, returns mime type"""
+ # Taken from embedimage.py
+ for head, mime in (
+ (b'\x89PNG', 'image/png'),
+ (b'\xff\xd8', 'image/jpeg'),
+ (b'BM', 'image/bmp'),
+ (b'GIF87a', 'image/gif'),
+ (b'GIF89a', 'image/gif'),
+ (b'MM\x00\x2a', 'image/tiff'),
+ (b'II\x2a\x00', 'image/tiff'),
+ ):
+ if header.startswith(head):
+ return mime
+ return None
+
+
+if __name__ == '__main__':
+ ImportWebImage().run()
diff --git a/share/extensions/other/clipart/import_web_image.svg b/share/extensions/other/clipart/import_web_image.svg
new file mode 100644
index 0000000..c51b5ca
--- /dev/null
+++ b/share/extensions/other/clipart/import_web_image.svg
@@ -0,0 +1,239 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ width="128"
+ height="128"
+ viewBox="0 0 33.866666 33.866668"
+ version="1.1"
+ id="svg67608"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ 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="title1089">Import Web Image Icon</title>
+ <defs
+ id="defs67602">
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath2926">
+ <path
+ id="path2928"
+ d="m 2689.2051,1552.7812 c -1.2424,0.019 -2.4636,0.2473 -3.1465,0.6797 -1.8497,1.1712 -22.9148,23.028 -23.6426,24.5313 -1.7963,3.7106 -0.6201,4.6924 8.3516,6.9726 2.8028,0.7123 3.5695,1.2178 2.9609,1.9512 -2.0682,1.5183 -4.1017,1.4916 -5.3457,3.6836 -0.3034,0.5345 2.1692,1.6328 6.7676,3.1797 4.4912,1.5108 6.2597,2.4432 6.4434,3.3965 0.061,0.3149 -0.4986,1.2646 -1.2422,2.1094 -0.7437,0.8448 -1.3516,1.7158 -1.3516,1.9355 0,0.761 1.1951,1.4749 3.2871,1.9629 2.3269,0.5429 3.5368,1.4508 3.8535,2.8926 0.1151,0.5242 0.5336,1.1896 0.9297,1.4785 1.2444,0.9075 4.7254,0.4213 7.7715,-1.0859 1.4032,-0.6945 2.961,-1.0989 2.6699,-1.6739 -0.2913,-0.5751 -1.6876,-1.3472 -2.2558,-2.3711 0,-0.9287 2.6477,-2.6734 5.1386,-3.3867 3.1633,-0.9057 4.2601,-1.4932 4.9414,-2.6465 1.2056,-2.1269 -2.8024,-3.8295 -4.6425,-5.3437 -0.4263,-0.6898 1.0762,-1.4723 6.2285,-3.2442 6.1741,-2.1232 8.4648,-3.2421 9.8437,-4.8125 1.2722,-1.449 1.3617,-2.811 0.3008,-4.5527 -1.0094,-1.6572 -23.2889,-24.3719 -24.5898,-25.0703 -0.7656,-0.411 -2.0292,-0.6043 -3.2715,-0.586 z m -9.5781,34.375 c 0.1008,0.01 0.2318,0.032 0.3984,0.076 4.0066,0.9222 7.1355,1.4726 10.8808,2.4141 -1.2692,2.7302 -7.2117,-0.556 -9.6308,-1.1231 -1.5124,-0.6676 -2.3541,-1.4254 -1.6484,-1.3672 z m 32.664,5.9415 c -1.5858,0 -1.9559,0.1298 -2.8222,0.9961 -2.5197,2.5738 3.7953,2.3544 5.8359,1.996 1.1266,-0.4283 1.074,-1.0881 -0.1699,-2.1347 -0.8274,-0.6962 -1.3648,-0.8574 -2.8438,-0.8574 z m -35.6582,4.4824 c -1.4412,0.018 -3.1329,0.6061 -3.6269,1.5293 -0.018,1.0319 0.4404,2.3802 1.9472,2.6035 1.4798,0.035 4.3592,-2.6972 3.6914,-3.502 -0.3714,-0.4475 -1.147,-0.6418 -2.0117,-0.6308 z m 30.9317,0.1777 c -0.2139,0.013 -0.3469,0.1726 -0.5762,0.4863 -1.0404,1.5023 1.0131,3.4841 2.6758,2.375 0.8704,-0.6365 0.3866,-1.7985 -1.0313,-2.4746 -0.558,-0.2663 -0.8545,-0.3996 -1.0683,-0.3867 z"
+ style="display:inline;fill:#12283a;fill-opacity:1;stroke-width:1"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2934"
+ id="linearGradient67521"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0387194,0,0,1.0387194,-2653.2878,-1650.9321)"
+ x1="2661.7014"
+ y1="1705.3958"
+ x2="2717.7971"
+ y2="1705.3958" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient2934">
+ <stop
+ style="stop-color:#dae1e7;stop-opacity:1"
+ offset="0"
+ id="stop2930" />
+ <stop
+ style="stop-color:#dae1e7;stop-opacity:0"
+ offset="1"
+ id="stop2932" />
+ </linearGradient>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.6211757"
+ inkscape:cx="-40.821376"
+ inkscape:cy="66.573179"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ units="px"
+ inkscape:window-width="1534"
+ inkscape:window-height="843"
+ inkscape:window-x="66"
+ inkscape:window-y="20"
+ inkscape:window-maximized="1"
+ objecttolerance="10.0"
+ gridtolerance="10.0"
+ guidetolerance="10.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:snap-global="false"
+ inkscape:deskcolor="#d1d1d1" />
+ <metadata
+ id="metadata67605">
+ <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/4.0/" />
+ <dc:title>Import Web Image Icon</dc:title>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Olibia Tsati</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:source>https://inkscape.org/~olibia/%E2%98%85inkscape-about-screen+6</dc:source>
+ <dc:date>2019-10-25</dc:date>
+ <dc:publisher>
+ <cc:Agent>
+ <dc:title>Inkscape</dc:title>
+ </cc:Agent>
+ </dc:publisher>
+ </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:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-111.47325,-97.102188)">
+ <g
+ id="g88390"
+ transform="matrix(0.58122678,0,0,0.58122678,46.682019,43.739455)">
+ <g
+ style="stroke-width:0.254721"
+ transform="matrix(1.0387194,0,0,1.0387194,-2653.2877,-1521.0922)"
+ clip-path="url(#clipPath2926)"
+ id="g52147">
+ <circle
+ style="fill:#f6998b;stroke-linecap:round;stroke-linejoin:round"
+ id="circle52137"
+ cx="2690.9072"
+ cy="1587.1523"
+ r="36.816235" />
+ <circle
+ r="36.816235"
+ cy="1602.707"
+ cx="2683.9019"
+ id="circle52139"
+ style="fill:#de751f;stroke-linecap:round;stroke-linejoin:round" />
+ <circle
+ style="fill:#613b1f;stroke-linecap:round;stroke-linejoin:round"
+ id="circle52141"
+ cx="2701.6948"
+ cy="1607.007"
+ r="36.816235" />
+ <circle
+ r="36.816235"
+ cy="1618.1439"
+ cx="2683.9019"
+ id="circle52143"
+ style="fill:#1c3d5a;stroke-linecap:round;stroke-linejoin:round" />
+ <circle
+ style="fill:#1f9d55;stroke-linecap:round;stroke-linejoin:round"
+ id="circle52145"
+ cx="2698.5181"
+ cy="1628.2202"
+ r="36.816235" />
+ </g>
+ <path
+ id="path52151"
+ d="m 141.48293,108.20013 2.56511,-1.67907 1.69053,0.85654 c 0.92974,0.47114 1.76061,0.7865 1.84631,0.7008 0.0852,-0.0852 0.32512,-1.17726 0.53205,-2.42581 l 0.37611,-2.26991 2.15088,1.71148 c 1.85774,1.47842 2.17352,1.62457 2.3178,1.0731 0.32501,-1.24272 -0.75174,-2.68404 -5.47571,-7.330016 -5.07487,-4.990862 -5.80769,-5.426181 -8.33541,-4.951994 -1.00092,0.187801 -2.08026,1.037669 -5.18406,4.082362 -4.89122,4.797958 -6.59294,6.892418 -6.59294,8.114688 0,1.47061 0.57544,1.76104 3.48967,1.76104 h 2.66255 l 1.11776,-1.98146 c 1.99663,-3.53944 1.87376,-3.49684 2.52389,-0.87387 1.06095,4.28014 1.25809,4.923 1.50521,4.90712 0.13473,-0.0103 1.39946,-0.77147 2.81025,-1.695 z"
+ style="fill:#ffffff;stroke-width:0.264583"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path56425"
+ d="m 140.0418,91.811755 c -1.29051,0.01984 -2.559,0.25688 -3.26832,0.70601 -1.92132,1.21656 -23.80205,23.919635 -24.55804,25.481155 -1.86584,3.85427 -0.6441,4.87408 8.67497,7.24257 2.91132,0.73988 3.70769,1.26495 3.07554,2.02674 -2.14825,1.5771 -4.26053,1.54935 -5.55267,3.82624 -0.31518,0.55521 2.25319,1.69604 7.02963,3.30282 4.66508,1.56927 6.50206,2.53778 6.69288,3.52798 0.0634,0.32711 -0.5179,1.31358 -1.2903,2.1911 -0.77248,0.87752 -1.40393,1.78223 -1.40393,2.01044 0,0.79046 1.24137,1.53199 3.41439,2.0389 2.41697,0.56391 3.67374,1.50696 4.0027,3.00458 0.11957,0.54452 0.55425,1.23569 0.96568,1.53578 1.29259,0.94263 4.90836,0.43759 8.07243,-1.12795 1.45751,-0.72141 3.07565,-1.14144 2.77326,-1.73873 -0.30258,-0.59735 -1.75294,-1.39936 -2.34312,-2.4629 0,-0.96465 2.75021,-2.77691 5.33754,-3.51783 3.28578,-0.94075 4.42505,-1.55101 5.13273,-2.74899 1.25228,-2.20924 -2.91092,-3.97777 -4.82227,-5.55059 -0.44278,-0.71649 1.1179,-1.52929 6.46968,-3.36981 6.41315,-2.20541 8.79255,-3.36764 10.22484,-4.99883 1.32147,-1.5051 1.41444,-2.91986 0.31245,-4.729 -1.04849,-1.72135 -24.19064,-25.315545 -25.54189,-26.040985 -0.79526,-0.42693 -2.10778,-0.627724 -3.39818,-0.6087 z m -9.94897,35.705975 c 0.10472,0.0103 0.24077,0.0333 0.41384,0.0789 4.16173,0.95793 7.41177,1.52961 11.3021,2.50756 -1.31834,2.83594 -7.49094,-0.5775 -10.00369,-1.16657 -1.57099,-0.69345 -2.44528,-1.48061 -1.71225,-1.42012 z m 33.92874,6.17157 c -1.64719,0 -2.03163,0.1348 -2.93148,1.03468 -2.61726,2.67342 3.94227,2.44554 6.06187,2.07327 1.17023,-0.4449 1.11559,-1.13025 -0.17648,-2.21737 -0.85944,-0.72316 -1.41766,-0.89058 -2.95391,-0.89058 z m -37.03886,4.65595 c -1.49699,0.0185 -3.25419,0.62957 -3.76735,1.5885 -0.0188,1.07186 0.45749,2.47238 2.02261,2.70434 1.53712,0.0363 4.528,-2.80165 3.83434,-3.6376 -0.38579,-0.46485 -1.19142,-0.66667 -2.0896,-0.65524 z m 32.12936,0.18457 c -0.22217,0.0135 -0.36034,0.17928 -0.59852,0.50514 -1.08066,1.56046 1.05233,3.619 2.7794,2.46695 0.90411,-0.66114 0.40158,-1.86814 -1.07122,-2.57042 -0.5796,-0.2766 -0.8876,-0.41506 -1.10966,-0.40167 z"
+ style="opacity:0.4;fill:url(#linearGradient67521);stroke-width:0.264583" />
+ </g>
+ <g
+ aria-label="Olibia Tsati"
+ style="font-weight:300;font-size:3.52778px;line-height:1.25;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Light';letter-spacing:0px;word-spacing:-1.32292px;fill:#bec8d0;stroke-width:0.264583"
+ id="text67600"
+ transform="matrix(0.58122678,0,0,0.58122678,57.511426,2.5161417)">
+ <path
+ d="m 133.14589,214.21099 q 0.29633,0 0.51858,0.14464 0.22225,0.14111 0.34572,0.42333 0.12347,0.28222 0.12347,0.68086 0,0.39158 -0.12347,0.67381 -0.11994,0.27869 -0.34219,0.42686 -0.22225,0.14464 -0.52211,0.14464 -0.29281,0 -0.51506,-0.14464 -0.22225,-0.14464 -0.34572,-0.42334 -0.12347,-0.27869 -0.12347,-0.6738 0,-0.39158 0.12347,-0.67381 0.12347,-0.28222 0.34572,-0.43039 0.22578,-0.14816 0.51506,-0.14816 z m 0,0.17991 q -0.35278,0 -0.55739,0.27164 -0.20461,0.26811 -0.20461,0.80081 0,0.52564 0.20461,0.79375 0.20814,0.26811 0.55739,0.26811 0.36336,0 0.56444,-0.26458 0.20108,-0.26811 0.20108,-0.80081 0,-0.53622 -0.20461,-0.8008 -0.20108,-0.26812 -0.56091,-0.26812 z"
+ style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.52778px;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Light';word-spacing:0px"
+ id="path85387"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 135.04383,216.70513 q -0.15169,0 -0.23989,-0.0882 -0.0882,-0.0882 -0.0882,-0.26105 v -2.286 l 0.20461,-0.0247 v 2.30364 q 0,0.17992 0.14816,0.17992 0.0776,0 0.13053,-0.0247 l 0.0529,0.1517 q -0.0988,0.0494 -0.20814,0.0494 z"
+ style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.52778px;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Light';word-spacing:0px"
+ id="path85389"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 135.85874,214.0099 q 0.0706,0 0.11289,0.0423 0.0423,0.0423 0.0423,0.10583 0,0.0635 -0.0423,0.10583 -0.0423,0.0423 -0.11289,0.0423 -0.067,0 -0.10936,-0.0423 -0.0423,-0.0423 -0.0423,-0.10583 0,-0.0635 0.0423,-0.10583 0.0423,-0.0423 0.10936,-0.0423 z m 0.10584,2.65642 h -0.20461 v -1.84503 h 0.20461 z"
+ style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.52778px;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Light';word-spacing:0px"
+ id="path85391"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 137.46035,214.78249 q 0.3175,0 0.49389,0.24694 0.17639,0.24695 0.17639,0.70556 0,0.44803 -0.18345,0.70908 -0.18344,0.26106 -0.51505,0.26106 -0.16581,0 -0.30339,-0.0741 -0.13406,-0.0741 -0.22931,-0.19755 l -0.0212,0.23283 h -0.17639 v -2.59644 l 0.20461,-0.0247 v 1.03011 q 0.21519,-0.2928 0.55386,-0.2928 z m -0.067,1.7533 q 0.24695,0 0.38453,-0.20108 0.13758,-0.20461 0.13758,-0.59972 0,-0.78317 -0.49741,-0.78317 -0.16581,0 -0.28575,0.0847 -0.11995,0.0811 -0.22578,0.23283 v 0.9772 q 0.19755,0.28927 0.48683,0.28927 z"
+ style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.52778px;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Light';word-spacing:0px"
+ id="path85393"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 138.8256,214.0099 q 0.0705,0 0.11289,0.0423 0.0423,0.0423 0.0423,0.10583 0,0.0635 -0.0423,0.10583 -0.0423,0.0423 -0.11289,0.0423 -0.067,0 -0.10936,-0.0423 -0.0423,-0.0423 -0.0423,-0.10583 0,-0.0635 0.0423,-0.10583 0.0423,-0.0423 0.10936,-0.0423 z m 0.10583,2.65642 h -0.20461 v -1.84503 h 0.20461 z"
+ style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.52778px;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Light';word-spacing:0px"
+ id="path85395"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 140.80115,216.2571 q 0,0.14464 0.0353,0.20814 0.0388,0.0635 0.11995,0.0952 l -0.0459,0.14464 q -0.127,-0.0247 -0.19756,-0.0952 -0.067,-0.0706 -0.0882,-0.2152 -0.1905,0.31045 -0.57503,0.31045 -0.26458,0 -0.41981,-0.14817 -0.15169,-0.15169 -0.15169,-0.40217 0,-0.28575 0.20108,-0.44097 0.20461,-0.15522 0.56445,-0.15522 h 0.35277 v -0.17992 q 0,-0.22225 -0.0988,-0.32103 -0.0988,-0.1023 -0.32809,-0.1023 -0.21166,0 -0.50094,0.10583 l -0.0529,-0.15522 q 0.31045,-0.12347 0.58209,-0.12347 0.60325,0 0.60325,0.58561 z m -0.71614,0.28222 q 0.33161,0 0.51152,-0.32455 v -0.508 h -0.32102 q -0.28223,0 -0.43039,0.10936 -0.14817,0.10936 -0.14817,0.32808 0,0.1905 0.10231,0.29281 0.1023,0.1023 0.28575,0.1023 z"
+ style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.52778px;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Light';word-spacing:0px"
+ id="path85397"
+ inkscape:connector-curvature="0" />
+ <path
+ d="M 143.84208,214.43677 H 143.133 v 2.22955 h -0.20814 v -2.22955 h -0.71614 v -0.18698 h 1.65806 z"
+ style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.52778px;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Light';word-spacing:0px"
+ id="path85399"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 144.54057,214.78249 q 0.17287,0 0.31398,0.0529 0.14111,0.0494 0.27516,0.1517 l -0.0952,0.13405 q -0.127,-0.0882 -0.23989,-0.127 -0.11288,-0.0423 -0.24694,-0.0423 -0.18344,0 -0.29633,0.0847 -0.11289,0.0847 -0.11289,0.22578 0,0.13405 0.0952,0.20813 0.0988,0.0741 0.35278,0.14112 0.3175,0.0811 0.45508,0.20461 0.13758,0.12347 0.13758,0.35277 0,0.25048 -0.1905,0.39512 -0.18697,0.14111 -0.47625,0.14111 -0.21166,0 -0.37041,-0.06 -0.15875,-0.0635 -0.28928,-0.17638 l 0.11289,-0.13053 q 0.127,0.0988 0.254,0.14816 0.127,0.0459 0.2928,0.0459 0.20461,0 0.32809,-0.0917 0.12347,-0.0952 0.12347,-0.26105 0,-0.11289 -0.0423,-0.18345 -0.0423,-0.0705 -0.14463,-0.11994 -0.0988,-0.0494 -0.29634,-0.10583 -0.29633,-0.0776 -0.42686,-0.19403 -0.127,-0.11642 -0.127,-0.31045 0,-0.13758 0.0811,-0.24694 0.0811,-0.11289 0.21872,-0.17286 0.14111,-0.0635 0.31397,-0.0635 z"
+ style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.52778px;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Light';word-spacing:0px"
+ id="path85401"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 146.84421,216.2571 q 0,0.14464 0.0353,0.20814 0.0388,0.0635 0.11995,0.0952 l -0.0459,0.14464 q -0.127,-0.0247 -0.19756,-0.0952 -0.067,-0.0706 -0.0882,-0.2152 -0.1905,0.31045 -0.57503,0.31045 -0.26458,0 -0.41981,-0.14817 -0.15169,-0.15169 -0.15169,-0.40217 0,-0.28575 0.20108,-0.44097 0.20461,-0.15522 0.56445,-0.15522 h 0.35278 v -0.17992 q 0,-0.22225 -0.0988,-0.32103 -0.0988,-0.1023 -0.32809,-0.1023 -0.21166,0 -0.50094,0.10583 l -0.0529,-0.15522 q 0.31045,-0.12347 0.58209,-0.12347 0.60325,0 0.60325,0.58561 z m -0.71614,0.28222 q 0.33161,0 0.51153,-0.32455 v -0.508 h -0.32103 q -0.28222,0 -0.43039,0.10936 -0.14817,0.10936 -0.14817,0.32808 0,0.1905 0.10231,0.29281 0.1023,0.1023 0.28575,0.1023 z"
+ style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.52778px;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Light';word-spacing:0px"
+ id="path85403"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 148.42817,216.58871 q -0.17639,0.11642 -0.38805,0.11642 -0.21167,0 -0.33161,-0.12348 -0.11995,-0.127 -0.11995,-0.36336 v -1.23119 h -0.31044 v -0.16581 h 0.31044 v -0.44097 l 0.20461,-0.0247 v 0.46566 h 0.47625 l -0.0247,0.16581 h -0.45156 v 1.22061 q 0,0.16228 0.067,0.24342 0.067,0.0776 0.20461,0.0776 0.14111,0 0.28222,-0.0811 z"
+ style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.52778px;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Light';word-spacing:0px"
+ id="path85405"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 148.89737,214.0099 q 0.0705,0 0.11288,0.0423 0.0423,0.0423 0.0423,0.10583 0,0.0635 -0.0423,0.10583 -0.0423,0.0423 -0.11288,0.0423 -0.067,0 -0.10937,-0.0423 -0.0423,-0.0423 -0.0423,-0.10583 0,-0.0635 0.0423,-0.10583 0.0423,-0.0423 0.10937,-0.0423 z m 0.10583,2.65642 h -0.20461 v -1.84503 h 0.20461 z"
+ style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:3.52778px;font-family:'Fira Sans';-inkscape-font-specification:'Fira Sans Light';word-spacing:0px"
+ id="path85407"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+</svg>
diff --git a/share/extensions/other/clipart/import_web_image.ui b/share/extensions/other/clipart/import_web_image.ui
new file mode 100644
index 0000000..8d5b681
--- /dev/null
+++ b/share/extensions/other/clipart/import_web_image.ui
@@ -0,0 +1,934 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2
+
+Copyright (C) Martin Owens
+
+This file is part of Inkscape Import Web Image extension.
+
+Inkscape Import Web Image extension 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 3 of the License, or
+(at your option) any later version.
+
+Inkscape Import Web Image extension 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 Inkscape Extensions Manager. If not, see <http://www.gnu.org/licenses/>.
+
+-->
+<interface domain="inkscape-import-web-image">
+ <requires lib="gtk+" version="3.18"/>
+ <!-- interface-license-type gplv3 -->
+ <!-- interface-name Inkscape Import Web Image -->
+ <!-- interface-description Download svg files from around the internet -->
+ <!-- interface-copyright Martin Owens -->
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">gtk-remove</property>
+ </object>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">gtk-cancel</property>
+ </object>
+ <object class="GtkImage" id="image3">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">gtk-go-down</property>
+ </object>
+ <object class="GtkImage" id="image4">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">gtk-add</property>
+ </object>
+ <object class="GtkImage" id="image5">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">gtk-apply</property>
+ </object>
+ <object class="GtkImage" id="image6">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">gtk-go-up</property>
+ </object>
+ <object class="GtkImage" id="image7">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="icon-name">gtk-go-forward</property>
+ </object>
+ <object class="GtkListStore" id="service_items">
+ <columns>
+ <!-- column-name icon -->
+ <column type="GdkPixbuf"/>
+ <!-- column-name name -->
+ <column type="gchararray"/>
+ <!-- column-name key -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">import_web_image.svg</col>
+ <col id="1" translatable="yes">Test Icon</col>
+ <col id="2" translatable="yes">key</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkWindow" id="import_web_image">
+ <property name="can-focus">False</property>
+ <property name="title" translatable="yes">Import Web Image</property>
+ <property name="window-position">center</property>
+ <property name="default-width">600</property>
+ <property name="default-height">600</property>
+ <property name="icon">import_web_image.svg</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">4</property>
+ <property name="margin-end">4</property>
+ <child>
+ <object class="GtkSpinner" id="dl-searching">
+ <property name="name">searcher</property>
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="events"/>
+ <property name="margin-top">4</property>
+ <property name="margin-bottom">4</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">6</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSearchEntry" id="dl-search">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="valign">center</property>
+ <property name="primary-icon-name">edit-find-symbolic</property>
+ <property name="primary-icon-activatable">False</property>
+ <property name="primary-icon-sensitive">False</property>
+ <signal name="activate" handler="search" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="btn-next-page">
+ <property name="label" translatable="yes">Next Page</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="margin-end">10</property>
+ <property name="image">image7</property>
+ <property name="image-position">right</property>
+ <property name="always-show-image">True</property>
+ <signal name="activate" handler="show_next_page" swapped="no"/>
+ <signal name="clicked" handler="show_next_page" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="service_list">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">6</property>
+ <property name="model">service_items</property>
+ <property name="id-column">2</property>
+ <signal name="changed" handler="search_clear" swapped="no"/>
+ <child>
+ <object class="GtkCellRendererPixbuf">
+ <property name="width">48</property>
+ <property name="height">48</property>
+ <property name="stock_size">3</property>
+ </object>
+ <attributes>
+ <attribute name="pixbuf">0</attribute>
+ </attributes>
+ </child>
+ <child>
+ <object class="GtkCellRendererText">
+ <property name="xpad">8</property>
+ </object>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">4</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="shadow-type">in</property>
+ <child>
+ <object class="GtkIconView" id="results">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="margin">6</property>
+ <signal name="item-activated" handler="result_activate" swapped="no"/>
+ <signal name="selection-changed" handler="select_image" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButtonBox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">4</property>
+ <property name="margin-end">4</property>
+ <property name="margin-top">4</property>
+ <property name="margin-bottom">4</property>
+ <property name="spacing">2</property>
+ <child type="center">
+ <object class="GtkButton" id="btn-import">
+ <property name="label">Import</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="image">image5</property>
+ <property name="always-show-image">True</property>
+ <signal name="activate" handler="img_import" swapped="no"/>
+ <signal name="clicked" handler="img_import" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="label">Cancel</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="image">image2</property>
+ <property name="always-show-image">True</property>
+ <signal name="activate" handler="exit" swapped="no"/>
+ <signal name="clicked" handler="exit" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="btn-multiple">
+ <property name="label">Multiple Images</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="image">image6</property>
+ <property name="relief">none</property>
+ <property name="always-show-image">True</property>
+ <signal name="activate" handler="img_multiple" swapped="no"/>
+ <signal name="clicked" handler="img_multiple" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ <property name="non-homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="btn-single">
+ <property name="label">Single Image</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="image">image3</property>
+ <property name="relief">none</property>
+ <property name="always-show-image">True</property>
+ <signal name="activate" handler="img_single" swapped="no"/>
+ <signal name="clicked" handler="img_single" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="non-homogeneous">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack-type">end</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="multiple-box">
+ <property name="can-focus">True</property>
+ <property name="shadow-type">in</property>
+ <child>
+ <object class="GtkIconView" id="pool">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="margin">6</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="pack-type">end</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButtonBox" id="multiple-buttons">
+ <property name="can-focus">False</property>
+ <property name="margin-start">4</property>
+ <property name="margin-end">4</property>
+ <property name="margin-top">4</property>
+ <property name="margin-bottom">4</property>
+ <property name="spacing">2</property>
+ <property name="baseline-position">bottom</property>
+ <property name="layout-style">center</property>
+ <child>
+ <object class="GtkButton">
+ <property name="label" translatable="yes">Remove</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="image">image1</property>
+ <property name="always-show-image">True</property>
+ <signal name="activate" handler="img_remove" swapped="no"/>
+ <signal name="clicked" handler="img_remove" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="label" translatable="yes">Add</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="image">image4</property>
+ <property name="always-show-image">True</property>
+ <signal name="activate" handler="img_add" swapped="no"/>
+ <signal name="clicked" handler="img_add" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack-type">end</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=2 n-rows=7 -->
+ <object class="GtkGrid" id="perms">
+ <property name="name">license_info</property>
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-top">4</property>
+ <property name="row-spacing">3</property>
+ <child>
+ <object class="GtkInfoBar" id="perm-nocopyright">
+ <property name="can-focus">False</property>
+ <property name="message-type">error</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can-focus">False</property>
+ <property name="spacing">6</property>
+ <property name="layout-style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child internal-child="content_area">
+ <object class="GtkBox">
+ <property name="can-focus">False</property>
+ <property name="spacing">16</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="pixbuf">licenses/perm-pd.svg</property>
+ <property name="icon_size">6</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes">Public domain, no attribution or credit necessary.</property>
+ <property name="wrap">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkInfoBar" id="perm-sa">
+ <property name="can-focus">False</property>
+ <property name="message-type">error</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can-focus">False</property>
+ <property name="spacing">6</property>
+ <property name="layout-style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child internal-child="content_area">
+ <object class="GtkBox">
+ <property name="can-focus">False</property>
+ <property name="spacing">16</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="pixbuf">licenses/perm-sa.svg</property>
+ <property name="icon_size">6</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes">Any modifications must also be licensed under the same or a compatible license.</property>
+ <property name="wrap">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkInfoBar" id="perm-nc">
+ <property name="can-focus">False</property>
+ <property name="message-type">error</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can-focus">False</property>
+ <property name="spacing">6</property>
+ <property name="layout-style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child internal-child="content_area">
+ <object class="GtkBox">
+ <property name="can-focus">False</property>
+ <property name="spacing">16</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="pixbuf">licenses/perm-nc.svg</property>
+ <property name="icon_size">6</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes">Do not use the material for commercial purposes.</property>
+ <property name="wrap">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkInfoBar" id="perm-nd">
+ <property name="can-focus">False</property>
+ <property name="message-type">error</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can-focus">False</property>
+ <property name="spacing">6</property>
+ <property name="layout-style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child internal-child="content_area">
+ <object class="GtkBox">
+ <property name="can-focus">False</property>
+ <property name="spacing">16</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="pixbuf">licenses/perm-nd.svg</property>
+ <property name="icon_size">6</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes">If you remix, transform, or build upon the material, you may not distribute the modified material.</property>
+ <property name="wrap">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkInfoBar" id="perm-ne">
+ <property name="can-focus">False</property>
+ <property name="message-type">error</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can-focus">False</property>
+ <property name="spacing">6</property>
+ <property name="layout-style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child internal-child="content_area">
+ <object class="GtkBox">
+ <property name="can-focus">False</property>
+ <property name="spacing">16</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="pixbuf">licenses/perm-ne.svg</property>
+ <property name="icon_size">6</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes">Do not promote or endorse products using the name of the copyright holder.</property>
+ <property name="wrap">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkInfoBar" id="perm-retaincopyrightnotice">
+ <property name="can-focus">False</property>
+ <property name="message-type">error</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can-focus">False</property>
+ <property name="spacing">6</property>
+ <property name="layout-style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child internal-child="content_area">
+ <object class="GtkBox">
+ <property name="can-focus">False</property>
+ <property name="spacing">16</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="pixbuf">licenses/perm-notice.svg</property>
+ <property name="icon_size">6</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes">Include COPYRIGHT YEAR AUTHORNAME and include the software license file.</property>
+ <property name="wrap">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkInfoBar" id="perm-by">
+ <property name="can-focus">False</property>
+ <property name="message-type">error</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can-focus">False</property>
+ <property name="spacing">6</property>
+ <property name="layout-style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child internal-child="content_area">
+ <object class="GtkBox">
+ <property name="can-focus">False</property>
+ <property name="spacing">16</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="pixbuf">licenses/perm-by.svg</property>
+ <property name="icon_size">6</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes">Give credit in the figure caption or acknowledgements, link the license and indicate changes. Do not suggest endorsement.</property>
+ <property name="wrap">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/share/extensions/other/clipart/import_web_image_cli.py b/share/extensions/other/clipart/import_web_image_cli.py
new file mode 100755
index 0000000..7b073cc
--- /dev/null
+++ b/share/extensions/other/clipart/import_web_image_cli.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python3
+"""
+Testing tool for running queries.
+"""
+
+import sys
+import json
+
+from import_sources import RemoteSource
+
+def run():
+ RemoteSource.load('sources')
+ source = RemoteSource.sources[sys.argv[1]]('/tmp')
+
+ for item in source.search(sys.argv[2]):
+ if callable(item):
+ print(f"Next Page {item}")
+ else:
+ print(json.dumps(item, indent=2))
+
+if __name__ == '__main__':
+ run()
diff --git a/share/extensions/other/clipart/licenses/asl.svg b/share/extensions/other/clipart/licenses/asl.svg
new file mode 100644
index 0000000..a44a3ab
--- /dev/null
+++ b/share/extensions/other/clipart/licenses/asl.svg
@@ -0,0 +1,343 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="50"
+ height="16"
+ viewBox="0 0 50 16"
+ version="1.1"
+ id="svg5"
+ sodipodi:docname="asl.svg"
+ inkscape:version="1.2-alpha1 (8b0d57f509, 2022-03-02, custom)"
+ inkscape:export-filename="/home/doctormo/Projects/inkscape/extensions/main/other/clipart/licenses/cc-by-sa.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#999999"
+ borderopacity="1"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="2.9434"
+ inkscape:cx="-51.810831"
+ inkscape:cy="28.02881"
+ inkscape:window-width="1472"
+ inkscape:window-height="807"
+ inkscape:window-x="64"
+ inkscape:window-y="20"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer2" />
+ <defs
+ id="defs2">
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect2486"
+ is_visible="true"
+ lpeversion="1"
+ nodesatellites_param=""
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false"
+ satellites_param="" />
+ <color-profile
+ name="AL1706"
+ xlink:href="../../../../../.local/share/icc/edid-a9cf44b399fa09c3fc2589cbaadd3747.icc"
+ id="color-profile597" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="a">
+ <path
+ d="M 0.24,1.04 H 322.045 V 255.205 H 0.24 Z"
+ id="path1048" />
+ </clipPath>
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect2486-3"
+ is_visible="true"
+ lpeversion="1"
+ nodesatellites_param=""
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false"
+ satellites_param="" />
+ </defs>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-51.633091,-21.31349)"
+ sodipodi:insensitive="true"
+ style="display:none">
+ <g
+ inkscape:label="dog.svg"
+ transform="matrix(0.24767307,0,0,0.24767307,51.414234,28.015162)"
+ id="g1104">
+ <path
+ d="m 308.493,99.14 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1058" />
+ <path
+ clip-path="url(#a)"
+ d="m 64.96,104.297 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.929,73.715 47.091,72.716 44.293,69.198 41.935,67.2 35.34,66.2 33.46,66.2 23.586,66.2 16.55,65.68 8.555,57.645 6.676,55.167 5.717,52.128 4.797,48.651 3.358,44.613 1.959,45.612 1.479,39.616 0.999,33.1 1.959,31.581 6.196,30.581 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.996,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.879,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.552 -1.4,6.516 -2.319,17.03 -1.879,23.545 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.359,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.838,25.544 -0.96,3.518 0,4.518 -2.36,8.035 -1.878,2.519 -9.873,3.998 -13.151,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.036 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.518 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.998 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.519 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.919,1.48 -0.919,2.479 -0.48,-0.48 -0.96,-0.48 -1.44,-0.48 -0.439,0.48 -0.439,1 -0.919,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.035,5.476 -7.035,5.476 0,0 -3.279,-2.998 -6.117,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1060" />
+ <path
+ d="m 147.31,59.604 c 16.95,3.038 32.461,6.556 49.85,5.557 21.627,-1.52 42.775,-5.037 64.401,0 -8.434,-2 -18.788,-2 -21.626,8.554 0.48,-3.038 -0.92,-6.036 -3.758,-7.035 -4.198,-2.04 -5.637,1.998 -9.394,2.998 -5.637,1.519 -7.036,-2.519 -12.673,4.517 -3.318,-8.555 -5.197,-1.999 -10.833,-1.48 -2.838,0 -3.758,-2.518 -6.116,-3.037 -4.678,-1 -6.557,3.518 -10.794,3.518 -1.44,0 -1.44,-2.999 -3.318,-2.999 -1.4,-0.52 -2.798,0.48 -4.677,0 -2.359,0 -2.838,-2.038 -5.637,-1.519 -3.797,0.52 -5.676,6.037 -9.434,6.516 -0.92,-6.516 0,-7.515 -5.157,-10.553 z M 47.531,15.39 C 48.011,3.959 77.633,1.96 82.79,7.956 80.471,5.957 74.835,6.437 73.875,9.955 c -2.838,-2.998 -5.636,-1.999 -7.995,0 -2.358,-1.999 -4.677,-0.52 -7.036,-1 z m -32.86,15.032 c 4.238,-2.479 9.394,-2.479 13.632,-3.478 4.717,-1 8.475,-3.478 12.672,-4.997 -2.318,2.518 -5.636,5.996 -9.394,7.995 -5.637,2.958 -10.794,-0.52 -16.43,1.999 z m 105.776,126.883 c 6.596,9.554 10.873,20.067 15.55,30.621 2.839,5.996 5.677,10.993 5.197,18.03 0,8.034 -3.278,16.03 -4.237,23.545 0.96,-3.478 4.237,-12.513 8.955,-11.513 -0.96,-1.52 -2.359,-3.998 -2.359,-5.996 0,-3.039 3.278,-4.518 3.278,-7.036 0,-1.999 -3.278,-5.517 -3.758,-8.035 0,-2.479 0.48,-4.997 0.96,-6.996 -5.197,-1.999 -6.117,-7.516 -3.798,-12.553 -4.237,-0.999 -7.515,-2.998 -9.394,-7.515 -0.96,-1.999 0,-3.998 -1.44,-5.517 -1.399,-2.518 -3.757,-2.998 -5.156,-5.516 z M 264.84,144.353 c 7.995,10.553 19.308,17.549 26.823,28.582 3.758,4.997 7.995,11.513 10.354,17.55 1.4,2.478 3.278,5.996 3.278,8.994 0.48,3.518 -1.879,7.036 -1.4,10.514 1.88,-2 3.759,-6.476 3.759,-8.995 0.44,-3.518 -2.359,-3.518 -3.318,-7.515 -0.92,-3.518 0.959,-5.517 -0.44,-8.035 -0.48,-1.48 -2.838,-2.479 -3.758,-3.998 0,-1 -0.48,-3.518 -0.96,-3.998 -1.398,-2.518 -5.636,-2.518 -7.035,-5.516 -1.879,-5.517 1.879,-5.517 -3.318,-8.515 -4.677,-2.998 -14.551,-8.035 -15.99,-14.551 z m 10.353,30.541 c -0.44,2.518 -2.358,6.556 -1.399,9.554 0.48,1 2.359,0 2.359,0.52 0.48,1 0.92,2.518 1.399,3.518 1.439,4.517 -0.92,13.072 -6.596,12.072 2.358,-0.52 4.717,0.48 5.676,2.479 0,-3.998 1.4,-7.036 4.678,-8.515 -1.88,-3.038 -1.88,-6.036 -2.32,-9.074 -0.479,-3.998 -0.959,-6.516 -1.918,-10.034 -0.44,-3.518 0.48,-4.518 -1.879,-7.036 -1.879,-2.039 -3.758,-1 -6.596,-2.039 1.92,2.519 6.156,3.518 5.677,7.076 z m -149.469,19.068 c -3.798,4.997 -1.919,11.034 -2.359,17.03 0,1.999 -0.48,6.036 -1.879,7.516 -1.918,1.998 -4.237,1.519 -6.156,2.998 2.838,-2.479 7.076,-2.479 10.394,-1.48 -1.44,-4.517 -3.318,-9.034 2.318,-10.033 -2.318,-3.518 -1.399,-4.997 -1.399,-8.515 -0.48,-2.998 -1.879,-6.996 -0.92,-10.034 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1062" />
+ <path
+ d="m 117.649,122.206 c 0.96,-2.998 -0.92,-6.516 -0.44,-9.514 0.44,-3.998 1.879,-5.517 4.197,-8.515 -6.076,-2.519 -4.677,-6.036 -4.197,-11.553 0.44,-4.997 -2.359,-5.517 -4.717,-10.034 -2.838,-6.516 -2.838,-17.03 -3.278,-24.065 0,-7.996 -2.838,-14.032 -8.955,-19.029 -2.798,-2.518 -7.035,-7.036 -10.793,-7.036 -5.677,-0.52 -9.435,6.037 -11.313,11.034 -1.4,4.997 -4.238,17.549 -3.278,23.066 l 9.874,48.13 1.878,1.52 c 4.238,3.477 1.88,5.516 -0.48,7.515 0.48,1 0.96,1.48 1.88,1.999 h 1.879 c 1.439,0 2.838,0 3.757,0.52 0.48,0 1.44,0.48 2.359,0.48 0,3.517 -2.359,7.035 -1.88,10.513 2.84,-0.48 5.638,-1 7.077,-3.998 -0.96,2.998 -1.44,7.036 -1.44,9.514 1.44,-1.998 2.36,-4.996 2.839,-5.996 3.278,-6.036 13.632,-8.515 15.03,-14.551 z m 3.318,47.771 c 2.798,5.996 3.717,13.032 6.076,19.028 2.798,6.037 4.197,10.554 4.197,17.55 0.48,5.037 -0.48,13.072 -3.757,17.07 -3.238,3.997 -8.875,6.036 -12.633,9.514 6.117,-5.997 13.592,1 17.79,-6.996 3.757,-7.036 4.197,-14.551 4.197,-22.067 0,-8.554 -4.677,-10.553 -7.475,-17.549 -2.799,-6.036 -4.678,-14.551 -9.834,-18.589 z m 46.931,20.388 c 1.4,4.037 4.198,18.069 -2.358,16.55 0,3.517 0.92,6.516 -0.48,10.034 -1.4,-2 -2.838,-6.037 -5.157,-2.519 1.879,1.999 0,1.999 0,3.518 0.44,1.999 0.44,3.997 0.92,5.996 -6.117,1 -7.516,6.516 -10.794,11.034 -3.798,4.517 -8.954,7.515 -9.434,14.51 1.439,-4.996 -0.48,-11.512 2.838,-15.51 0,0.48 2.798,0 3.758,-1 1.879,-1.518 1.399,-3.997 2.358,-6.036 2.359,-4.997 2.799,-2.478 6.117,-5.996 3.278,-3.518 0.92,-7.036 0,-11.513 4.237,2.479 3.757,-4.037 2.798,-6.516 4.717,0 6.596,-1 6.116,-5.517 -0.48,-2.518 -2.358,-8.514 -3.278,-10.513 2.799,1.999 5.637,0.48 7.516,-1.04 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1064" />
+ <path
+ d="m 166.06,187.846 c -0.48,-1.959 -1.4,-5.477 -0.48,-7.435 0.96,-2.519 3.318,-2.999 3.757,-4.997 0.96,-3.478 -3.278,-6.476 1.88,-8.475 -2.32,0 -4.678,1.999 -6.557,-1 1.4,5.997 -4.717,8.995 -1.879,14.472 z m 11.752,-26.544 c -0.96,4.997 -3.318,12.992 3.278,14.991 3.318,1 11.753,-9.474 13.192,-2.998 2.359,-3.998 5.157,-3.478 8.915,-4.477 1.439,-0.52 1.879,-2.999 3.798,-2.519 1.878,0.52 2.798,3.518 2.798,4.997 0.96,-1.999 3.318,-7.515 5.636,-8.515 5.197,-1.479 4.238,3.038 5.677,6.037 1.4,-2 1.879,-5.517 4.237,-5.517 2.799,-0.52 4.198,2.998 4.678,4.997 1.878,-1.999 1.878,-8.515 4.717,-8.515 2.358,-0.48 3.757,2.998 3.278,5.037 2.838,-3.038 -0.48,-9.514 3.318,-11.513 0.92,1.48 1.399,3.478 1.399,4.477 1.399,-4.997 0.92,-7.475 6.596,-6.995 4.677,0 6.116,0.999 7.036,5.996 5.636,-4.997 6.596,4.997 6.596,8.515 3.757,-4.517 5.156,-8.995 2.358,-13.992 -2.838,-4.517 -4.717,-9.514 -6.116,-15.03 -1.4,1.998 -3.758,7.995 -6.116,7.995 -3.318,0 -4.238,-7.476 -5.197,-9.515 -1.4,2.04 -3.278,10.034 -5.637,10.514 -4.237,1.519 -6.596,-4.477 -7.995,-7.476 -1.879,2.999 -1.4,9.475 -4.717,11.993 -4.677,3.998 -4.198,-1.519 -8.435,-2.998 -1.879,7.515 -2.359,10.993 -9.914,12.512 -1.879,0 -1.879,0 -3.758,0.48 -1.879,0.52 -3.757,1.999 -5.636,2.519 -9.395,3.997 -19.269,1.479 -21.627,-9.515 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1066" />
+ <path
+ d="m 263.84,161.782 c 4.238,-4.477 13.192,3.518 16.03,6.516 4.238,4.038 5.677,8.555 5.197,14.031 0,5.517 -0.48,14.552 -3.318,19.549 -0.92,1.998 -3.757,5.037 -6.116,6.516 -2.359,1.519 -6.156,1.519 -7.076,3.997 6.117,-1.479 14.631,-1 16.99,-7.995 2.359,-7.515 2.359,-16.03 2.838,-23.546 0.44,-8.035 -3.797,-11.513 -9.914,-16.03 -2.838,-2.518 -10.873,-12.552 -13.711,-15.03 -2.799,-3.039 -0.44,1.998 -5.197,1.478 z m 48.93,57.645 c 0.92,5.517 5.157,13.552 1.88,18.549 -1.88,3.038 -15.112,7.515 -13.193,0 5.157,1 5.637,-3.998 7.516,-7.516 2.838,-4.997 2.838,-3.518 1.919,-9.034 -0.96,-8.515 3.757,-17.03 2.798,-25.585 z M 292.583,79.112 c 3.757,7.036 10.353,8.555 10.793,18.07 0.96,7.035 -0.44,15.07 1.879,22.066 1.4,6.036 4.717,11.073 7.036,16.59 0.96,1.479 4.237,5.996 4.237,7.515 0.44,2.998 -2.358,4.517 -1.879,9.035 -6.116,-0.52 -1.399,5.516 -0.48,8.514 -2.358,-2.478 -7.035,-4.996 -7.955,-8.514 7.956,-2.519 2.799,-11.034 -1.439,-14.032 5.197,-9.034 -3.278,-12.073 -7.955,-17.59 3.758,-4.516 1.879,-8.034 -1.879,-11.552 5.157,-5.997 4.238,-26.584 -2.358,-31.621 z M 39.536,63.601 c 3.318,1.52 5.197,1.52 7.555,5.037 1.88,2.479 2.359,5.477 4.238,7.996 1.399,1.998 3.278,3.997 4.717,6.476 1.4,1.519 4.677,5.996 6.596,7.995 0.92,-5.997 -2.838,-9.474 -2.359,-14.991 0.44,-3.998 2.359,-8.475 3.758,-11.993 1.879,-4.997 3.278,-8.515 6.116,-11.993 3.278,-3.517 7.516,-7.995 6.596,-14.031 -1.399,6.516 -7.075,15.51 -14.59,12.512 -2.839,5.997 -4.238,7.516 -10.354,7.516 2.798,2.478 5.636,6.996 4.237,11.513 -1.879,-1.999 -5.197,-4.517 -7.555,-5.037 -3.278,-0.48 -5.637,1.519 -8.955,-1.999 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1068" />
+ <path
+ d="m 111.053,226.023 c -1.84,0.52 -3.278,2.998 -3.278,3.998 m 153.267,-88.747 c 1.439,7.556 13.672,16.07 17.909,22.067 3.318,4.517 10.833,9.035 12.233,15.03 M 121.446,164.94 c 2.839,4.517 5.197,10.514 7.076,15.03 0.92,2.52 1.4,4.998 2.359,7.516 1.399,2.519 2.798,2.999 4.677,5.517 5.157,6.996 0.48,27.503 -2.798,35.538 -0.48,1.48 -0.96,2.999 -1.88,3.478 M 52.288,6.396 c -3.278,1.52 -7.955,7.076 -9.354,10.594 -1.879,3.518 -6.076,3.997 -7.515,4.997 m 100.019,222.585 c -1.839,0.52 -2.319,3.038 -3.278,4.557 m -1.839,-7.995 c -3.278,0 -7.036,1.519 -7.995,4.957 m -11.673,-25.505 c -1.879,1 -4.237,1 -6.156,2.959 m 168.378,-16.55 c -2.319,0.52 -5.597,1.519 -6.077,3.997 m 2.799,-9.514 c -1.92,0 -3.838,1.04 -5.277,2.558 m 38.137,30.542 c -1.88,2.039 -3.758,4.037 -3.758,6.556 m -3.278,-9.594 c -1.839,1.559 -4.637,2.558 -5.117,5.596 m 21.986,-3.997 c -0.919,1.519 -1.358,2.518 -1.838,3.997 M 181.17,151.828 c -1.399,0.52 -4.717,4.038 -6.116,5.037 2.358,2.518 0.96,10.554 -2.838,11.553 0.48,2.039 -0.48,2.518 0.48,4.517 m -52.169,-7.595 c 0.92,-4.477 -5.197,-3.998 -7.076,-6.516 1.44,-1.48 3.318,-3.478 1.88,-5.477 -1.88,0.48 -3.759,0 -5.158,-1.519 1.4,-1.999 2.359,-4.997 0.48,-7.036 -1.919,1.52 -3.798,1.04 -6.156,0.52 M 11.473,32.94 c 0.44,7.076 -3.358,11.593 -8.595,9.075"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1070" />
+ <path
+ d="m 9.514,39.976 c 0.96,-1 2.359,-6.476 1.44,-7.955 -0.96,-1.52 -4.718,-1.52 -6.637,-1 -2.358,1 -3.318,2.998 -2.838,8.475 0,1.999 0.48,2.998 0.48,3.958 l 1.439,-0.96 c 2.359,0 4.717,0 6.116,-2.518 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1072" />
+ <path
+ d="m 55.566,32.54 c -2.798,-1.479 -4.197,-5.996 -7.035,-7.995 -2.799,-1.999 -2.799,0.52 -4.718,3.518"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1074" />
+ <path
+ d="M 52.848,29.102 C 49.09,38.137 42.454,27.104 45.772,25.584 m 11.233,0.96 C 55.606,22.067 50.01,18.549 46.692,19.548 m -33.98,39.136 c 3.318,-1.998 4.278,0.96 6.636,2.439 3.318,1.959 6.157,-0.48 8.955,0.52"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1076" />
+ <path
+ clip-path="url(#a)"
+ d="m 65,104.337 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.969,73.755 47.131,72.756 44.333,69.238 41.975,67.239 35.379,66.24 33.5,66.24 23.626,66.24 16.59,65.72 8.595,57.685 6.715,55.207 5.757,52.168 4.837,48.69 3.397,44.653 2,45.652 1.52,39.656 1.04,33.14 2,31.621 6.237,30.621 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.995,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.88,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.551 -1.4,6.517 -2.319,17.03 -1.879,23.546 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.36,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.839,25.544 -0.959,3.518 0,4.518 -2.358,8.035 -1.879,2.519 -9.874,3.998 -13.152,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.037 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.517 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.999 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.518 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.92,1.48 -0.92,2.479 -0.479,-0.48 -0.958,-0.48 -1.438,-0.48 -0.44,0.48 -0.44,1 -0.92,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.036,5.476 -7.036,5.476 0,0 -3.278,-2.998 -6.116,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1078" />
+ <path
+ d="m 308.533,99.18 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 v 0.52 c 0,0 0,0 0,0 v 1.519"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1080" />
+ <path
+ d="m 95.102,24.905 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.551 0,3.038 0,5.517 0.48,8.555 0.48,3.518 0,7.036 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.92,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.196,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.076,-1.519 -1.88,1.52 -0.92,3.998 -0.44,6.036 -1.44,0 -2.839,-0.52 -3.798,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.514,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.96,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1082" />
+ <path
+ d="m 81.91,41.055 c -1.399,4.038 -3.278,8.035 -5.596,11.033 -1.88,2.519 -4.238,5.037 -5.157,7.516 -0.48,1.519 0,3.038 -0.48,4.517 -0.44,1.52 -2.318,2.998 -2.798,4.517 -0.48,1 -0.48,2.519 -0.48,3.518 -0.44,1.48 -1.879,2.519 -1.879,3.998 0,1.519 1.44,2.998 1.44,4.517 0.44,1.52 0.44,2.998 0.44,4.517 0,3.518 -0.92,6.996 -0.44,10.034 0,2 0.919,3.478 0.919,5.517 0,1.999 -0.92,3.478 -0.48,5.477 0.48,1.519 0.96,2.038 1.4,3.517 0.959,1.52 0,3.518 0.479,5.037 3.278,-0.999 2.798,2.479 3.278,4.478 0.96,-2 3.758,-2.479 5.637,-2 -0.96,-0.479 -3.758,-0.998 -4.678,-1.478 -1.878,-1.52 0,-6.037 1.4,-7.516 -1.4,0 -4.238,-0.52 -4.678,-2.038 -0.959,-2 3.278,-4.478 3.718,-5.997 -1.879,-0.52 -3.278,-1 -3.718,-2.998 -1.439,-3.518 1.4,-5.037 1.84,-8.035 0,-1.999 -1.4,-1.48 -2.32,-3.518 -0.959,-1.999 0,-4.477 1.88,-5.996 -2.359,-3.518 -2.839,-5.517 -0.48,-9.035 0.92,-1.479 0.92,-0.48 0.92,-1.999 0.479,-1.998 -1.4,-3.517 0.959,-5.516 0.92,-1 1.879,-0.48 2.318,-1.999 0.48,-1 0,-3.998 0.96,-5.517 0.48,-1.998 0.92,-4.517 1.879,-6.995 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1084" />
+ <path
+ d="m 95.142,24.945 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.55 0,3.04 0,5.518 0.48,8.556 0.48,3.518 0,7.035 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.919,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.197,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.077,-1.519 -1.878,1.52 -0.919,3.998 -0.44,6.036 -1.438,0 -2.838,-0.52 -3.797,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.515,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.959,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1086" />
+ <path
+ d="m 103.058,54.087 c -0.48,2.998 0,5.997 0,9.035 v 9.994 c 0.44,6.556 1.399,13.551 3.278,19.588 0.48,1 0.959,1.999 1.399,3.478 0,1.519 0,1 -0.44,2.518 -0.48,1.999 -0.96,2.998 -0.96,5.037 0.48,1.999 0.96,2.998 0.96,4.477 -0.48,0.52 -1.44,1.52 -1.44,2.519 -0.439,1 0,2.518 -0.439,2.998 -0.48,1 -1.919,1 -2.838,2.039 -0.48,1.479 0,2.998 -0.96,4.477 -1.399,-1 -2.798,0.52 -3.757,1 -0.92,-1 -1.88,-1.48 -2.839,-1 0.96,-1 3.798,-2.478 4.718,-3.478 0.959,-2.039 0,-4.517 -0.92,-7.036 2.359,0 3.278,-2.518 3.278,-4.996 0,-2.04 -0.92,-2.04 -1.879,-3.518 -0.96,-2.519 1.4,-4.038 1.88,-6.516 0.959,-4.038 -0.92,-5.517 -2.84,-8.036 4.238,-4.517 1.92,-8.035 0.48,-12.512 -0.919,-3.038 0.96,-5.517 0.48,-9.034 0,-2.999 1.4,-6.037 1.4,-9.035 0.48,-1.999 0.959,-4.997 0.48,-7.036 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1088" />
+ <path
+ d="m 45.253,24.545 c -1.88,3.478 2.838,10.914 6.116,6.956 2.318,-2.479 -3.758,-9.954 -5.637,-6.956 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1090" />
+ <path
+ d="m 45.692,26.944 c 0,-0.52 0.44,-1 0.92,-1 0.52,0 0.92,0.48 0.92,1 0,0.56 -0.4,1 -0.92,1 -0.48,0 -0.92,-0.44 -0.92,-1 z"
+ fill="#ffffff"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1092" />
+ <path
+ d="m 2.878,39.016 c 0.96,0 2.399,0.48 3.358,0.48 0.96,0 1.44,-1.479 2.399,-1.999"
+ fill="none"
+ stroke="#ffffff"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1094" />
+ <path
+ d="m 80.111,31.46 c -1.439,-0.519 -3.358,0 -3.837,2.08 1.919,0.48 3.837,-1.04 5.277,0.48 -0.96,2.078 -2.879,3.078 -4.798,3.078 M 96.981,26.064 c -2.798,-1.519 -7.036,3.038 -1.879,3.518 1.88,0.52 3.278,-1.519 4.238,1 0.44,1.998 -3.278,5.036 -4.238,6.516 M 47.171,20.987 c -0.48,-3.438 5.677,-4.437 2.399,1.96 M 26.944,63.082 c 0,-1 0.96,-3.478 -0.48,-3.478 -1.919,-0.52 -2.878,2.478 -2.399,3.478 m 82.271,86.348 c 0,-2.04 0.48,-4.558 0.959,-6.637 2.319,0.52 2.319,4.118 1.879,6.636 m 71.516,4.917 c -3.717,-6.915 -6.556,0.48 -2.798,2.439 m 83.709,-12.952 c 0.92,-0.48 1.84,-1 2.719,-1.999 m 7.995,67.159 c -0.44,-4.037 -6.556,-4.557 -3.718,0 m 33.86,28.143 c -0.96,-1.04 -1.92,-1.599 -2.879,-1.599 m -5.116,-1.399 c -2.359,-6.116 -6.157,1.56 -2.359,2.039"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1096" />
+ <path
+ d="m 267.638,200.039 c -1.4,1.999 1.399,4.997 0.48,5.996 -1.88,1.999 -3.798,-1 -3.798,-2.478 m -155.146,16.07 c 0,1.479 0.44,2.478 0.44,3.918 -1.4,-0.48 -2.319,-0.96 -3.278,-2.439 m 1.838,4.917 c 0.52,1.52 1,2.518 2,3.518 m 18.868,10.514 c 2.318,6.036 -2.359,2.518 -4.238,-0.52"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1098" />
+ <path
+ clip-path="url(#a)"
+ d="m 135.078,244.092 c -0.44,1.999 0.96,2.519 1.4,3.998 -2.32,0.48 -3.718,-1 -5.597,-1.48"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1100" />
+ <path
+ d="m 121.926,242.573 c 0.48,2.039 1.879,3.038 3.278,3.518"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1102" />
+ </g>
+ </g>
+ <g
+ id="layer2"
+ inkscape:label="Layer 2"
+ clip-path="none"
+ inkscape:groupmode="layer"
+ transform="matrix(0.5,0,0,0.5,0,150)">
+ <rect
+ style="opacity:0.8;fill:#ffffff;stroke-width:2.06559;stop-color:#000000"
+ id="rect1552"
+ width="100"
+ height="32"
+ x="0"
+ y="-300" />
+ <g
+ aria-label="ASL"
+ id="text378"
+ style="font-size:32.4222px;line-height:1.25;font-family:'Arial Black';-inkscape-font-specification:'Arial Black, ';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#a40000;stroke-width:1.51979">
+ <path
+ d="m 31.026362,-276.22689 h -8.168875 l -1.124011,3.83114 h -7.329824 l 8.722965,-23.20847 h 7.820589 l 8.722965,23.20847 h -7.503966 z m -1.50396,-5.01848 -2.564646,-8.34301 -2.548816,8.34301 z"
+ id="path588" />
+ <path
+ d="m 40.715026,-280.07386 6.823227,-0.42744 q 0.221636,1.66227 0.902375,2.53298 1.108181,1.40898 3.166231,1.40898 1.535622,0 2.358841,-0.71241 0.839052,-0.72823 0.839052,-1.6781 0,-0.90237 -0.791558,-1.61478 -0.791558,-0.7124 -3.672827,-1.34564 -4.717684,-1.06069 -6.72824,-2.81795 -2.026387,-1.75726 -2.026387,-4.48022 0,-1.78892 1.029025,-3.37203 1.044856,-1.59895 3.118736,-2.50132 Q 47.823214,-296 51.448547,-296 q 4.448554,0 6.775733,1.66227 2.343011,1.64644 2.786283,5.25594 l -6.759902,0.39578 q -0.269129,-1.56728 -1.139843,-2.27968 -0.854882,-0.71241 -2.374673,-0.71241 -1.250661,0 -1.883907,0.53826 -0.633246,0.52243 -0.633246,1.28233 0,0.55409 0.522428,0.99736 0.506597,0.4591 2.406335,0.85488 4.701853,1.0132 6.72824,2.05805 2.042219,1.02903 2.960425,2.56465 0.934038,1.53562 0.934038,3.43536 0,2.23219 -1.234829,4.1161 -1.23483,1.88391 -3.451192,2.86544 -2.216361,0.9657 -5.588396,0.9657 -5.920851,0 -8.200537,-2.27969 -2.279686,-2.27968 -2.580478,-5.7942 z"
+ id="path590" />
+ <path
+ d="m 65.379963,-295.60422 h 7.171512 v 17.49342 H 83.7441 v 5.71505 H 65.379963 Z"
+ id="path592" />
+ </g>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="Layer 3" />
+</svg>
diff --git a/share/extensions/other/clipart/licenses/bsd.svg b/share/extensions/other/clipart/licenses/bsd.svg
new file mode 100644
index 0000000..dbad70c
--- /dev/null
+++ b/share/extensions/other/clipart/licenses/bsd.svg
@@ -0,0 +1,343 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="50"
+ height="16"
+ viewBox="0 0 50 16"
+ version="1.1"
+ id="svg5"
+ sodipodi:docname="bsd.svg"
+ inkscape:version="1.2-alpha1 (8b0d57f509, 2022-03-02, custom)"
+ inkscape:export-filename="/home/doctormo/Projects/inkscape/extensions/main/other/clipart/licenses/cc-by-sa.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#999999"
+ borderopacity="1"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="2.9434"
+ inkscape:cx="-51.810831"
+ inkscape:cy="28.02881"
+ inkscape:window-width="1472"
+ inkscape:window-height="807"
+ inkscape:window-x="64"
+ inkscape:window-y="20"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer2" />
+ <defs
+ id="defs2">
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect2486"
+ is_visible="true"
+ lpeversion="1"
+ nodesatellites_param=""
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false"
+ satellites_param="" />
+ <color-profile
+ name="AL1706"
+ xlink:href="../../../../../.local/share/icc/edid-a9cf44b399fa09c3fc2589cbaadd3747.icc"
+ id="color-profile444" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="a">
+ <path
+ d="M 0.24,1.04 H 322.045 V 255.205 H 0.24 Z"
+ id="path1048" />
+ </clipPath>
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect2486-3"
+ is_visible="true"
+ lpeversion="1"
+ nodesatellites_param=""
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false"
+ satellites_param="" />
+ </defs>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-51.633091,-21.31349)"
+ sodipodi:insensitive="true"
+ style="display:none">
+ <g
+ inkscape:label="dog.svg"
+ transform="matrix(0.24767307,0,0,0.24767307,51.414234,28.015162)"
+ id="g1104">
+ <path
+ d="m 308.493,99.14 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1058" />
+ <path
+ clip-path="url(#a)"
+ d="m 64.96,104.297 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.929,73.715 47.091,72.716 44.293,69.198 41.935,67.2 35.34,66.2 33.46,66.2 23.586,66.2 16.55,65.68 8.555,57.645 6.676,55.167 5.717,52.128 4.797,48.651 3.358,44.613 1.959,45.612 1.479,39.616 0.999,33.1 1.959,31.581 6.196,30.581 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.996,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.879,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.552 -1.4,6.516 -2.319,17.03 -1.879,23.545 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.359,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.838,25.544 -0.96,3.518 0,4.518 -2.36,8.035 -1.878,2.519 -9.873,3.998 -13.151,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.036 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.518 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.998 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.519 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.919,1.48 -0.919,2.479 -0.48,-0.48 -0.96,-0.48 -1.44,-0.48 -0.439,0.48 -0.439,1 -0.919,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.035,5.476 -7.035,5.476 0,0 -3.279,-2.998 -6.117,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1060" />
+ <path
+ d="m 147.31,59.604 c 16.95,3.038 32.461,6.556 49.85,5.557 21.627,-1.52 42.775,-5.037 64.401,0 -8.434,-2 -18.788,-2 -21.626,8.554 0.48,-3.038 -0.92,-6.036 -3.758,-7.035 -4.198,-2.04 -5.637,1.998 -9.394,2.998 -5.637,1.519 -7.036,-2.519 -12.673,4.517 -3.318,-8.555 -5.197,-1.999 -10.833,-1.48 -2.838,0 -3.758,-2.518 -6.116,-3.037 -4.678,-1 -6.557,3.518 -10.794,3.518 -1.44,0 -1.44,-2.999 -3.318,-2.999 -1.4,-0.52 -2.798,0.48 -4.677,0 -2.359,0 -2.838,-2.038 -5.637,-1.519 -3.797,0.52 -5.676,6.037 -9.434,6.516 -0.92,-6.516 0,-7.515 -5.157,-10.553 z M 47.531,15.39 C 48.011,3.959 77.633,1.96 82.79,7.956 80.471,5.957 74.835,6.437 73.875,9.955 c -2.838,-2.998 -5.636,-1.999 -7.995,0 -2.358,-1.999 -4.677,-0.52 -7.036,-1 z m -32.86,15.032 c 4.238,-2.479 9.394,-2.479 13.632,-3.478 4.717,-1 8.475,-3.478 12.672,-4.997 -2.318,2.518 -5.636,5.996 -9.394,7.995 -5.637,2.958 -10.794,-0.52 -16.43,1.999 z m 105.776,126.883 c 6.596,9.554 10.873,20.067 15.55,30.621 2.839,5.996 5.677,10.993 5.197,18.03 0,8.034 -3.278,16.03 -4.237,23.545 0.96,-3.478 4.237,-12.513 8.955,-11.513 -0.96,-1.52 -2.359,-3.998 -2.359,-5.996 0,-3.039 3.278,-4.518 3.278,-7.036 0,-1.999 -3.278,-5.517 -3.758,-8.035 0,-2.479 0.48,-4.997 0.96,-6.996 -5.197,-1.999 -6.117,-7.516 -3.798,-12.553 -4.237,-0.999 -7.515,-2.998 -9.394,-7.515 -0.96,-1.999 0,-3.998 -1.44,-5.517 -1.399,-2.518 -3.757,-2.998 -5.156,-5.516 z M 264.84,144.353 c 7.995,10.553 19.308,17.549 26.823,28.582 3.758,4.997 7.995,11.513 10.354,17.55 1.4,2.478 3.278,5.996 3.278,8.994 0.48,3.518 -1.879,7.036 -1.4,10.514 1.88,-2 3.759,-6.476 3.759,-8.995 0.44,-3.518 -2.359,-3.518 -3.318,-7.515 -0.92,-3.518 0.959,-5.517 -0.44,-8.035 -0.48,-1.48 -2.838,-2.479 -3.758,-3.998 0,-1 -0.48,-3.518 -0.96,-3.998 -1.398,-2.518 -5.636,-2.518 -7.035,-5.516 -1.879,-5.517 1.879,-5.517 -3.318,-8.515 -4.677,-2.998 -14.551,-8.035 -15.99,-14.551 z m 10.353,30.541 c -0.44,2.518 -2.358,6.556 -1.399,9.554 0.48,1 2.359,0 2.359,0.52 0.48,1 0.92,2.518 1.399,3.518 1.439,4.517 -0.92,13.072 -6.596,12.072 2.358,-0.52 4.717,0.48 5.676,2.479 0,-3.998 1.4,-7.036 4.678,-8.515 -1.88,-3.038 -1.88,-6.036 -2.32,-9.074 -0.479,-3.998 -0.959,-6.516 -1.918,-10.034 -0.44,-3.518 0.48,-4.518 -1.879,-7.036 -1.879,-2.039 -3.758,-1 -6.596,-2.039 1.92,2.519 6.156,3.518 5.677,7.076 z m -149.469,19.068 c -3.798,4.997 -1.919,11.034 -2.359,17.03 0,1.999 -0.48,6.036 -1.879,7.516 -1.918,1.998 -4.237,1.519 -6.156,2.998 2.838,-2.479 7.076,-2.479 10.394,-1.48 -1.44,-4.517 -3.318,-9.034 2.318,-10.033 -2.318,-3.518 -1.399,-4.997 -1.399,-8.515 -0.48,-2.998 -1.879,-6.996 -0.92,-10.034 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1062" />
+ <path
+ d="m 117.649,122.206 c 0.96,-2.998 -0.92,-6.516 -0.44,-9.514 0.44,-3.998 1.879,-5.517 4.197,-8.515 -6.076,-2.519 -4.677,-6.036 -4.197,-11.553 0.44,-4.997 -2.359,-5.517 -4.717,-10.034 -2.838,-6.516 -2.838,-17.03 -3.278,-24.065 0,-7.996 -2.838,-14.032 -8.955,-19.029 -2.798,-2.518 -7.035,-7.036 -10.793,-7.036 -5.677,-0.52 -9.435,6.037 -11.313,11.034 -1.4,4.997 -4.238,17.549 -3.278,23.066 l 9.874,48.13 1.878,1.52 c 4.238,3.477 1.88,5.516 -0.48,7.515 0.48,1 0.96,1.48 1.88,1.999 h 1.879 c 1.439,0 2.838,0 3.757,0.52 0.48,0 1.44,0.48 2.359,0.48 0,3.517 -2.359,7.035 -1.88,10.513 2.84,-0.48 5.638,-1 7.077,-3.998 -0.96,2.998 -1.44,7.036 -1.44,9.514 1.44,-1.998 2.36,-4.996 2.839,-5.996 3.278,-6.036 13.632,-8.515 15.03,-14.551 z m 3.318,47.771 c 2.798,5.996 3.717,13.032 6.076,19.028 2.798,6.037 4.197,10.554 4.197,17.55 0.48,5.037 -0.48,13.072 -3.757,17.07 -3.238,3.997 -8.875,6.036 -12.633,9.514 6.117,-5.997 13.592,1 17.79,-6.996 3.757,-7.036 4.197,-14.551 4.197,-22.067 0,-8.554 -4.677,-10.553 -7.475,-17.549 -2.799,-6.036 -4.678,-14.551 -9.834,-18.589 z m 46.931,20.388 c 1.4,4.037 4.198,18.069 -2.358,16.55 0,3.517 0.92,6.516 -0.48,10.034 -1.4,-2 -2.838,-6.037 -5.157,-2.519 1.879,1.999 0,1.999 0,3.518 0.44,1.999 0.44,3.997 0.92,5.996 -6.117,1 -7.516,6.516 -10.794,11.034 -3.798,4.517 -8.954,7.515 -9.434,14.51 1.439,-4.996 -0.48,-11.512 2.838,-15.51 0,0.48 2.798,0 3.758,-1 1.879,-1.518 1.399,-3.997 2.358,-6.036 2.359,-4.997 2.799,-2.478 6.117,-5.996 3.278,-3.518 0.92,-7.036 0,-11.513 4.237,2.479 3.757,-4.037 2.798,-6.516 4.717,0 6.596,-1 6.116,-5.517 -0.48,-2.518 -2.358,-8.514 -3.278,-10.513 2.799,1.999 5.637,0.48 7.516,-1.04 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1064" />
+ <path
+ d="m 166.06,187.846 c -0.48,-1.959 -1.4,-5.477 -0.48,-7.435 0.96,-2.519 3.318,-2.999 3.757,-4.997 0.96,-3.478 -3.278,-6.476 1.88,-8.475 -2.32,0 -4.678,1.999 -6.557,-1 1.4,5.997 -4.717,8.995 -1.879,14.472 z m 11.752,-26.544 c -0.96,4.997 -3.318,12.992 3.278,14.991 3.318,1 11.753,-9.474 13.192,-2.998 2.359,-3.998 5.157,-3.478 8.915,-4.477 1.439,-0.52 1.879,-2.999 3.798,-2.519 1.878,0.52 2.798,3.518 2.798,4.997 0.96,-1.999 3.318,-7.515 5.636,-8.515 5.197,-1.479 4.238,3.038 5.677,6.037 1.4,-2 1.879,-5.517 4.237,-5.517 2.799,-0.52 4.198,2.998 4.678,4.997 1.878,-1.999 1.878,-8.515 4.717,-8.515 2.358,-0.48 3.757,2.998 3.278,5.037 2.838,-3.038 -0.48,-9.514 3.318,-11.513 0.92,1.48 1.399,3.478 1.399,4.477 1.399,-4.997 0.92,-7.475 6.596,-6.995 4.677,0 6.116,0.999 7.036,5.996 5.636,-4.997 6.596,4.997 6.596,8.515 3.757,-4.517 5.156,-8.995 2.358,-13.992 -2.838,-4.517 -4.717,-9.514 -6.116,-15.03 -1.4,1.998 -3.758,7.995 -6.116,7.995 -3.318,0 -4.238,-7.476 -5.197,-9.515 -1.4,2.04 -3.278,10.034 -5.637,10.514 -4.237,1.519 -6.596,-4.477 -7.995,-7.476 -1.879,2.999 -1.4,9.475 -4.717,11.993 -4.677,3.998 -4.198,-1.519 -8.435,-2.998 -1.879,7.515 -2.359,10.993 -9.914,12.512 -1.879,0 -1.879,0 -3.758,0.48 -1.879,0.52 -3.757,1.999 -5.636,2.519 -9.395,3.997 -19.269,1.479 -21.627,-9.515 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1066" />
+ <path
+ d="m 263.84,161.782 c 4.238,-4.477 13.192,3.518 16.03,6.516 4.238,4.038 5.677,8.555 5.197,14.031 0,5.517 -0.48,14.552 -3.318,19.549 -0.92,1.998 -3.757,5.037 -6.116,6.516 -2.359,1.519 -6.156,1.519 -7.076,3.997 6.117,-1.479 14.631,-1 16.99,-7.995 2.359,-7.515 2.359,-16.03 2.838,-23.546 0.44,-8.035 -3.797,-11.513 -9.914,-16.03 -2.838,-2.518 -10.873,-12.552 -13.711,-15.03 -2.799,-3.039 -0.44,1.998 -5.197,1.478 z m 48.93,57.645 c 0.92,5.517 5.157,13.552 1.88,18.549 -1.88,3.038 -15.112,7.515 -13.193,0 5.157,1 5.637,-3.998 7.516,-7.516 2.838,-4.997 2.838,-3.518 1.919,-9.034 -0.96,-8.515 3.757,-17.03 2.798,-25.585 z M 292.583,79.112 c 3.757,7.036 10.353,8.555 10.793,18.07 0.96,7.035 -0.44,15.07 1.879,22.066 1.4,6.036 4.717,11.073 7.036,16.59 0.96,1.479 4.237,5.996 4.237,7.515 0.44,2.998 -2.358,4.517 -1.879,9.035 -6.116,-0.52 -1.399,5.516 -0.48,8.514 -2.358,-2.478 -7.035,-4.996 -7.955,-8.514 7.956,-2.519 2.799,-11.034 -1.439,-14.032 5.197,-9.034 -3.278,-12.073 -7.955,-17.59 3.758,-4.516 1.879,-8.034 -1.879,-11.552 5.157,-5.997 4.238,-26.584 -2.358,-31.621 z M 39.536,63.601 c 3.318,1.52 5.197,1.52 7.555,5.037 1.88,2.479 2.359,5.477 4.238,7.996 1.399,1.998 3.278,3.997 4.717,6.476 1.4,1.519 4.677,5.996 6.596,7.995 0.92,-5.997 -2.838,-9.474 -2.359,-14.991 0.44,-3.998 2.359,-8.475 3.758,-11.993 1.879,-4.997 3.278,-8.515 6.116,-11.993 3.278,-3.517 7.516,-7.995 6.596,-14.031 -1.399,6.516 -7.075,15.51 -14.59,12.512 -2.839,5.997 -4.238,7.516 -10.354,7.516 2.798,2.478 5.636,6.996 4.237,11.513 -1.879,-1.999 -5.197,-4.517 -7.555,-5.037 -3.278,-0.48 -5.637,1.519 -8.955,-1.999 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1068" />
+ <path
+ d="m 111.053,226.023 c -1.84,0.52 -3.278,2.998 -3.278,3.998 m 153.267,-88.747 c 1.439,7.556 13.672,16.07 17.909,22.067 3.318,4.517 10.833,9.035 12.233,15.03 M 121.446,164.94 c 2.839,4.517 5.197,10.514 7.076,15.03 0.92,2.52 1.4,4.998 2.359,7.516 1.399,2.519 2.798,2.999 4.677,5.517 5.157,6.996 0.48,27.503 -2.798,35.538 -0.48,1.48 -0.96,2.999 -1.88,3.478 M 52.288,6.396 c -3.278,1.52 -7.955,7.076 -9.354,10.594 -1.879,3.518 -6.076,3.997 -7.515,4.997 m 100.019,222.585 c -1.839,0.52 -2.319,3.038 -3.278,4.557 m -1.839,-7.995 c -3.278,0 -7.036,1.519 -7.995,4.957 m -11.673,-25.505 c -1.879,1 -4.237,1 -6.156,2.959 m 168.378,-16.55 c -2.319,0.52 -5.597,1.519 -6.077,3.997 m 2.799,-9.514 c -1.92,0 -3.838,1.04 -5.277,2.558 m 38.137,30.542 c -1.88,2.039 -3.758,4.037 -3.758,6.556 m -3.278,-9.594 c -1.839,1.559 -4.637,2.558 -5.117,5.596 m 21.986,-3.997 c -0.919,1.519 -1.358,2.518 -1.838,3.997 M 181.17,151.828 c -1.399,0.52 -4.717,4.038 -6.116,5.037 2.358,2.518 0.96,10.554 -2.838,11.553 0.48,2.039 -0.48,2.518 0.48,4.517 m -52.169,-7.595 c 0.92,-4.477 -5.197,-3.998 -7.076,-6.516 1.44,-1.48 3.318,-3.478 1.88,-5.477 -1.88,0.48 -3.759,0 -5.158,-1.519 1.4,-1.999 2.359,-4.997 0.48,-7.036 -1.919,1.52 -3.798,1.04 -6.156,0.52 M 11.473,32.94 c 0.44,7.076 -3.358,11.593 -8.595,9.075"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1070" />
+ <path
+ d="m 9.514,39.976 c 0.96,-1 2.359,-6.476 1.44,-7.955 -0.96,-1.52 -4.718,-1.52 -6.637,-1 -2.358,1 -3.318,2.998 -2.838,8.475 0,1.999 0.48,2.998 0.48,3.958 l 1.439,-0.96 c 2.359,0 4.717,0 6.116,-2.518 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1072" />
+ <path
+ d="m 55.566,32.54 c -2.798,-1.479 -4.197,-5.996 -7.035,-7.995 -2.799,-1.999 -2.799,0.52 -4.718,3.518"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1074" />
+ <path
+ d="M 52.848,29.102 C 49.09,38.137 42.454,27.104 45.772,25.584 m 11.233,0.96 C 55.606,22.067 50.01,18.549 46.692,19.548 m -33.98,39.136 c 3.318,-1.998 4.278,0.96 6.636,2.439 3.318,1.959 6.157,-0.48 8.955,0.52"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1076" />
+ <path
+ clip-path="url(#a)"
+ d="m 65,104.337 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.969,73.755 47.131,72.756 44.333,69.238 41.975,67.239 35.379,66.24 33.5,66.24 23.626,66.24 16.59,65.72 8.595,57.685 6.715,55.207 5.757,52.168 4.837,48.69 3.397,44.653 2,45.652 1.52,39.656 1.04,33.14 2,31.621 6.237,30.621 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.995,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.88,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.551 -1.4,6.517 -2.319,17.03 -1.879,23.546 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.36,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.839,25.544 -0.959,3.518 0,4.518 -2.358,8.035 -1.879,2.519 -9.874,3.998 -13.152,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.037 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.517 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.999 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.518 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.92,1.48 -0.92,2.479 -0.479,-0.48 -0.958,-0.48 -1.438,-0.48 -0.44,0.48 -0.44,1 -0.92,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.036,5.476 -7.036,5.476 0,0 -3.278,-2.998 -6.116,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1078" />
+ <path
+ d="m 308.533,99.18 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 v 0.52 c 0,0 0,0 0,0 v 1.519"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1080" />
+ <path
+ d="m 95.102,24.905 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.551 0,3.038 0,5.517 0.48,8.555 0.48,3.518 0,7.036 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.92,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.196,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.076,-1.519 -1.88,1.52 -0.92,3.998 -0.44,6.036 -1.44,0 -2.839,-0.52 -3.798,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.514,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.96,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1082" />
+ <path
+ d="m 81.91,41.055 c -1.399,4.038 -3.278,8.035 -5.596,11.033 -1.88,2.519 -4.238,5.037 -5.157,7.516 -0.48,1.519 0,3.038 -0.48,4.517 -0.44,1.52 -2.318,2.998 -2.798,4.517 -0.48,1 -0.48,2.519 -0.48,3.518 -0.44,1.48 -1.879,2.519 -1.879,3.998 0,1.519 1.44,2.998 1.44,4.517 0.44,1.52 0.44,2.998 0.44,4.517 0,3.518 -0.92,6.996 -0.44,10.034 0,2 0.919,3.478 0.919,5.517 0,1.999 -0.92,3.478 -0.48,5.477 0.48,1.519 0.96,2.038 1.4,3.517 0.959,1.52 0,3.518 0.479,5.037 3.278,-0.999 2.798,2.479 3.278,4.478 0.96,-2 3.758,-2.479 5.637,-2 -0.96,-0.479 -3.758,-0.998 -4.678,-1.478 -1.878,-1.52 0,-6.037 1.4,-7.516 -1.4,0 -4.238,-0.52 -4.678,-2.038 -0.959,-2 3.278,-4.478 3.718,-5.997 -1.879,-0.52 -3.278,-1 -3.718,-2.998 -1.439,-3.518 1.4,-5.037 1.84,-8.035 0,-1.999 -1.4,-1.48 -2.32,-3.518 -0.959,-1.999 0,-4.477 1.88,-5.996 -2.359,-3.518 -2.839,-5.517 -0.48,-9.035 0.92,-1.479 0.92,-0.48 0.92,-1.999 0.479,-1.998 -1.4,-3.517 0.959,-5.516 0.92,-1 1.879,-0.48 2.318,-1.999 0.48,-1 0,-3.998 0.96,-5.517 0.48,-1.998 0.92,-4.517 1.879,-6.995 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1084" />
+ <path
+ d="m 95.142,24.945 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.55 0,3.04 0,5.518 0.48,8.556 0.48,3.518 0,7.035 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.919,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.197,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.077,-1.519 -1.878,1.52 -0.919,3.998 -0.44,6.036 -1.438,0 -2.838,-0.52 -3.797,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.515,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.959,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1086" />
+ <path
+ d="m 103.058,54.087 c -0.48,2.998 0,5.997 0,9.035 v 9.994 c 0.44,6.556 1.399,13.551 3.278,19.588 0.48,1 0.959,1.999 1.399,3.478 0,1.519 0,1 -0.44,2.518 -0.48,1.999 -0.96,2.998 -0.96,5.037 0.48,1.999 0.96,2.998 0.96,4.477 -0.48,0.52 -1.44,1.52 -1.44,2.519 -0.439,1 0,2.518 -0.439,2.998 -0.48,1 -1.919,1 -2.838,2.039 -0.48,1.479 0,2.998 -0.96,4.477 -1.399,-1 -2.798,0.52 -3.757,1 -0.92,-1 -1.88,-1.48 -2.839,-1 0.96,-1 3.798,-2.478 4.718,-3.478 0.959,-2.039 0,-4.517 -0.92,-7.036 2.359,0 3.278,-2.518 3.278,-4.996 0,-2.04 -0.92,-2.04 -1.879,-3.518 -0.96,-2.519 1.4,-4.038 1.88,-6.516 0.959,-4.038 -0.92,-5.517 -2.84,-8.036 4.238,-4.517 1.92,-8.035 0.48,-12.512 -0.919,-3.038 0.96,-5.517 0.48,-9.034 0,-2.999 1.4,-6.037 1.4,-9.035 0.48,-1.999 0.959,-4.997 0.48,-7.036 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1088" />
+ <path
+ d="m 45.253,24.545 c -1.88,3.478 2.838,10.914 6.116,6.956 2.318,-2.479 -3.758,-9.954 -5.637,-6.956 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1090" />
+ <path
+ d="m 45.692,26.944 c 0,-0.52 0.44,-1 0.92,-1 0.52,0 0.92,0.48 0.92,1 0,0.56 -0.4,1 -0.92,1 -0.48,0 -0.92,-0.44 -0.92,-1 z"
+ fill="#ffffff"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1092" />
+ <path
+ d="m 2.878,39.016 c 0.96,0 2.399,0.48 3.358,0.48 0.96,0 1.44,-1.479 2.399,-1.999"
+ fill="none"
+ stroke="#ffffff"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1094" />
+ <path
+ d="m 80.111,31.46 c -1.439,-0.519 -3.358,0 -3.837,2.08 1.919,0.48 3.837,-1.04 5.277,0.48 -0.96,2.078 -2.879,3.078 -4.798,3.078 M 96.981,26.064 c -2.798,-1.519 -7.036,3.038 -1.879,3.518 1.88,0.52 3.278,-1.519 4.238,1 0.44,1.998 -3.278,5.036 -4.238,6.516 M 47.171,20.987 c -0.48,-3.438 5.677,-4.437 2.399,1.96 M 26.944,63.082 c 0,-1 0.96,-3.478 -0.48,-3.478 -1.919,-0.52 -2.878,2.478 -2.399,3.478 m 82.271,86.348 c 0,-2.04 0.48,-4.558 0.959,-6.637 2.319,0.52 2.319,4.118 1.879,6.636 m 71.516,4.917 c -3.717,-6.915 -6.556,0.48 -2.798,2.439 m 83.709,-12.952 c 0.92,-0.48 1.84,-1 2.719,-1.999 m 7.995,67.159 c -0.44,-4.037 -6.556,-4.557 -3.718,0 m 33.86,28.143 c -0.96,-1.04 -1.92,-1.599 -2.879,-1.599 m -5.116,-1.399 c -2.359,-6.116 -6.157,1.56 -2.359,2.039"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1096" />
+ <path
+ d="m 267.638,200.039 c -1.4,1.999 1.399,4.997 0.48,5.996 -1.88,1.999 -3.798,-1 -3.798,-2.478 m -155.146,16.07 c 0,1.479 0.44,2.478 0.44,3.918 -1.4,-0.48 -2.319,-0.96 -3.278,-2.439 m 1.838,4.917 c 0.52,1.52 1,2.518 2,3.518 m 18.868,10.514 c 2.318,6.036 -2.359,2.518 -4.238,-0.52"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1098" />
+ <path
+ clip-path="url(#a)"
+ d="m 135.078,244.092 c -0.44,1.999 0.96,2.519 1.4,3.998 -2.32,0.48 -3.718,-1 -5.597,-1.48"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1100" />
+ <path
+ d="m 121.926,242.573 c 0.48,2.039 1.879,3.038 3.278,3.518"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1102" />
+ </g>
+ </g>
+ <g
+ id="layer2"
+ inkscape:label="Layer 2"
+ clip-path="none"
+ inkscape:groupmode="layer"
+ transform="matrix(0.5,0,0,0.5,0,150)">
+ <rect
+ style="opacity:0.8;fill:#ffffff;stroke-width:2.06559;stop-color:#000000"
+ id="rect1552"
+ width="100"
+ height="32"
+ x="0"
+ y="-300" />
+ <g
+ aria-label="BSD"
+ id="text378"
+ style="font-size:32.4222px;line-height:1.25;font-family:'Arial Black';-inkscape-font-specification:'Arial Black, ';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#a40000;stroke-width:1.51979">
+ <path
+ d="m 14.965658,-295.60422 h 13.424817 q 3.356204,0 5.145124,1.66227 1.804752,1.66227 1.804752,4.1161 0,2.05805 -1.282324,3.53035 -0.854882,0.98153 -2.501322,1.55145 2.501322,0.60158 3.672828,2.07388 1.187336,1.45647 1.187336,3.67283 0,1.80475 -0.839051,3.24538 -0.839051,1.44064 -2.295517,2.27969 -0.902376,0.52243 -2.722958,0.7599 -2.422167,0.31662 -3.213724,0.31662 H 14.965658 Z m 7.234836,9.10291 h 3.118737 q 1.678103,0 2.32718,-0.56992 0.664908,-0.58575 0.664908,-1.6781 0,-1.0132 -0.664908,-1.58312 -0.649077,-0.56992 -2.279686,-0.56992 h -3.166231 z m 0,9.11875 h 3.656997 q 1.852244,0 2.61214,-0.64908 0.759895,-0.66491 0.759895,-1.77309 0,-1.02903 -0.759895,-1.64644 -0.744064,-0.63325 -2.627972,-0.63325 h -3.641165 z"
+ id="path435" />
+ <path
+ d="m 38.918191,-280.07386 6.823226,-0.42744 q 0.221636,1.66227 0.902376,2.53298 1.10818,1.40898 3.16623,1.40898 1.535622,0 2.358842,-0.71241 0.839051,-0.72823 0.839051,-1.6781 0,-0.90237 -0.791558,-1.61478 -0.791557,-0.7124 -3.672827,-1.34564 -4.717683,-1.06069 -6.72824,-2.81795 -2.026387,-1.75726 -2.026387,-4.48022 0,-1.78892 1.029025,-3.37203 1.044856,-1.59895 3.118737,-2.50132 Q 46.026378,-296 49.651712,-296 q 4.448553,0 6.775733,1.66227 2.34301,1.64644 2.786282,5.25594 l -6.759902,0.39578 q -0.269129,-1.56728 -1.139842,-2.27968 -0.854883,-0.71241 -2.374673,-0.71241 -1.250661,0 -1.883907,0.53826 -0.633246,0.52243 -0.633246,1.28233 0,0.55409 0.522428,0.99736 0.506596,0.4591 2.406335,0.85488 4.701852,1.0132 6.728239,2.05805 2.042219,1.02903 2.960426,2.56465 0.934038,1.53562 0.934038,3.43536 0,2.23219 -1.23483,4.1161 -1.23483,1.88391 -3.451191,2.86544 -2.216362,0.9657 -5.588397,0.9657 -5.920851,0 -8.200537,-2.27969 -2.279686,-2.27968 -2.580477,-5.7942 z"
+ id="path437" />
+ <path
+ d="M 63.678115,-295.60422 H 74.33248 q 3.150399,0 5.0818,0.85488 1.947231,0.85488 3.213723,2.45383 1.266493,1.59895 1.836414,3.72032 0.569922,2.12138 0.569922,4.49605 0,3.72032 -0.854883,5.77837 -0.839051,2.04222 -2.34301,3.43536 -1.50396,1.37731 -3.229555,1.83641 -2.358842,0.63325 -4.274411,0.63325 H 63.678115 Z m 7.171511,5.25594 v 12.68075 h 1.757258 q 2.248024,0 3.197893,-0.49076 0.949869,-0.5066 1.488128,-1.74143 0.538259,-1.25066 0.538259,-4.03694 0,-3.68866 -1.203167,-5.05014 -1.203168,-1.36148 -3.98945,-1.36148 z"
+ id="path439" />
+ </g>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="Layer 3" />
+</svg>
diff --git a/share/extensions/other/clipart/licenses/cc-by-nc-sa.svg b/share/extensions/other/clipart/licenses/cc-by-nc-sa.svg
new file mode 100644
index 0000000..2f20ee7
--- /dev/null
+++ b/share/extensions/other/clipart/licenses/cc-by-nc-sa.svg
@@ -0,0 +1,346 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="50"
+ height="16"
+ viewBox="0 0 50 16"
+ version="1.1"
+ id="svg5"
+ sodipodi:docname="cc-by-sa-nc.svg"
+ inkscape:version="1.2-alpha1 (8b0d57f509, 2022-03-02, custom)"
+ inkscape:export-filename="/home/doctormo/Projects/inkscape/extensions/main/other/clipart/licenses/cc-by-sa.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#999999"
+ borderopacity="1"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="2.9434"
+ inkscape:cx="-1.5288442"
+ inkscape:cy="27.349324"
+ inkscape:window-width="1472"
+ inkscape:window-height="807"
+ inkscape:window-x="64"
+ inkscape:window-y="20"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer2" />
+ <defs
+ id="defs2">
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect2486"
+ is_visible="true"
+ lpeversion="1"
+ nodesatellites_param=""
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false"
+ satellites_param="" />
+ <color-profile
+ name="AL1706"
+ xlink:href="../../../../../.local/share/icc/edid-a9cf44b399fa09c3fc2589cbaadd3747.icc"
+ id="color-profile1067" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="a">
+ <path
+ d="M 0.24,1.04 H 322.045 V 255.205 H 0.24 Z"
+ id="path1048" />
+ </clipPath>
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect2486-3"
+ is_visible="true"
+ lpeversion="1"
+ nodesatellites_param=""
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false"
+ satellites_param="" />
+ </defs>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-51.633091,-21.31349)"
+ sodipodi:insensitive="true"
+ style="display:none">
+ <g
+ inkscape:label="dog.svg"
+ transform="matrix(0.24767307,0,0,0.24767307,51.414234,28.015162)"
+ id="g1104">
+ <path
+ d="m 308.493,99.14 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1058" />
+ <path
+ clip-path="url(#a)"
+ d="m 64.96,104.297 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.929,73.715 47.091,72.716 44.293,69.198 41.935,67.2 35.34,66.2 33.46,66.2 23.586,66.2 16.55,65.68 8.555,57.645 6.676,55.167 5.717,52.128 4.797,48.651 3.358,44.613 1.959,45.612 1.479,39.616 0.999,33.1 1.959,31.581 6.196,30.581 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.996,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.879,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.552 -1.4,6.516 -2.319,17.03 -1.879,23.545 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.359,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.838,25.544 -0.96,3.518 0,4.518 -2.36,8.035 -1.878,2.519 -9.873,3.998 -13.151,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.036 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.518 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.998 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.519 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.919,1.48 -0.919,2.479 -0.48,-0.48 -0.96,-0.48 -1.44,-0.48 -0.439,0.48 -0.439,1 -0.919,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.035,5.476 -7.035,5.476 0,0 -3.279,-2.998 -6.117,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1060" />
+ <path
+ d="m 147.31,59.604 c 16.95,3.038 32.461,6.556 49.85,5.557 21.627,-1.52 42.775,-5.037 64.401,0 -8.434,-2 -18.788,-2 -21.626,8.554 0.48,-3.038 -0.92,-6.036 -3.758,-7.035 -4.198,-2.04 -5.637,1.998 -9.394,2.998 -5.637,1.519 -7.036,-2.519 -12.673,4.517 -3.318,-8.555 -5.197,-1.999 -10.833,-1.48 -2.838,0 -3.758,-2.518 -6.116,-3.037 -4.678,-1 -6.557,3.518 -10.794,3.518 -1.44,0 -1.44,-2.999 -3.318,-2.999 -1.4,-0.52 -2.798,0.48 -4.677,0 -2.359,0 -2.838,-2.038 -5.637,-1.519 -3.797,0.52 -5.676,6.037 -9.434,6.516 -0.92,-6.516 0,-7.515 -5.157,-10.553 z M 47.531,15.39 C 48.011,3.959 77.633,1.96 82.79,7.956 80.471,5.957 74.835,6.437 73.875,9.955 c -2.838,-2.998 -5.636,-1.999 -7.995,0 -2.358,-1.999 -4.677,-0.52 -7.036,-1 z m -32.86,15.032 c 4.238,-2.479 9.394,-2.479 13.632,-3.478 4.717,-1 8.475,-3.478 12.672,-4.997 -2.318,2.518 -5.636,5.996 -9.394,7.995 -5.637,2.958 -10.794,-0.52 -16.43,1.999 z m 105.776,126.883 c 6.596,9.554 10.873,20.067 15.55,30.621 2.839,5.996 5.677,10.993 5.197,18.03 0,8.034 -3.278,16.03 -4.237,23.545 0.96,-3.478 4.237,-12.513 8.955,-11.513 -0.96,-1.52 -2.359,-3.998 -2.359,-5.996 0,-3.039 3.278,-4.518 3.278,-7.036 0,-1.999 -3.278,-5.517 -3.758,-8.035 0,-2.479 0.48,-4.997 0.96,-6.996 -5.197,-1.999 -6.117,-7.516 -3.798,-12.553 -4.237,-0.999 -7.515,-2.998 -9.394,-7.515 -0.96,-1.999 0,-3.998 -1.44,-5.517 -1.399,-2.518 -3.757,-2.998 -5.156,-5.516 z M 264.84,144.353 c 7.995,10.553 19.308,17.549 26.823,28.582 3.758,4.997 7.995,11.513 10.354,17.55 1.4,2.478 3.278,5.996 3.278,8.994 0.48,3.518 -1.879,7.036 -1.4,10.514 1.88,-2 3.759,-6.476 3.759,-8.995 0.44,-3.518 -2.359,-3.518 -3.318,-7.515 -0.92,-3.518 0.959,-5.517 -0.44,-8.035 -0.48,-1.48 -2.838,-2.479 -3.758,-3.998 0,-1 -0.48,-3.518 -0.96,-3.998 -1.398,-2.518 -5.636,-2.518 -7.035,-5.516 -1.879,-5.517 1.879,-5.517 -3.318,-8.515 -4.677,-2.998 -14.551,-8.035 -15.99,-14.551 z m 10.353,30.541 c -0.44,2.518 -2.358,6.556 -1.399,9.554 0.48,1 2.359,0 2.359,0.52 0.48,1 0.92,2.518 1.399,3.518 1.439,4.517 -0.92,13.072 -6.596,12.072 2.358,-0.52 4.717,0.48 5.676,2.479 0,-3.998 1.4,-7.036 4.678,-8.515 -1.88,-3.038 -1.88,-6.036 -2.32,-9.074 -0.479,-3.998 -0.959,-6.516 -1.918,-10.034 -0.44,-3.518 0.48,-4.518 -1.879,-7.036 -1.879,-2.039 -3.758,-1 -6.596,-2.039 1.92,2.519 6.156,3.518 5.677,7.076 z m -149.469,19.068 c -3.798,4.997 -1.919,11.034 -2.359,17.03 0,1.999 -0.48,6.036 -1.879,7.516 -1.918,1.998 -4.237,1.519 -6.156,2.998 2.838,-2.479 7.076,-2.479 10.394,-1.48 -1.44,-4.517 -3.318,-9.034 2.318,-10.033 -2.318,-3.518 -1.399,-4.997 -1.399,-8.515 -0.48,-2.998 -1.879,-6.996 -0.92,-10.034 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1062" />
+ <path
+ d="m 117.649,122.206 c 0.96,-2.998 -0.92,-6.516 -0.44,-9.514 0.44,-3.998 1.879,-5.517 4.197,-8.515 -6.076,-2.519 -4.677,-6.036 -4.197,-11.553 0.44,-4.997 -2.359,-5.517 -4.717,-10.034 -2.838,-6.516 -2.838,-17.03 -3.278,-24.065 0,-7.996 -2.838,-14.032 -8.955,-19.029 -2.798,-2.518 -7.035,-7.036 -10.793,-7.036 -5.677,-0.52 -9.435,6.037 -11.313,11.034 -1.4,4.997 -4.238,17.549 -3.278,23.066 l 9.874,48.13 1.878,1.52 c 4.238,3.477 1.88,5.516 -0.48,7.515 0.48,1 0.96,1.48 1.88,1.999 h 1.879 c 1.439,0 2.838,0 3.757,0.52 0.48,0 1.44,0.48 2.359,0.48 0,3.517 -2.359,7.035 -1.88,10.513 2.84,-0.48 5.638,-1 7.077,-3.998 -0.96,2.998 -1.44,7.036 -1.44,9.514 1.44,-1.998 2.36,-4.996 2.839,-5.996 3.278,-6.036 13.632,-8.515 15.03,-14.551 z m 3.318,47.771 c 2.798,5.996 3.717,13.032 6.076,19.028 2.798,6.037 4.197,10.554 4.197,17.55 0.48,5.037 -0.48,13.072 -3.757,17.07 -3.238,3.997 -8.875,6.036 -12.633,9.514 6.117,-5.997 13.592,1 17.79,-6.996 3.757,-7.036 4.197,-14.551 4.197,-22.067 0,-8.554 -4.677,-10.553 -7.475,-17.549 -2.799,-6.036 -4.678,-14.551 -9.834,-18.589 z m 46.931,20.388 c 1.4,4.037 4.198,18.069 -2.358,16.55 0,3.517 0.92,6.516 -0.48,10.034 -1.4,-2 -2.838,-6.037 -5.157,-2.519 1.879,1.999 0,1.999 0,3.518 0.44,1.999 0.44,3.997 0.92,5.996 -6.117,1 -7.516,6.516 -10.794,11.034 -3.798,4.517 -8.954,7.515 -9.434,14.51 1.439,-4.996 -0.48,-11.512 2.838,-15.51 0,0.48 2.798,0 3.758,-1 1.879,-1.518 1.399,-3.997 2.358,-6.036 2.359,-4.997 2.799,-2.478 6.117,-5.996 3.278,-3.518 0.92,-7.036 0,-11.513 4.237,2.479 3.757,-4.037 2.798,-6.516 4.717,0 6.596,-1 6.116,-5.517 -0.48,-2.518 -2.358,-8.514 -3.278,-10.513 2.799,1.999 5.637,0.48 7.516,-1.04 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1064" />
+ <path
+ d="m 166.06,187.846 c -0.48,-1.959 -1.4,-5.477 -0.48,-7.435 0.96,-2.519 3.318,-2.999 3.757,-4.997 0.96,-3.478 -3.278,-6.476 1.88,-8.475 -2.32,0 -4.678,1.999 -6.557,-1 1.4,5.997 -4.717,8.995 -1.879,14.472 z m 11.752,-26.544 c -0.96,4.997 -3.318,12.992 3.278,14.991 3.318,1 11.753,-9.474 13.192,-2.998 2.359,-3.998 5.157,-3.478 8.915,-4.477 1.439,-0.52 1.879,-2.999 3.798,-2.519 1.878,0.52 2.798,3.518 2.798,4.997 0.96,-1.999 3.318,-7.515 5.636,-8.515 5.197,-1.479 4.238,3.038 5.677,6.037 1.4,-2 1.879,-5.517 4.237,-5.517 2.799,-0.52 4.198,2.998 4.678,4.997 1.878,-1.999 1.878,-8.515 4.717,-8.515 2.358,-0.48 3.757,2.998 3.278,5.037 2.838,-3.038 -0.48,-9.514 3.318,-11.513 0.92,1.48 1.399,3.478 1.399,4.477 1.399,-4.997 0.92,-7.475 6.596,-6.995 4.677,0 6.116,0.999 7.036,5.996 5.636,-4.997 6.596,4.997 6.596,8.515 3.757,-4.517 5.156,-8.995 2.358,-13.992 -2.838,-4.517 -4.717,-9.514 -6.116,-15.03 -1.4,1.998 -3.758,7.995 -6.116,7.995 -3.318,0 -4.238,-7.476 -5.197,-9.515 -1.4,2.04 -3.278,10.034 -5.637,10.514 -4.237,1.519 -6.596,-4.477 -7.995,-7.476 -1.879,2.999 -1.4,9.475 -4.717,11.993 -4.677,3.998 -4.198,-1.519 -8.435,-2.998 -1.879,7.515 -2.359,10.993 -9.914,12.512 -1.879,0 -1.879,0 -3.758,0.48 -1.879,0.52 -3.757,1.999 -5.636,2.519 -9.395,3.997 -19.269,1.479 -21.627,-9.515 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1066" />
+ <path
+ d="m 263.84,161.782 c 4.238,-4.477 13.192,3.518 16.03,6.516 4.238,4.038 5.677,8.555 5.197,14.031 0,5.517 -0.48,14.552 -3.318,19.549 -0.92,1.998 -3.757,5.037 -6.116,6.516 -2.359,1.519 -6.156,1.519 -7.076,3.997 6.117,-1.479 14.631,-1 16.99,-7.995 2.359,-7.515 2.359,-16.03 2.838,-23.546 0.44,-8.035 -3.797,-11.513 -9.914,-16.03 -2.838,-2.518 -10.873,-12.552 -13.711,-15.03 -2.799,-3.039 -0.44,1.998 -5.197,1.478 z m 48.93,57.645 c 0.92,5.517 5.157,13.552 1.88,18.549 -1.88,3.038 -15.112,7.515 -13.193,0 5.157,1 5.637,-3.998 7.516,-7.516 2.838,-4.997 2.838,-3.518 1.919,-9.034 -0.96,-8.515 3.757,-17.03 2.798,-25.585 z M 292.583,79.112 c 3.757,7.036 10.353,8.555 10.793,18.07 0.96,7.035 -0.44,15.07 1.879,22.066 1.4,6.036 4.717,11.073 7.036,16.59 0.96,1.479 4.237,5.996 4.237,7.515 0.44,2.998 -2.358,4.517 -1.879,9.035 -6.116,-0.52 -1.399,5.516 -0.48,8.514 -2.358,-2.478 -7.035,-4.996 -7.955,-8.514 7.956,-2.519 2.799,-11.034 -1.439,-14.032 5.197,-9.034 -3.278,-12.073 -7.955,-17.59 3.758,-4.516 1.879,-8.034 -1.879,-11.552 5.157,-5.997 4.238,-26.584 -2.358,-31.621 z M 39.536,63.601 c 3.318,1.52 5.197,1.52 7.555,5.037 1.88,2.479 2.359,5.477 4.238,7.996 1.399,1.998 3.278,3.997 4.717,6.476 1.4,1.519 4.677,5.996 6.596,7.995 0.92,-5.997 -2.838,-9.474 -2.359,-14.991 0.44,-3.998 2.359,-8.475 3.758,-11.993 1.879,-4.997 3.278,-8.515 6.116,-11.993 3.278,-3.517 7.516,-7.995 6.596,-14.031 -1.399,6.516 -7.075,15.51 -14.59,12.512 -2.839,5.997 -4.238,7.516 -10.354,7.516 2.798,2.478 5.636,6.996 4.237,11.513 -1.879,-1.999 -5.197,-4.517 -7.555,-5.037 -3.278,-0.48 -5.637,1.519 -8.955,-1.999 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1068" />
+ <path
+ d="m 111.053,226.023 c -1.84,0.52 -3.278,2.998 -3.278,3.998 m 153.267,-88.747 c 1.439,7.556 13.672,16.07 17.909,22.067 3.318,4.517 10.833,9.035 12.233,15.03 M 121.446,164.94 c 2.839,4.517 5.197,10.514 7.076,15.03 0.92,2.52 1.4,4.998 2.359,7.516 1.399,2.519 2.798,2.999 4.677,5.517 5.157,6.996 0.48,27.503 -2.798,35.538 -0.48,1.48 -0.96,2.999 -1.88,3.478 M 52.288,6.396 c -3.278,1.52 -7.955,7.076 -9.354,10.594 -1.879,3.518 -6.076,3.997 -7.515,4.997 m 100.019,222.585 c -1.839,0.52 -2.319,3.038 -3.278,4.557 m -1.839,-7.995 c -3.278,0 -7.036,1.519 -7.995,4.957 m -11.673,-25.505 c -1.879,1 -4.237,1 -6.156,2.959 m 168.378,-16.55 c -2.319,0.52 -5.597,1.519 -6.077,3.997 m 2.799,-9.514 c -1.92,0 -3.838,1.04 -5.277,2.558 m 38.137,30.542 c -1.88,2.039 -3.758,4.037 -3.758,6.556 m -3.278,-9.594 c -1.839,1.559 -4.637,2.558 -5.117,5.596 m 21.986,-3.997 c -0.919,1.519 -1.358,2.518 -1.838,3.997 M 181.17,151.828 c -1.399,0.52 -4.717,4.038 -6.116,5.037 2.358,2.518 0.96,10.554 -2.838,11.553 0.48,2.039 -0.48,2.518 0.48,4.517 m -52.169,-7.595 c 0.92,-4.477 -5.197,-3.998 -7.076,-6.516 1.44,-1.48 3.318,-3.478 1.88,-5.477 -1.88,0.48 -3.759,0 -5.158,-1.519 1.4,-1.999 2.359,-4.997 0.48,-7.036 -1.919,1.52 -3.798,1.04 -6.156,0.52 M 11.473,32.94 c 0.44,7.076 -3.358,11.593 -8.595,9.075"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1070" />
+ <path
+ d="m 9.514,39.976 c 0.96,-1 2.359,-6.476 1.44,-7.955 -0.96,-1.52 -4.718,-1.52 -6.637,-1 -2.358,1 -3.318,2.998 -2.838,8.475 0,1.999 0.48,2.998 0.48,3.958 l 1.439,-0.96 c 2.359,0 4.717,0 6.116,-2.518 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1072" />
+ <path
+ d="m 55.566,32.54 c -2.798,-1.479 -4.197,-5.996 -7.035,-7.995 -2.799,-1.999 -2.799,0.52 -4.718,3.518"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1074" />
+ <path
+ d="M 52.848,29.102 C 49.09,38.137 42.454,27.104 45.772,25.584 m 11.233,0.96 C 55.606,22.067 50.01,18.549 46.692,19.548 m -33.98,39.136 c 3.318,-1.998 4.278,0.96 6.636,2.439 3.318,1.959 6.157,-0.48 8.955,0.52"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1076" />
+ <path
+ clip-path="url(#a)"
+ d="m 65,104.337 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.969,73.755 47.131,72.756 44.333,69.238 41.975,67.239 35.379,66.24 33.5,66.24 23.626,66.24 16.59,65.72 8.595,57.685 6.715,55.207 5.757,52.168 4.837,48.69 3.397,44.653 2,45.652 1.52,39.656 1.04,33.14 2,31.621 6.237,30.621 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.995,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.88,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.551 -1.4,6.517 -2.319,17.03 -1.879,23.546 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.36,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.839,25.544 -0.959,3.518 0,4.518 -2.358,8.035 -1.879,2.519 -9.874,3.998 -13.152,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.037 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.517 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.999 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.518 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.92,1.48 -0.92,2.479 -0.479,-0.48 -0.958,-0.48 -1.438,-0.48 -0.44,0.48 -0.44,1 -0.92,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.036,5.476 -7.036,5.476 0,0 -3.278,-2.998 -6.116,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1078" />
+ <path
+ d="m 308.533,99.18 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 v 0.52 c 0,0 0,0 0,0 v 1.519"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1080" />
+ <path
+ d="m 95.102,24.905 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.551 0,3.038 0,5.517 0.48,8.555 0.48,3.518 0,7.036 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.92,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.196,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.076,-1.519 -1.88,1.52 -0.92,3.998 -0.44,6.036 -1.44,0 -2.839,-0.52 -3.798,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.514,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.96,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1082" />
+ <path
+ d="m 81.91,41.055 c -1.399,4.038 -3.278,8.035 -5.596,11.033 -1.88,2.519 -4.238,5.037 -5.157,7.516 -0.48,1.519 0,3.038 -0.48,4.517 -0.44,1.52 -2.318,2.998 -2.798,4.517 -0.48,1 -0.48,2.519 -0.48,3.518 -0.44,1.48 -1.879,2.519 -1.879,3.998 0,1.519 1.44,2.998 1.44,4.517 0.44,1.52 0.44,2.998 0.44,4.517 0,3.518 -0.92,6.996 -0.44,10.034 0,2 0.919,3.478 0.919,5.517 0,1.999 -0.92,3.478 -0.48,5.477 0.48,1.519 0.96,2.038 1.4,3.517 0.959,1.52 0,3.518 0.479,5.037 3.278,-0.999 2.798,2.479 3.278,4.478 0.96,-2 3.758,-2.479 5.637,-2 -0.96,-0.479 -3.758,-0.998 -4.678,-1.478 -1.878,-1.52 0,-6.037 1.4,-7.516 -1.4,0 -4.238,-0.52 -4.678,-2.038 -0.959,-2 3.278,-4.478 3.718,-5.997 -1.879,-0.52 -3.278,-1 -3.718,-2.998 -1.439,-3.518 1.4,-5.037 1.84,-8.035 0,-1.999 -1.4,-1.48 -2.32,-3.518 -0.959,-1.999 0,-4.477 1.88,-5.996 -2.359,-3.518 -2.839,-5.517 -0.48,-9.035 0.92,-1.479 0.92,-0.48 0.92,-1.999 0.479,-1.998 -1.4,-3.517 0.959,-5.516 0.92,-1 1.879,-0.48 2.318,-1.999 0.48,-1 0,-3.998 0.96,-5.517 0.48,-1.998 0.92,-4.517 1.879,-6.995 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1084" />
+ <path
+ d="m 95.142,24.945 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.55 0,3.04 0,5.518 0.48,8.556 0.48,3.518 0,7.035 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.919,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.197,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.077,-1.519 -1.878,1.52 -0.919,3.998 -0.44,6.036 -1.438,0 -2.838,-0.52 -3.797,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.515,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.959,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1086" />
+ <path
+ d="m 103.058,54.087 c -0.48,2.998 0,5.997 0,9.035 v 9.994 c 0.44,6.556 1.399,13.551 3.278,19.588 0.48,1 0.959,1.999 1.399,3.478 0,1.519 0,1 -0.44,2.518 -0.48,1.999 -0.96,2.998 -0.96,5.037 0.48,1.999 0.96,2.998 0.96,4.477 -0.48,0.52 -1.44,1.52 -1.44,2.519 -0.439,1 0,2.518 -0.439,2.998 -0.48,1 -1.919,1 -2.838,2.039 -0.48,1.479 0,2.998 -0.96,4.477 -1.399,-1 -2.798,0.52 -3.757,1 -0.92,-1 -1.88,-1.48 -2.839,-1 0.96,-1 3.798,-2.478 4.718,-3.478 0.959,-2.039 0,-4.517 -0.92,-7.036 2.359,0 3.278,-2.518 3.278,-4.996 0,-2.04 -0.92,-2.04 -1.879,-3.518 -0.96,-2.519 1.4,-4.038 1.88,-6.516 0.959,-4.038 -0.92,-5.517 -2.84,-8.036 4.238,-4.517 1.92,-8.035 0.48,-12.512 -0.919,-3.038 0.96,-5.517 0.48,-9.034 0,-2.999 1.4,-6.037 1.4,-9.035 0.48,-1.999 0.959,-4.997 0.48,-7.036 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1088" />
+ <path
+ d="m 45.253,24.545 c -1.88,3.478 2.838,10.914 6.116,6.956 2.318,-2.479 -3.758,-9.954 -5.637,-6.956 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1090" />
+ <path
+ d="m 45.692,26.944 c 0,-0.52 0.44,-1 0.92,-1 0.52,0 0.92,0.48 0.92,1 0,0.56 -0.4,1 -0.92,1 -0.48,0 -0.92,-0.44 -0.92,-1 z"
+ fill="#ffffff"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1092" />
+ <path
+ d="m 2.878,39.016 c 0.96,0 2.399,0.48 3.358,0.48 0.96,0 1.44,-1.479 2.399,-1.999"
+ fill="none"
+ stroke="#ffffff"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1094" />
+ <path
+ d="m 80.111,31.46 c -1.439,-0.519 -3.358,0 -3.837,2.08 1.919,0.48 3.837,-1.04 5.277,0.48 -0.96,2.078 -2.879,3.078 -4.798,3.078 M 96.981,26.064 c -2.798,-1.519 -7.036,3.038 -1.879,3.518 1.88,0.52 3.278,-1.519 4.238,1 0.44,1.998 -3.278,5.036 -4.238,6.516 M 47.171,20.987 c -0.48,-3.438 5.677,-4.437 2.399,1.96 M 26.944,63.082 c 0,-1 0.96,-3.478 -0.48,-3.478 -1.919,-0.52 -2.878,2.478 -2.399,3.478 m 82.271,86.348 c 0,-2.04 0.48,-4.558 0.959,-6.637 2.319,0.52 2.319,4.118 1.879,6.636 m 71.516,4.917 c -3.717,-6.915 -6.556,0.48 -2.798,2.439 m 83.709,-12.952 c 0.92,-0.48 1.84,-1 2.719,-1.999 m 7.995,67.159 c -0.44,-4.037 -6.556,-4.557 -3.718,0 m 33.86,28.143 c -0.96,-1.04 -1.92,-1.599 -2.879,-1.599 m -5.116,-1.399 c -2.359,-6.116 -6.157,1.56 -2.359,2.039"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1096" />
+ <path
+ d="m 267.638,200.039 c -1.4,1.999 1.399,4.997 0.48,5.996 -1.88,1.999 -3.798,-1 -3.798,-2.478 m -155.146,16.07 c 0,1.479 0.44,2.478 0.44,3.918 -1.4,-0.48 -2.319,-0.96 -3.278,-2.439 m 1.838,4.917 c 0.52,1.52 1,2.518 2,3.518 m 18.868,10.514 c 2.318,6.036 -2.359,2.518 -4.238,-0.52"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1098" />
+ <path
+ clip-path="url(#a)"
+ d="m 135.078,244.092 c -0.44,1.999 0.96,2.519 1.4,3.998 -2.32,0.48 -3.718,-1 -5.597,-1.48"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1100" />
+ <path
+ d="m 121.926,242.573 c 0.48,2.039 1.879,3.038 3.278,3.518"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1102" />
+ </g>
+ </g>
+ <g
+ id="layer2"
+ inkscape:label="Layer 2"
+ clip-path="none"
+ inkscape:groupmode="layer"
+ transform="matrix(0.5,0,0,0.5,0,150)">
+ <circle
+ r="8"
+ cy="-284"
+ cx="34"
+ style="fill:#ffc022;stroke:#b88100;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
+ id="path3319-3" />
+ <circle
+ r="8"
+ cy="-284"
+ cx="78"
+ style="fill:#f57900;stroke:#ce5c00;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
+ id="circle1047" />
+ <circle
+ r="8"
+ cy="-284"
+ cx="66"
+ style="fill:#ad7fa8;stroke:#5c3566;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
+ id="path3319" />
+ <circle
+ r="12"
+ cy="-284"
+ cx="50"
+ style="fill:#ffffff;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
+ id="path3331" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="Layer 3" />
+</svg>
diff --git a/share/extensions/other/clipart/licenses/cc-by-nc.svg b/share/extensions/other/clipart/licenses/cc-by-nc.svg
new file mode 100644
index 0000000..80dd1f6
--- /dev/null
+++ b/share/extensions/other/clipart/licenses/cc-by-nc.svg
@@ -0,0 +1,340 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="50"
+ height="16"
+ viewBox="0 0 50 16"
+ version="1.1"
+ id="svg5"
+ sodipodi:docname="cc-by-nc.svg"
+ inkscape:version="1.2-alpha1 (8b0d57f509, 2022-03-02, custom)"
+ inkscape:export-filename="/home/doctormo/Projects/inkscape/extensions/main/other/clipart/licenses/cc-by-sa.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#999999"
+ borderopacity="1"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="2.9434"
+ inkscape:cx="-13.080111"
+ inkscape:cy="27.349324"
+ inkscape:window-width="1472"
+ inkscape:window-height="807"
+ inkscape:window-x="64"
+ inkscape:window-y="20"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer2" />
+ <defs
+ id="defs2">
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect2486"
+ is_visible="true"
+ lpeversion="1"
+ nodesatellites_param=""
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false"
+ satellites_param="" />
+ <color-profile
+ name="AL1706"
+ xlink:href="../../../../../.local/share/icc/edid-a9cf44b399fa09c3fc2589cbaadd3747.icc"
+ id="color-profile1851" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="a">
+ <path
+ d="M 0.24,1.04 H 322.045 V 255.205 H 0.24 Z"
+ id="path1048" />
+ </clipPath>
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect2486-3"
+ is_visible="true"
+ lpeversion="1"
+ nodesatellites_param=""
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false"
+ satellites_param="" />
+ </defs>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-51.633091,-21.31349)"
+ sodipodi:insensitive="true"
+ style="display:none">
+ <g
+ inkscape:label="dog.svg"
+ transform="matrix(0.24767307,0,0,0.24767307,51.414234,28.015162)"
+ id="g1104">
+ <path
+ d="m 308.493,99.14 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1058" />
+ <path
+ clip-path="url(#a)"
+ d="m 64.96,104.297 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.929,73.715 47.091,72.716 44.293,69.198 41.935,67.2 35.34,66.2 33.46,66.2 23.586,66.2 16.55,65.68 8.555,57.645 6.676,55.167 5.717,52.128 4.797,48.651 3.358,44.613 1.959,45.612 1.479,39.616 0.999,33.1 1.959,31.581 6.196,30.581 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.996,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.879,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.552 -1.4,6.516 -2.319,17.03 -1.879,23.545 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.359,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.838,25.544 -0.96,3.518 0,4.518 -2.36,8.035 -1.878,2.519 -9.873,3.998 -13.151,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.036 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.518 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.998 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.519 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.919,1.48 -0.919,2.479 -0.48,-0.48 -0.96,-0.48 -1.44,-0.48 -0.439,0.48 -0.439,1 -0.919,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.035,5.476 -7.035,5.476 0,0 -3.279,-2.998 -6.117,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1060" />
+ <path
+ d="m 147.31,59.604 c 16.95,3.038 32.461,6.556 49.85,5.557 21.627,-1.52 42.775,-5.037 64.401,0 -8.434,-2 -18.788,-2 -21.626,8.554 0.48,-3.038 -0.92,-6.036 -3.758,-7.035 -4.198,-2.04 -5.637,1.998 -9.394,2.998 -5.637,1.519 -7.036,-2.519 -12.673,4.517 -3.318,-8.555 -5.197,-1.999 -10.833,-1.48 -2.838,0 -3.758,-2.518 -6.116,-3.037 -4.678,-1 -6.557,3.518 -10.794,3.518 -1.44,0 -1.44,-2.999 -3.318,-2.999 -1.4,-0.52 -2.798,0.48 -4.677,0 -2.359,0 -2.838,-2.038 -5.637,-1.519 -3.797,0.52 -5.676,6.037 -9.434,6.516 -0.92,-6.516 0,-7.515 -5.157,-10.553 z M 47.531,15.39 C 48.011,3.959 77.633,1.96 82.79,7.956 80.471,5.957 74.835,6.437 73.875,9.955 c -2.838,-2.998 -5.636,-1.999 -7.995,0 -2.358,-1.999 -4.677,-0.52 -7.036,-1 z m -32.86,15.032 c 4.238,-2.479 9.394,-2.479 13.632,-3.478 4.717,-1 8.475,-3.478 12.672,-4.997 -2.318,2.518 -5.636,5.996 -9.394,7.995 -5.637,2.958 -10.794,-0.52 -16.43,1.999 z m 105.776,126.883 c 6.596,9.554 10.873,20.067 15.55,30.621 2.839,5.996 5.677,10.993 5.197,18.03 0,8.034 -3.278,16.03 -4.237,23.545 0.96,-3.478 4.237,-12.513 8.955,-11.513 -0.96,-1.52 -2.359,-3.998 -2.359,-5.996 0,-3.039 3.278,-4.518 3.278,-7.036 0,-1.999 -3.278,-5.517 -3.758,-8.035 0,-2.479 0.48,-4.997 0.96,-6.996 -5.197,-1.999 -6.117,-7.516 -3.798,-12.553 -4.237,-0.999 -7.515,-2.998 -9.394,-7.515 -0.96,-1.999 0,-3.998 -1.44,-5.517 -1.399,-2.518 -3.757,-2.998 -5.156,-5.516 z M 264.84,144.353 c 7.995,10.553 19.308,17.549 26.823,28.582 3.758,4.997 7.995,11.513 10.354,17.55 1.4,2.478 3.278,5.996 3.278,8.994 0.48,3.518 -1.879,7.036 -1.4,10.514 1.88,-2 3.759,-6.476 3.759,-8.995 0.44,-3.518 -2.359,-3.518 -3.318,-7.515 -0.92,-3.518 0.959,-5.517 -0.44,-8.035 -0.48,-1.48 -2.838,-2.479 -3.758,-3.998 0,-1 -0.48,-3.518 -0.96,-3.998 -1.398,-2.518 -5.636,-2.518 -7.035,-5.516 -1.879,-5.517 1.879,-5.517 -3.318,-8.515 -4.677,-2.998 -14.551,-8.035 -15.99,-14.551 z m 10.353,30.541 c -0.44,2.518 -2.358,6.556 -1.399,9.554 0.48,1 2.359,0 2.359,0.52 0.48,1 0.92,2.518 1.399,3.518 1.439,4.517 -0.92,13.072 -6.596,12.072 2.358,-0.52 4.717,0.48 5.676,2.479 0,-3.998 1.4,-7.036 4.678,-8.515 -1.88,-3.038 -1.88,-6.036 -2.32,-9.074 -0.479,-3.998 -0.959,-6.516 -1.918,-10.034 -0.44,-3.518 0.48,-4.518 -1.879,-7.036 -1.879,-2.039 -3.758,-1 -6.596,-2.039 1.92,2.519 6.156,3.518 5.677,7.076 z m -149.469,19.068 c -3.798,4.997 -1.919,11.034 -2.359,17.03 0,1.999 -0.48,6.036 -1.879,7.516 -1.918,1.998 -4.237,1.519 -6.156,2.998 2.838,-2.479 7.076,-2.479 10.394,-1.48 -1.44,-4.517 -3.318,-9.034 2.318,-10.033 -2.318,-3.518 -1.399,-4.997 -1.399,-8.515 -0.48,-2.998 -1.879,-6.996 -0.92,-10.034 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1062" />
+ <path
+ d="m 117.649,122.206 c 0.96,-2.998 -0.92,-6.516 -0.44,-9.514 0.44,-3.998 1.879,-5.517 4.197,-8.515 -6.076,-2.519 -4.677,-6.036 -4.197,-11.553 0.44,-4.997 -2.359,-5.517 -4.717,-10.034 -2.838,-6.516 -2.838,-17.03 -3.278,-24.065 0,-7.996 -2.838,-14.032 -8.955,-19.029 -2.798,-2.518 -7.035,-7.036 -10.793,-7.036 -5.677,-0.52 -9.435,6.037 -11.313,11.034 -1.4,4.997 -4.238,17.549 -3.278,23.066 l 9.874,48.13 1.878,1.52 c 4.238,3.477 1.88,5.516 -0.48,7.515 0.48,1 0.96,1.48 1.88,1.999 h 1.879 c 1.439,0 2.838,0 3.757,0.52 0.48,0 1.44,0.48 2.359,0.48 0,3.517 -2.359,7.035 -1.88,10.513 2.84,-0.48 5.638,-1 7.077,-3.998 -0.96,2.998 -1.44,7.036 -1.44,9.514 1.44,-1.998 2.36,-4.996 2.839,-5.996 3.278,-6.036 13.632,-8.515 15.03,-14.551 z m 3.318,47.771 c 2.798,5.996 3.717,13.032 6.076,19.028 2.798,6.037 4.197,10.554 4.197,17.55 0.48,5.037 -0.48,13.072 -3.757,17.07 -3.238,3.997 -8.875,6.036 -12.633,9.514 6.117,-5.997 13.592,1 17.79,-6.996 3.757,-7.036 4.197,-14.551 4.197,-22.067 0,-8.554 -4.677,-10.553 -7.475,-17.549 -2.799,-6.036 -4.678,-14.551 -9.834,-18.589 z m 46.931,20.388 c 1.4,4.037 4.198,18.069 -2.358,16.55 0,3.517 0.92,6.516 -0.48,10.034 -1.4,-2 -2.838,-6.037 -5.157,-2.519 1.879,1.999 0,1.999 0,3.518 0.44,1.999 0.44,3.997 0.92,5.996 -6.117,1 -7.516,6.516 -10.794,11.034 -3.798,4.517 -8.954,7.515 -9.434,14.51 1.439,-4.996 -0.48,-11.512 2.838,-15.51 0,0.48 2.798,0 3.758,-1 1.879,-1.518 1.399,-3.997 2.358,-6.036 2.359,-4.997 2.799,-2.478 6.117,-5.996 3.278,-3.518 0.92,-7.036 0,-11.513 4.237,2.479 3.757,-4.037 2.798,-6.516 4.717,0 6.596,-1 6.116,-5.517 -0.48,-2.518 -2.358,-8.514 -3.278,-10.513 2.799,1.999 5.637,0.48 7.516,-1.04 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1064" />
+ <path
+ d="m 166.06,187.846 c -0.48,-1.959 -1.4,-5.477 -0.48,-7.435 0.96,-2.519 3.318,-2.999 3.757,-4.997 0.96,-3.478 -3.278,-6.476 1.88,-8.475 -2.32,0 -4.678,1.999 -6.557,-1 1.4,5.997 -4.717,8.995 -1.879,14.472 z m 11.752,-26.544 c -0.96,4.997 -3.318,12.992 3.278,14.991 3.318,1 11.753,-9.474 13.192,-2.998 2.359,-3.998 5.157,-3.478 8.915,-4.477 1.439,-0.52 1.879,-2.999 3.798,-2.519 1.878,0.52 2.798,3.518 2.798,4.997 0.96,-1.999 3.318,-7.515 5.636,-8.515 5.197,-1.479 4.238,3.038 5.677,6.037 1.4,-2 1.879,-5.517 4.237,-5.517 2.799,-0.52 4.198,2.998 4.678,4.997 1.878,-1.999 1.878,-8.515 4.717,-8.515 2.358,-0.48 3.757,2.998 3.278,5.037 2.838,-3.038 -0.48,-9.514 3.318,-11.513 0.92,1.48 1.399,3.478 1.399,4.477 1.399,-4.997 0.92,-7.475 6.596,-6.995 4.677,0 6.116,0.999 7.036,5.996 5.636,-4.997 6.596,4.997 6.596,8.515 3.757,-4.517 5.156,-8.995 2.358,-13.992 -2.838,-4.517 -4.717,-9.514 -6.116,-15.03 -1.4,1.998 -3.758,7.995 -6.116,7.995 -3.318,0 -4.238,-7.476 -5.197,-9.515 -1.4,2.04 -3.278,10.034 -5.637,10.514 -4.237,1.519 -6.596,-4.477 -7.995,-7.476 -1.879,2.999 -1.4,9.475 -4.717,11.993 -4.677,3.998 -4.198,-1.519 -8.435,-2.998 -1.879,7.515 -2.359,10.993 -9.914,12.512 -1.879,0 -1.879,0 -3.758,0.48 -1.879,0.52 -3.757,1.999 -5.636,2.519 -9.395,3.997 -19.269,1.479 -21.627,-9.515 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1066" />
+ <path
+ d="m 263.84,161.782 c 4.238,-4.477 13.192,3.518 16.03,6.516 4.238,4.038 5.677,8.555 5.197,14.031 0,5.517 -0.48,14.552 -3.318,19.549 -0.92,1.998 -3.757,5.037 -6.116,6.516 -2.359,1.519 -6.156,1.519 -7.076,3.997 6.117,-1.479 14.631,-1 16.99,-7.995 2.359,-7.515 2.359,-16.03 2.838,-23.546 0.44,-8.035 -3.797,-11.513 -9.914,-16.03 -2.838,-2.518 -10.873,-12.552 -13.711,-15.03 -2.799,-3.039 -0.44,1.998 -5.197,1.478 z m 48.93,57.645 c 0.92,5.517 5.157,13.552 1.88,18.549 -1.88,3.038 -15.112,7.515 -13.193,0 5.157,1 5.637,-3.998 7.516,-7.516 2.838,-4.997 2.838,-3.518 1.919,-9.034 -0.96,-8.515 3.757,-17.03 2.798,-25.585 z M 292.583,79.112 c 3.757,7.036 10.353,8.555 10.793,18.07 0.96,7.035 -0.44,15.07 1.879,22.066 1.4,6.036 4.717,11.073 7.036,16.59 0.96,1.479 4.237,5.996 4.237,7.515 0.44,2.998 -2.358,4.517 -1.879,9.035 -6.116,-0.52 -1.399,5.516 -0.48,8.514 -2.358,-2.478 -7.035,-4.996 -7.955,-8.514 7.956,-2.519 2.799,-11.034 -1.439,-14.032 5.197,-9.034 -3.278,-12.073 -7.955,-17.59 3.758,-4.516 1.879,-8.034 -1.879,-11.552 5.157,-5.997 4.238,-26.584 -2.358,-31.621 z M 39.536,63.601 c 3.318,1.52 5.197,1.52 7.555,5.037 1.88,2.479 2.359,5.477 4.238,7.996 1.399,1.998 3.278,3.997 4.717,6.476 1.4,1.519 4.677,5.996 6.596,7.995 0.92,-5.997 -2.838,-9.474 -2.359,-14.991 0.44,-3.998 2.359,-8.475 3.758,-11.993 1.879,-4.997 3.278,-8.515 6.116,-11.993 3.278,-3.517 7.516,-7.995 6.596,-14.031 -1.399,6.516 -7.075,15.51 -14.59,12.512 -2.839,5.997 -4.238,7.516 -10.354,7.516 2.798,2.478 5.636,6.996 4.237,11.513 -1.879,-1.999 -5.197,-4.517 -7.555,-5.037 -3.278,-0.48 -5.637,1.519 -8.955,-1.999 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1068" />
+ <path
+ d="m 111.053,226.023 c -1.84,0.52 -3.278,2.998 -3.278,3.998 m 153.267,-88.747 c 1.439,7.556 13.672,16.07 17.909,22.067 3.318,4.517 10.833,9.035 12.233,15.03 M 121.446,164.94 c 2.839,4.517 5.197,10.514 7.076,15.03 0.92,2.52 1.4,4.998 2.359,7.516 1.399,2.519 2.798,2.999 4.677,5.517 5.157,6.996 0.48,27.503 -2.798,35.538 -0.48,1.48 -0.96,2.999 -1.88,3.478 M 52.288,6.396 c -3.278,1.52 -7.955,7.076 -9.354,10.594 -1.879,3.518 -6.076,3.997 -7.515,4.997 m 100.019,222.585 c -1.839,0.52 -2.319,3.038 -3.278,4.557 m -1.839,-7.995 c -3.278,0 -7.036,1.519 -7.995,4.957 m -11.673,-25.505 c -1.879,1 -4.237,1 -6.156,2.959 m 168.378,-16.55 c -2.319,0.52 -5.597,1.519 -6.077,3.997 m 2.799,-9.514 c -1.92,0 -3.838,1.04 -5.277,2.558 m 38.137,30.542 c -1.88,2.039 -3.758,4.037 -3.758,6.556 m -3.278,-9.594 c -1.839,1.559 -4.637,2.558 -5.117,5.596 m 21.986,-3.997 c -0.919,1.519 -1.358,2.518 -1.838,3.997 M 181.17,151.828 c -1.399,0.52 -4.717,4.038 -6.116,5.037 2.358,2.518 0.96,10.554 -2.838,11.553 0.48,2.039 -0.48,2.518 0.48,4.517 m -52.169,-7.595 c 0.92,-4.477 -5.197,-3.998 -7.076,-6.516 1.44,-1.48 3.318,-3.478 1.88,-5.477 -1.88,0.48 -3.759,0 -5.158,-1.519 1.4,-1.999 2.359,-4.997 0.48,-7.036 -1.919,1.52 -3.798,1.04 -6.156,0.52 M 11.473,32.94 c 0.44,7.076 -3.358,11.593 -8.595,9.075"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1070" />
+ <path
+ d="m 9.514,39.976 c 0.96,-1 2.359,-6.476 1.44,-7.955 -0.96,-1.52 -4.718,-1.52 -6.637,-1 -2.358,1 -3.318,2.998 -2.838,8.475 0,1.999 0.48,2.998 0.48,3.958 l 1.439,-0.96 c 2.359,0 4.717,0 6.116,-2.518 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1072" />
+ <path
+ d="m 55.566,32.54 c -2.798,-1.479 -4.197,-5.996 -7.035,-7.995 -2.799,-1.999 -2.799,0.52 -4.718,3.518"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1074" />
+ <path
+ d="M 52.848,29.102 C 49.09,38.137 42.454,27.104 45.772,25.584 m 11.233,0.96 C 55.606,22.067 50.01,18.549 46.692,19.548 m -33.98,39.136 c 3.318,-1.998 4.278,0.96 6.636,2.439 3.318,1.959 6.157,-0.48 8.955,0.52"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1076" />
+ <path
+ clip-path="url(#a)"
+ d="m 65,104.337 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.969,73.755 47.131,72.756 44.333,69.238 41.975,67.239 35.379,66.24 33.5,66.24 23.626,66.24 16.59,65.72 8.595,57.685 6.715,55.207 5.757,52.168 4.837,48.69 3.397,44.653 2,45.652 1.52,39.656 1.04,33.14 2,31.621 6.237,30.621 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.995,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.88,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.551 -1.4,6.517 -2.319,17.03 -1.879,23.546 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.36,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.839,25.544 -0.959,3.518 0,4.518 -2.358,8.035 -1.879,2.519 -9.874,3.998 -13.152,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.037 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.517 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.999 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.518 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.92,1.48 -0.92,2.479 -0.479,-0.48 -0.958,-0.48 -1.438,-0.48 -0.44,0.48 -0.44,1 -0.92,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.036,5.476 -7.036,5.476 0,0 -3.278,-2.998 -6.116,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1078" />
+ <path
+ d="m 308.533,99.18 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 v 0.52 c 0,0 0,0 0,0 v 1.519"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1080" />
+ <path
+ d="m 95.102,24.905 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.551 0,3.038 0,5.517 0.48,8.555 0.48,3.518 0,7.036 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.92,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.196,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.076,-1.519 -1.88,1.52 -0.92,3.998 -0.44,6.036 -1.44,0 -2.839,-0.52 -3.798,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.514,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.96,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1082" />
+ <path
+ d="m 81.91,41.055 c -1.399,4.038 -3.278,8.035 -5.596,11.033 -1.88,2.519 -4.238,5.037 -5.157,7.516 -0.48,1.519 0,3.038 -0.48,4.517 -0.44,1.52 -2.318,2.998 -2.798,4.517 -0.48,1 -0.48,2.519 -0.48,3.518 -0.44,1.48 -1.879,2.519 -1.879,3.998 0,1.519 1.44,2.998 1.44,4.517 0.44,1.52 0.44,2.998 0.44,4.517 0,3.518 -0.92,6.996 -0.44,10.034 0,2 0.919,3.478 0.919,5.517 0,1.999 -0.92,3.478 -0.48,5.477 0.48,1.519 0.96,2.038 1.4,3.517 0.959,1.52 0,3.518 0.479,5.037 3.278,-0.999 2.798,2.479 3.278,4.478 0.96,-2 3.758,-2.479 5.637,-2 -0.96,-0.479 -3.758,-0.998 -4.678,-1.478 -1.878,-1.52 0,-6.037 1.4,-7.516 -1.4,0 -4.238,-0.52 -4.678,-2.038 -0.959,-2 3.278,-4.478 3.718,-5.997 -1.879,-0.52 -3.278,-1 -3.718,-2.998 -1.439,-3.518 1.4,-5.037 1.84,-8.035 0,-1.999 -1.4,-1.48 -2.32,-3.518 -0.959,-1.999 0,-4.477 1.88,-5.996 -2.359,-3.518 -2.839,-5.517 -0.48,-9.035 0.92,-1.479 0.92,-0.48 0.92,-1.999 0.479,-1.998 -1.4,-3.517 0.959,-5.516 0.92,-1 1.879,-0.48 2.318,-1.999 0.48,-1 0,-3.998 0.96,-5.517 0.48,-1.998 0.92,-4.517 1.879,-6.995 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1084" />
+ <path
+ d="m 95.142,24.945 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.55 0,3.04 0,5.518 0.48,8.556 0.48,3.518 0,7.035 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.919,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.197,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.077,-1.519 -1.878,1.52 -0.919,3.998 -0.44,6.036 -1.438,0 -2.838,-0.52 -3.797,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.515,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.959,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1086" />
+ <path
+ d="m 103.058,54.087 c -0.48,2.998 0,5.997 0,9.035 v 9.994 c 0.44,6.556 1.399,13.551 3.278,19.588 0.48,1 0.959,1.999 1.399,3.478 0,1.519 0,1 -0.44,2.518 -0.48,1.999 -0.96,2.998 -0.96,5.037 0.48,1.999 0.96,2.998 0.96,4.477 -0.48,0.52 -1.44,1.52 -1.44,2.519 -0.439,1 0,2.518 -0.439,2.998 -0.48,1 -1.919,1 -2.838,2.039 -0.48,1.479 0,2.998 -0.96,4.477 -1.399,-1 -2.798,0.52 -3.757,1 -0.92,-1 -1.88,-1.48 -2.839,-1 0.96,-1 3.798,-2.478 4.718,-3.478 0.959,-2.039 0,-4.517 -0.92,-7.036 2.359,0 3.278,-2.518 3.278,-4.996 0,-2.04 -0.92,-2.04 -1.879,-3.518 -0.96,-2.519 1.4,-4.038 1.88,-6.516 0.959,-4.038 -0.92,-5.517 -2.84,-8.036 4.238,-4.517 1.92,-8.035 0.48,-12.512 -0.919,-3.038 0.96,-5.517 0.48,-9.034 0,-2.999 1.4,-6.037 1.4,-9.035 0.48,-1.999 0.959,-4.997 0.48,-7.036 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1088" />
+ <path
+ d="m 45.253,24.545 c -1.88,3.478 2.838,10.914 6.116,6.956 2.318,-2.479 -3.758,-9.954 -5.637,-6.956 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1090" />
+ <path
+ d="m 45.692,26.944 c 0,-0.52 0.44,-1 0.92,-1 0.52,0 0.92,0.48 0.92,1 0,0.56 -0.4,1 -0.92,1 -0.48,0 -0.92,-0.44 -0.92,-1 z"
+ fill="#ffffff"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1092" />
+ <path
+ d="m 2.878,39.016 c 0.96,0 2.399,0.48 3.358,0.48 0.96,0 1.44,-1.479 2.399,-1.999"
+ fill="none"
+ stroke="#ffffff"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1094" />
+ <path
+ d="m 80.111,31.46 c -1.439,-0.519 -3.358,0 -3.837,2.08 1.919,0.48 3.837,-1.04 5.277,0.48 -0.96,2.078 -2.879,3.078 -4.798,3.078 M 96.981,26.064 c -2.798,-1.519 -7.036,3.038 -1.879,3.518 1.88,0.52 3.278,-1.519 4.238,1 0.44,1.998 -3.278,5.036 -4.238,6.516 M 47.171,20.987 c -0.48,-3.438 5.677,-4.437 2.399,1.96 M 26.944,63.082 c 0,-1 0.96,-3.478 -0.48,-3.478 -1.919,-0.52 -2.878,2.478 -2.399,3.478 m 82.271,86.348 c 0,-2.04 0.48,-4.558 0.959,-6.637 2.319,0.52 2.319,4.118 1.879,6.636 m 71.516,4.917 c -3.717,-6.915 -6.556,0.48 -2.798,2.439 m 83.709,-12.952 c 0.92,-0.48 1.84,-1 2.719,-1.999 m 7.995,67.159 c -0.44,-4.037 -6.556,-4.557 -3.718,0 m 33.86,28.143 c -0.96,-1.04 -1.92,-1.599 -2.879,-1.599 m -5.116,-1.399 c -2.359,-6.116 -6.157,1.56 -2.359,2.039"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1096" />
+ <path
+ d="m 267.638,200.039 c -1.4,1.999 1.399,4.997 0.48,5.996 -1.88,1.999 -3.798,-1 -3.798,-2.478 m -155.146,16.07 c 0,1.479 0.44,2.478 0.44,3.918 -1.4,-0.48 -2.319,-0.96 -3.278,-2.439 m 1.838,4.917 c 0.52,1.52 1,2.518 2,3.518 m 18.868,10.514 c 2.318,6.036 -2.359,2.518 -4.238,-0.52"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1098" />
+ <path
+ clip-path="url(#a)"
+ d="m 135.078,244.092 c -0.44,1.999 0.96,2.519 1.4,3.998 -2.32,0.48 -3.718,-1 -5.597,-1.48"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1100" />
+ <path
+ d="m 121.926,242.573 c 0.48,2.039 1.879,3.038 3.278,3.518"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1102" />
+ </g>
+ </g>
+ <g
+ id="layer2"
+ inkscape:label="Layer 2"
+ clip-path="none"
+ inkscape:groupmode="layer"
+ transform="matrix(0.5,0,0,0.5,0,150)">
+ <circle
+ r="8"
+ cy="-284"
+ cx="34"
+ style="fill:#ffc022;stroke:#b88100;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
+ id="path3319-3" />
+ <circle
+ r="8"
+ cy="-284"
+ cx="66"
+ style="fill:#f57900;stroke:#ce5c00;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
+ id="path3319" />
+ <circle
+ r="12"
+ cy="-284"
+ cx="50"
+ style="fill:#ffffff;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
+ id="path3331" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="Layer 3" />
+</svg>
diff --git a/share/extensions/other/clipart/licenses/cc-by-nd.svg b/share/extensions/other/clipart/licenses/cc-by-nd.svg
new file mode 100644
index 0000000..ec255e6
--- /dev/null
+++ b/share/extensions/other/clipart/licenses/cc-by-nd.svg
@@ -0,0 +1,340 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="50"
+ height="16"
+ viewBox="0 0 50 16"
+ version="1.1"
+ id="svg5"
+ sodipodi:docname="cc-by-nd.svg"
+ inkscape:version="1.2-alpha1 (8b0d57f509, 2022-03-02, custom)"
+ inkscape:export-filename="/home/doctormo/Projects/inkscape/extensions/main/other/clipart/licenses/cc-by-sa.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#999999"
+ borderopacity="1"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="2.9434"
+ inkscape:cx="12.060882"
+ inkscape:cy="27.009581"
+ inkscape:window-width="1472"
+ inkscape:window-height="807"
+ inkscape:window-x="64"
+ inkscape:window-y="20"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer2" />
+ <defs
+ id="defs2">
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect2486"
+ is_visible="true"
+ lpeversion="1"
+ nodesatellites_param=""
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false"
+ satellites_param="" />
+ <color-profile
+ name="AL1706"
+ xlink:href="../../../../../.local/share/icc/edid-a9cf44b399fa09c3fc2589cbaadd3747.icc"
+ id="color-profile800" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="a">
+ <path
+ d="M 0.24,1.04 H 322.045 V 255.205 H 0.24 Z"
+ id="path1048" />
+ </clipPath>
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect2486-3"
+ is_visible="true"
+ lpeversion="1"
+ nodesatellites_param=""
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false"
+ satellites_param="" />
+ </defs>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-51.633091,-21.31349)"
+ sodipodi:insensitive="true"
+ style="display:none">
+ <g
+ inkscape:label="dog.svg"
+ transform="matrix(0.24767307,0,0,0.24767307,51.414234,28.015162)"
+ id="g1104">
+ <path
+ d="m 308.493,99.14 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1058" />
+ <path
+ clip-path="url(#a)"
+ d="m 64.96,104.297 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.929,73.715 47.091,72.716 44.293,69.198 41.935,67.2 35.34,66.2 33.46,66.2 23.586,66.2 16.55,65.68 8.555,57.645 6.676,55.167 5.717,52.128 4.797,48.651 3.358,44.613 1.959,45.612 1.479,39.616 0.999,33.1 1.959,31.581 6.196,30.581 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.996,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.879,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.552 -1.4,6.516 -2.319,17.03 -1.879,23.545 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.359,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.838,25.544 -0.96,3.518 0,4.518 -2.36,8.035 -1.878,2.519 -9.873,3.998 -13.151,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.036 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.518 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.998 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.519 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.919,1.48 -0.919,2.479 -0.48,-0.48 -0.96,-0.48 -1.44,-0.48 -0.439,0.48 -0.439,1 -0.919,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.035,5.476 -7.035,5.476 0,0 -3.279,-2.998 -6.117,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1060" />
+ <path
+ d="m 147.31,59.604 c 16.95,3.038 32.461,6.556 49.85,5.557 21.627,-1.52 42.775,-5.037 64.401,0 -8.434,-2 -18.788,-2 -21.626,8.554 0.48,-3.038 -0.92,-6.036 -3.758,-7.035 -4.198,-2.04 -5.637,1.998 -9.394,2.998 -5.637,1.519 -7.036,-2.519 -12.673,4.517 -3.318,-8.555 -5.197,-1.999 -10.833,-1.48 -2.838,0 -3.758,-2.518 -6.116,-3.037 -4.678,-1 -6.557,3.518 -10.794,3.518 -1.44,0 -1.44,-2.999 -3.318,-2.999 -1.4,-0.52 -2.798,0.48 -4.677,0 -2.359,0 -2.838,-2.038 -5.637,-1.519 -3.797,0.52 -5.676,6.037 -9.434,6.516 -0.92,-6.516 0,-7.515 -5.157,-10.553 z M 47.531,15.39 C 48.011,3.959 77.633,1.96 82.79,7.956 80.471,5.957 74.835,6.437 73.875,9.955 c -2.838,-2.998 -5.636,-1.999 -7.995,0 -2.358,-1.999 -4.677,-0.52 -7.036,-1 z m -32.86,15.032 c 4.238,-2.479 9.394,-2.479 13.632,-3.478 4.717,-1 8.475,-3.478 12.672,-4.997 -2.318,2.518 -5.636,5.996 -9.394,7.995 -5.637,2.958 -10.794,-0.52 -16.43,1.999 z m 105.776,126.883 c 6.596,9.554 10.873,20.067 15.55,30.621 2.839,5.996 5.677,10.993 5.197,18.03 0,8.034 -3.278,16.03 -4.237,23.545 0.96,-3.478 4.237,-12.513 8.955,-11.513 -0.96,-1.52 -2.359,-3.998 -2.359,-5.996 0,-3.039 3.278,-4.518 3.278,-7.036 0,-1.999 -3.278,-5.517 -3.758,-8.035 0,-2.479 0.48,-4.997 0.96,-6.996 -5.197,-1.999 -6.117,-7.516 -3.798,-12.553 -4.237,-0.999 -7.515,-2.998 -9.394,-7.515 -0.96,-1.999 0,-3.998 -1.44,-5.517 -1.399,-2.518 -3.757,-2.998 -5.156,-5.516 z M 264.84,144.353 c 7.995,10.553 19.308,17.549 26.823,28.582 3.758,4.997 7.995,11.513 10.354,17.55 1.4,2.478 3.278,5.996 3.278,8.994 0.48,3.518 -1.879,7.036 -1.4,10.514 1.88,-2 3.759,-6.476 3.759,-8.995 0.44,-3.518 -2.359,-3.518 -3.318,-7.515 -0.92,-3.518 0.959,-5.517 -0.44,-8.035 -0.48,-1.48 -2.838,-2.479 -3.758,-3.998 0,-1 -0.48,-3.518 -0.96,-3.998 -1.398,-2.518 -5.636,-2.518 -7.035,-5.516 -1.879,-5.517 1.879,-5.517 -3.318,-8.515 -4.677,-2.998 -14.551,-8.035 -15.99,-14.551 z m 10.353,30.541 c -0.44,2.518 -2.358,6.556 -1.399,9.554 0.48,1 2.359,0 2.359,0.52 0.48,1 0.92,2.518 1.399,3.518 1.439,4.517 -0.92,13.072 -6.596,12.072 2.358,-0.52 4.717,0.48 5.676,2.479 0,-3.998 1.4,-7.036 4.678,-8.515 -1.88,-3.038 -1.88,-6.036 -2.32,-9.074 -0.479,-3.998 -0.959,-6.516 -1.918,-10.034 -0.44,-3.518 0.48,-4.518 -1.879,-7.036 -1.879,-2.039 -3.758,-1 -6.596,-2.039 1.92,2.519 6.156,3.518 5.677,7.076 z m -149.469,19.068 c -3.798,4.997 -1.919,11.034 -2.359,17.03 0,1.999 -0.48,6.036 -1.879,7.516 -1.918,1.998 -4.237,1.519 -6.156,2.998 2.838,-2.479 7.076,-2.479 10.394,-1.48 -1.44,-4.517 -3.318,-9.034 2.318,-10.033 -2.318,-3.518 -1.399,-4.997 -1.399,-8.515 -0.48,-2.998 -1.879,-6.996 -0.92,-10.034 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1062" />
+ <path
+ d="m 117.649,122.206 c 0.96,-2.998 -0.92,-6.516 -0.44,-9.514 0.44,-3.998 1.879,-5.517 4.197,-8.515 -6.076,-2.519 -4.677,-6.036 -4.197,-11.553 0.44,-4.997 -2.359,-5.517 -4.717,-10.034 -2.838,-6.516 -2.838,-17.03 -3.278,-24.065 0,-7.996 -2.838,-14.032 -8.955,-19.029 -2.798,-2.518 -7.035,-7.036 -10.793,-7.036 -5.677,-0.52 -9.435,6.037 -11.313,11.034 -1.4,4.997 -4.238,17.549 -3.278,23.066 l 9.874,48.13 1.878,1.52 c 4.238,3.477 1.88,5.516 -0.48,7.515 0.48,1 0.96,1.48 1.88,1.999 h 1.879 c 1.439,0 2.838,0 3.757,0.52 0.48,0 1.44,0.48 2.359,0.48 0,3.517 -2.359,7.035 -1.88,10.513 2.84,-0.48 5.638,-1 7.077,-3.998 -0.96,2.998 -1.44,7.036 -1.44,9.514 1.44,-1.998 2.36,-4.996 2.839,-5.996 3.278,-6.036 13.632,-8.515 15.03,-14.551 z m 3.318,47.771 c 2.798,5.996 3.717,13.032 6.076,19.028 2.798,6.037 4.197,10.554 4.197,17.55 0.48,5.037 -0.48,13.072 -3.757,17.07 -3.238,3.997 -8.875,6.036 -12.633,9.514 6.117,-5.997 13.592,1 17.79,-6.996 3.757,-7.036 4.197,-14.551 4.197,-22.067 0,-8.554 -4.677,-10.553 -7.475,-17.549 -2.799,-6.036 -4.678,-14.551 -9.834,-18.589 z m 46.931,20.388 c 1.4,4.037 4.198,18.069 -2.358,16.55 0,3.517 0.92,6.516 -0.48,10.034 -1.4,-2 -2.838,-6.037 -5.157,-2.519 1.879,1.999 0,1.999 0,3.518 0.44,1.999 0.44,3.997 0.92,5.996 -6.117,1 -7.516,6.516 -10.794,11.034 -3.798,4.517 -8.954,7.515 -9.434,14.51 1.439,-4.996 -0.48,-11.512 2.838,-15.51 0,0.48 2.798,0 3.758,-1 1.879,-1.518 1.399,-3.997 2.358,-6.036 2.359,-4.997 2.799,-2.478 6.117,-5.996 3.278,-3.518 0.92,-7.036 0,-11.513 4.237,2.479 3.757,-4.037 2.798,-6.516 4.717,0 6.596,-1 6.116,-5.517 -0.48,-2.518 -2.358,-8.514 -3.278,-10.513 2.799,1.999 5.637,0.48 7.516,-1.04 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1064" />
+ <path
+ d="m 166.06,187.846 c -0.48,-1.959 -1.4,-5.477 -0.48,-7.435 0.96,-2.519 3.318,-2.999 3.757,-4.997 0.96,-3.478 -3.278,-6.476 1.88,-8.475 -2.32,0 -4.678,1.999 -6.557,-1 1.4,5.997 -4.717,8.995 -1.879,14.472 z m 11.752,-26.544 c -0.96,4.997 -3.318,12.992 3.278,14.991 3.318,1 11.753,-9.474 13.192,-2.998 2.359,-3.998 5.157,-3.478 8.915,-4.477 1.439,-0.52 1.879,-2.999 3.798,-2.519 1.878,0.52 2.798,3.518 2.798,4.997 0.96,-1.999 3.318,-7.515 5.636,-8.515 5.197,-1.479 4.238,3.038 5.677,6.037 1.4,-2 1.879,-5.517 4.237,-5.517 2.799,-0.52 4.198,2.998 4.678,4.997 1.878,-1.999 1.878,-8.515 4.717,-8.515 2.358,-0.48 3.757,2.998 3.278,5.037 2.838,-3.038 -0.48,-9.514 3.318,-11.513 0.92,1.48 1.399,3.478 1.399,4.477 1.399,-4.997 0.92,-7.475 6.596,-6.995 4.677,0 6.116,0.999 7.036,5.996 5.636,-4.997 6.596,4.997 6.596,8.515 3.757,-4.517 5.156,-8.995 2.358,-13.992 -2.838,-4.517 -4.717,-9.514 -6.116,-15.03 -1.4,1.998 -3.758,7.995 -6.116,7.995 -3.318,0 -4.238,-7.476 -5.197,-9.515 -1.4,2.04 -3.278,10.034 -5.637,10.514 -4.237,1.519 -6.596,-4.477 -7.995,-7.476 -1.879,2.999 -1.4,9.475 -4.717,11.993 -4.677,3.998 -4.198,-1.519 -8.435,-2.998 -1.879,7.515 -2.359,10.993 -9.914,12.512 -1.879,0 -1.879,0 -3.758,0.48 -1.879,0.52 -3.757,1.999 -5.636,2.519 -9.395,3.997 -19.269,1.479 -21.627,-9.515 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1066" />
+ <path
+ d="m 263.84,161.782 c 4.238,-4.477 13.192,3.518 16.03,6.516 4.238,4.038 5.677,8.555 5.197,14.031 0,5.517 -0.48,14.552 -3.318,19.549 -0.92,1.998 -3.757,5.037 -6.116,6.516 -2.359,1.519 -6.156,1.519 -7.076,3.997 6.117,-1.479 14.631,-1 16.99,-7.995 2.359,-7.515 2.359,-16.03 2.838,-23.546 0.44,-8.035 -3.797,-11.513 -9.914,-16.03 -2.838,-2.518 -10.873,-12.552 -13.711,-15.03 -2.799,-3.039 -0.44,1.998 -5.197,1.478 z m 48.93,57.645 c 0.92,5.517 5.157,13.552 1.88,18.549 -1.88,3.038 -15.112,7.515 -13.193,0 5.157,1 5.637,-3.998 7.516,-7.516 2.838,-4.997 2.838,-3.518 1.919,-9.034 -0.96,-8.515 3.757,-17.03 2.798,-25.585 z M 292.583,79.112 c 3.757,7.036 10.353,8.555 10.793,18.07 0.96,7.035 -0.44,15.07 1.879,22.066 1.4,6.036 4.717,11.073 7.036,16.59 0.96,1.479 4.237,5.996 4.237,7.515 0.44,2.998 -2.358,4.517 -1.879,9.035 -6.116,-0.52 -1.399,5.516 -0.48,8.514 -2.358,-2.478 -7.035,-4.996 -7.955,-8.514 7.956,-2.519 2.799,-11.034 -1.439,-14.032 5.197,-9.034 -3.278,-12.073 -7.955,-17.59 3.758,-4.516 1.879,-8.034 -1.879,-11.552 5.157,-5.997 4.238,-26.584 -2.358,-31.621 z M 39.536,63.601 c 3.318,1.52 5.197,1.52 7.555,5.037 1.88,2.479 2.359,5.477 4.238,7.996 1.399,1.998 3.278,3.997 4.717,6.476 1.4,1.519 4.677,5.996 6.596,7.995 0.92,-5.997 -2.838,-9.474 -2.359,-14.991 0.44,-3.998 2.359,-8.475 3.758,-11.993 1.879,-4.997 3.278,-8.515 6.116,-11.993 3.278,-3.517 7.516,-7.995 6.596,-14.031 -1.399,6.516 -7.075,15.51 -14.59,12.512 -2.839,5.997 -4.238,7.516 -10.354,7.516 2.798,2.478 5.636,6.996 4.237,11.513 -1.879,-1.999 -5.197,-4.517 -7.555,-5.037 -3.278,-0.48 -5.637,1.519 -8.955,-1.999 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1068" />
+ <path
+ d="m 111.053,226.023 c -1.84,0.52 -3.278,2.998 -3.278,3.998 m 153.267,-88.747 c 1.439,7.556 13.672,16.07 17.909,22.067 3.318,4.517 10.833,9.035 12.233,15.03 M 121.446,164.94 c 2.839,4.517 5.197,10.514 7.076,15.03 0.92,2.52 1.4,4.998 2.359,7.516 1.399,2.519 2.798,2.999 4.677,5.517 5.157,6.996 0.48,27.503 -2.798,35.538 -0.48,1.48 -0.96,2.999 -1.88,3.478 M 52.288,6.396 c -3.278,1.52 -7.955,7.076 -9.354,10.594 -1.879,3.518 -6.076,3.997 -7.515,4.997 m 100.019,222.585 c -1.839,0.52 -2.319,3.038 -3.278,4.557 m -1.839,-7.995 c -3.278,0 -7.036,1.519 -7.995,4.957 m -11.673,-25.505 c -1.879,1 -4.237,1 -6.156,2.959 m 168.378,-16.55 c -2.319,0.52 -5.597,1.519 -6.077,3.997 m 2.799,-9.514 c -1.92,0 -3.838,1.04 -5.277,2.558 m 38.137,30.542 c -1.88,2.039 -3.758,4.037 -3.758,6.556 m -3.278,-9.594 c -1.839,1.559 -4.637,2.558 -5.117,5.596 m 21.986,-3.997 c -0.919,1.519 -1.358,2.518 -1.838,3.997 M 181.17,151.828 c -1.399,0.52 -4.717,4.038 -6.116,5.037 2.358,2.518 0.96,10.554 -2.838,11.553 0.48,2.039 -0.48,2.518 0.48,4.517 m -52.169,-7.595 c 0.92,-4.477 -5.197,-3.998 -7.076,-6.516 1.44,-1.48 3.318,-3.478 1.88,-5.477 -1.88,0.48 -3.759,0 -5.158,-1.519 1.4,-1.999 2.359,-4.997 0.48,-7.036 -1.919,1.52 -3.798,1.04 -6.156,0.52 M 11.473,32.94 c 0.44,7.076 -3.358,11.593 -8.595,9.075"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1070" />
+ <path
+ d="m 9.514,39.976 c 0.96,-1 2.359,-6.476 1.44,-7.955 -0.96,-1.52 -4.718,-1.52 -6.637,-1 -2.358,1 -3.318,2.998 -2.838,8.475 0,1.999 0.48,2.998 0.48,3.958 l 1.439,-0.96 c 2.359,0 4.717,0 6.116,-2.518 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1072" />
+ <path
+ d="m 55.566,32.54 c -2.798,-1.479 -4.197,-5.996 -7.035,-7.995 -2.799,-1.999 -2.799,0.52 -4.718,3.518"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1074" />
+ <path
+ d="M 52.848,29.102 C 49.09,38.137 42.454,27.104 45.772,25.584 m 11.233,0.96 C 55.606,22.067 50.01,18.549 46.692,19.548 m -33.98,39.136 c 3.318,-1.998 4.278,0.96 6.636,2.439 3.318,1.959 6.157,-0.48 8.955,0.52"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1076" />
+ <path
+ clip-path="url(#a)"
+ d="m 65,104.337 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.969,73.755 47.131,72.756 44.333,69.238 41.975,67.239 35.379,66.24 33.5,66.24 23.626,66.24 16.59,65.72 8.595,57.685 6.715,55.207 5.757,52.168 4.837,48.69 3.397,44.653 2,45.652 1.52,39.656 1.04,33.14 2,31.621 6.237,30.621 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.995,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.88,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.551 -1.4,6.517 -2.319,17.03 -1.879,23.546 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.36,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.839,25.544 -0.959,3.518 0,4.518 -2.358,8.035 -1.879,2.519 -9.874,3.998 -13.152,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.037 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.517 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.999 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.518 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.92,1.48 -0.92,2.479 -0.479,-0.48 -0.958,-0.48 -1.438,-0.48 -0.44,0.48 -0.44,1 -0.92,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.036,5.476 -7.036,5.476 0,0 -3.278,-2.998 -6.116,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1078" />
+ <path
+ d="m 308.533,99.18 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 v 0.52 c 0,0 0,0 0,0 v 1.519"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1080" />
+ <path
+ d="m 95.102,24.905 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.551 0,3.038 0,5.517 0.48,8.555 0.48,3.518 0,7.036 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.92,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.196,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.076,-1.519 -1.88,1.52 -0.92,3.998 -0.44,6.036 -1.44,0 -2.839,-0.52 -3.798,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.514,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.96,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1082" />
+ <path
+ d="m 81.91,41.055 c -1.399,4.038 -3.278,8.035 -5.596,11.033 -1.88,2.519 -4.238,5.037 -5.157,7.516 -0.48,1.519 0,3.038 -0.48,4.517 -0.44,1.52 -2.318,2.998 -2.798,4.517 -0.48,1 -0.48,2.519 -0.48,3.518 -0.44,1.48 -1.879,2.519 -1.879,3.998 0,1.519 1.44,2.998 1.44,4.517 0.44,1.52 0.44,2.998 0.44,4.517 0,3.518 -0.92,6.996 -0.44,10.034 0,2 0.919,3.478 0.919,5.517 0,1.999 -0.92,3.478 -0.48,5.477 0.48,1.519 0.96,2.038 1.4,3.517 0.959,1.52 0,3.518 0.479,5.037 3.278,-0.999 2.798,2.479 3.278,4.478 0.96,-2 3.758,-2.479 5.637,-2 -0.96,-0.479 -3.758,-0.998 -4.678,-1.478 -1.878,-1.52 0,-6.037 1.4,-7.516 -1.4,0 -4.238,-0.52 -4.678,-2.038 -0.959,-2 3.278,-4.478 3.718,-5.997 -1.879,-0.52 -3.278,-1 -3.718,-2.998 -1.439,-3.518 1.4,-5.037 1.84,-8.035 0,-1.999 -1.4,-1.48 -2.32,-3.518 -0.959,-1.999 0,-4.477 1.88,-5.996 -2.359,-3.518 -2.839,-5.517 -0.48,-9.035 0.92,-1.479 0.92,-0.48 0.92,-1.999 0.479,-1.998 -1.4,-3.517 0.959,-5.516 0.92,-1 1.879,-0.48 2.318,-1.999 0.48,-1 0,-3.998 0.96,-5.517 0.48,-1.998 0.92,-4.517 1.879,-6.995 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1084" />
+ <path
+ d="m 95.142,24.945 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.55 0,3.04 0,5.518 0.48,8.556 0.48,3.518 0,7.035 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.919,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.197,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.077,-1.519 -1.878,1.52 -0.919,3.998 -0.44,6.036 -1.438,0 -2.838,-0.52 -3.797,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.515,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.959,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1086" />
+ <path
+ d="m 103.058,54.087 c -0.48,2.998 0,5.997 0,9.035 v 9.994 c 0.44,6.556 1.399,13.551 3.278,19.588 0.48,1 0.959,1.999 1.399,3.478 0,1.519 0,1 -0.44,2.518 -0.48,1.999 -0.96,2.998 -0.96,5.037 0.48,1.999 0.96,2.998 0.96,4.477 -0.48,0.52 -1.44,1.52 -1.44,2.519 -0.439,1 0,2.518 -0.439,2.998 -0.48,1 -1.919,1 -2.838,2.039 -0.48,1.479 0,2.998 -0.96,4.477 -1.399,-1 -2.798,0.52 -3.757,1 -0.92,-1 -1.88,-1.48 -2.839,-1 0.96,-1 3.798,-2.478 4.718,-3.478 0.959,-2.039 0,-4.517 -0.92,-7.036 2.359,0 3.278,-2.518 3.278,-4.996 0,-2.04 -0.92,-2.04 -1.879,-3.518 -0.96,-2.519 1.4,-4.038 1.88,-6.516 0.959,-4.038 -0.92,-5.517 -2.84,-8.036 4.238,-4.517 1.92,-8.035 0.48,-12.512 -0.919,-3.038 0.96,-5.517 0.48,-9.034 0,-2.999 1.4,-6.037 1.4,-9.035 0.48,-1.999 0.959,-4.997 0.48,-7.036 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1088" />
+ <path
+ d="m 45.253,24.545 c -1.88,3.478 2.838,10.914 6.116,6.956 2.318,-2.479 -3.758,-9.954 -5.637,-6.956 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1090" />
+ <path
+ d="m 45.692,26.944 c 0,-0.52 0.44,-1 0.92,-1 0.52,0 0.92,0.48 0.92,1 0,0.56 -0.4,1 -0.92,1 -0.48,0 -0.92,-0.44 -0.92,-1 z"
+ fill="#ffffff"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1092" />
+ <path
+ d="m 2.878,39.016 c 0.96,0 2.399,0.48 3.358,0.48 0.96,0 1.44,-1.479 2.399,-1.999"
+ fill="none"
+ stroke="#ffffff"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1094" />
+ <path
+ d="m 80.111,31.46 c -1.439,-0.519 -3.358,0 -3.837,2.08 1.919,0.48 3.837,-1.04 5.277,0.48 -0.96,2.078 -2.879,3.078 -4.798,3.078 M 96.981,26.064 c -2.798,-1.519 -7.036,3.038 -1.879,3.518 1.88,0.52 3.278,-1.519 4.238,1 0.44,1.998 -3.278,5.036 -4.238,6.516 M 47.171,20.987 c -0.48,-3.438 5.677,-4.437 2.399,1.96 M 26.944,63.082 c 0,-1 0.96,-3.478 -0.48,-3.478 -1.919,-0.52 -2.878,2.478 -2.399,3.478 m 82.271,86.348 c 0,-2.04 0.48,-4.558 0.959,-6.637 2.319,0.52 2.319,4.118 1.879,6.636 m 71.516,4.917 c -3.717,-6.915 -6.556,0.48 -2.798,2.439 m 83.709,-12.952 c 0.92,-0.48 1.84,-1 2.719,-1.999 m 7.995,67.159 c -0.44,-4.037 -6.556,-4.557 -3.718,0 m 33.86,28.143 c -0.96,-1.04 -1.92,-1.599 -2.879,-1.599 m -5.116,-1.399 c -2.359,-6.116 -6.157,1.56 -2.359,2.039"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1096" />
+ <path
+ d="m 267.638,200.039 c -1.4,1.999 1.399,4.997 0.48,5.996 -1.88,1.999 -3.798,-1 -3.798,-2.478 m -155.146,16.07 c 0,1.479 0.44,2.478 0.44,3.918 -1.4,-0.48 -2.319,-0.96 -3.278,-2.439 m 1.838,4.917 c 0.52,1.52 1,2.518 2,3.518 m 18.868,10.514 c 2.318,6.036 -2.359,2.518 -4.238,-0.52"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1098" />
+ <path
+ clip-path="url(#a)"
+ d="m 135.078,244.092 c -0.44,1.999 0.96,2.519 1.4,3.998 -2.32,0.48 -3.718,-1 -5.597,-1.48"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1100" />
+ <path
+ d="m 121.926,242.573 c 0.48,2.039 1.879,3.038 3.278,3.518"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1102" />
+ </g>
+ </g>
+ <g
+ id="layer2"
+ inkscape:label="Layer 2"
+ clip-path="none"
+ inkscape:groupmode="layer"
+ transform="matrix(0.5,0,0,0.5,0,150)">
+ <circle
+ r="8"
+ cy="-284"
+ cx="34"
+ style="fill:#ffc022;stroke:#b88100;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
+ id="path3319-3" />
+ <circle
+ r="8"
+ cy="-284"
+ cx="66"
+ style="fill:#cc0000;stroke:#a40000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
+ id="path3319" />
+ <circle
+ r="12"
+ cy="-284"
+ cx="50"
+ style="fill:#ffffff;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
+ id="path3331" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="Layer 3" />
+</svg>
diff --git a/share/extensions/other/clipart/licenses/cc-by-sa.png b/share/extensions/other/clipart/licenses/cc-by-sa.png
new file mode 100644
index 0000000..5dea2be
--- /dev/null
+++ b/share/extensions/other/clipart/licenses/cc-by-sa.png
Binary files differ
diff --git a/share/extensions/other/clipart/licenses/cc-by-sa.svg b/share/extensions/other/clipart/licenses/cc-by-sa.svg
new file mode 100644
index 0000000..320531d
--- /dev/null
+++ b/share/extensions/other/clipart/licenses/cc-by-sa.svg
@@ -0,0 +1,340 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="50"
+ height="16"
+ viewBox="0 0 50 16"
+ version="1.1"
+ id="svg5"
+ sodipodi:docname="cc-by-sa.svg"
+ inkscape:version="1.2-alpha1 (8b0d57f509, 2022-03-02, custom)"
+ inkscape:export-filename="/home/doctormo/Projects/inkscape/extensions/main/other/clipart/licenses/cc-by-sa.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#999999"
+ borderopacity="1"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="2.9434"
+ inkscape:cx="-13.080111"
+ inkscape:cy="27.349324"
+ inkscape:window-width="1472"
+ inkscape:window-height="807"
+ inkscape:window-x="64"
+ inkscape:window-y="20"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer2" />
+ <defs
+ id="defs2">
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect2486"
+ is_visible="true"
+ lpeversion="1"
+ nodesatellites_param=""
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false"
+ satellites_param="" />
+ <color-profile
+ name="AL1706"
+ xlink:href="../../../../../.local/share/icc/edid-a9cf44b399fa09c3fc2589cbaadd3747.icc"
+ id="color-profile1757" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="a">
+ <path
+ d="M 0.24,1.04 H 322.045 V 255.205 H 0.24 Z"
+ id="path1048" />
+ </clipPath>
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect2486-3"
+ is_visible="true"
+ lpeversion="1"
+ nodesatellites_param=""
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false"
+ satellites_param="" />
+ </defs>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-51.633091,-21.31349)"
+ sodipodi:insensitive="true"
+ style="display:none">
+ <g
+ inkscape:label="dog.svg"
+ transform="matrix(0.24767307,0,0,0.24767307,51.414234,28.015162)"
+ id="g1104">
+ <path
+ d="m 308.493,99.14 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1058" />
+ <path
+ clip-path="url(#a)"
+ d="m 64.96,104.297 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.929,73.715 47.091,72.716 44.293,69.198 41.935,67.2 35.34,66.2 33.46,66.2 23.586,66.2 16.55,65.68 8.555,57.645 6.676,55.167 5.717,52.128 4.797,48.651 3.358,44.613 1.959,45.612 1.479,39.616 0.999,33.1 1.959,31.581 6.196,30.581 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.996,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.879,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.552 -1.4,6.516 -2.319,17.03 -1.879,23.545 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.359,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.838,25.544 -0.96,3.518 0,4.518 -2.36,8.035 -1.878,2.519 -9.873,3.998 -13.151,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.036 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.518 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.998 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.519 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.919,1.48 -0.919,2.479 -0.48,-0.48 -0.96,-0.48 -1.44,-0.48 -0.439,0.48 -0.439,1 -0.919,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.035,5.476 -7.035,5.476 0,0 -3.279,-2.998 -6.117,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1060" />
+ <path
+ d="m 147.31,59.604 c 16.95,3.038 32.461,6.556 49.85,5.557 21.627,-1.52 42.775,-5.037 64.401,0 -8.434,-2 -18.788,-2 -21.626,8.554 0.48,-3.038 -0.92,-6.036 -3.758,-7.035 -4.198,-2.04 -5.637,1.998 -9.394,2.998 -5.637,1.519 -7.036,-2.519 -12.673,4.517 -3.318,-8.555 -5.197,-1.999 -10.833,-1.48 -2.838,0 -3.758,-2.518 -6.116,-3.037 -4.678,-1 -6.557,3.518 -10.794,3.518 -1.44,0 -1.44,-2.999 -3.318,-2.999 -1.4,-0.52 -2.798,0.48 -4.677,0 -2.359,0 -2.838,-2.038 -5.637,-1.519 -3.797,0.52 -5.676,6.037 -9.434,6.516 -0.92,-6.516 0,-7.515 -5.157,-10.553 z M 47.531,15.39 C 48.011,3.959 77.633,1.96 82.79,7.956 80.471,5.957 74.835,6.437 73.875,9.955 c -2.838,-2.998 -5.636,-1.999 -7.995,0 -2.358,-1.999 -4.677,-0.52 -7.036,-1 z m -32.86,15.032 c 4.238,-2.479 9.394,-2.479 13.632,-3.478 4.717,-1 8.475,-3.478 12.672,-4.997 -2.318,2.518 -5.636,5.996 -9.394,7.995 -5.637,2.958 -10.794,-0.52 -16.43,1.999 z m 105.776,126.883 c 6.596,9.554 10.873,20.067 15.55,30.621 2.839,5.996 5.677,10.993 5.197,18.03 0,8.034 -3.278,16.03 -4.237,23.545 0.96,-3.478 4.237,-12.513 8.955,-11.513 -0.96,-1.52 -2.359,-3.998 -2.359,-5.996 0,-3.039 3.278,-4.518 3.278,-7.036 0,-1.999 -3.278,-5.517 -3.758,-8.035 0,-2.479 0.48,-4.997 0.96,-6.996 -5.197,-1.999 -6.117,-7.516 -3.798,-12.553 -4.237,-0.999 -7.515,-2.998 -9.394,-7.515 -0.96,-1.999 0,-3.998 -1.44,-5.517 -1.399,-2.518 -3.757,-2.998 -5.156,-5.516 z M 264.84,144.353 c 7.995,10.553 19.308,17.549 26.823,28.582 3.758,4.997 7.995,11.513 10.354,17.55 1.4,2.478 3.278,5.996 3.278,8.994 0.48,3.518 -1.879,7.036 -1.4,10.514 1.88,-2 3.759,-6.476 3.759,-8.995 0.44,-3.518 -2.359,-3.518 -3.318,-7.515 -0.92,-3.518 0.959,-5.517 -0.44,-8.035 -0.48,-1.48 -2.838,-2.479 -3.758,-3.998 0,-1 -0.48,-3.518 -0.96,-3.998 -1.398,-2.518 -5.636,-2.518 -7.035,-5.516 -1.879,-5.517 1.879,-5.517 -3.318,-8.515 -4.677,-2.998 -14.551,-8.035 -15.99,-14.551 z m 10.353,30.541 c -0.44,2.518 -2.358,6.556 -1.399,9.554 0.48,1 2.359,0 2.359,0.52 0.48,1 0.92,2.518 1.399,3.518 1.439,4.517 -0.92,13.072 -6.596,12.072 2.358,-0.52 4.717,0.48 5.676,2.479 0,-3.998 1.4,-7.036 4.678,-8.515 -1.88,-3.038 -1.88,-6.036 -2.32,-9.074 -0.479,-3.998 -0.959,-6.516 -1.918,-10.034 -0.44,-3.518 0.48,-4.518 -1.879,-7.036 -1.879,-2.039 -3.758,-1 -6.596,-2.039 1.92,2.519 6.156,3.518 5.677,7.076 z m -149.469,19.068 c -3.798,4.997 -1.919,11.034 -2.359,17.03 0,1.999 -0.48,6.036 -1.879,7.516 -1.918,1.998 -4.237,1.519 -6.156,2.998 2.838,-2.479 7.076,-2.479 10.394,-1.48 -1.44,-4.517 -3.318,-9.034 2.318,-10.033 -2.318,-3.518 -1.399,-4.997 -1.399,-8.515 -0.48,-2.998 -1.879,-6.996 -0.92,-10.034 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1062" />
+ <path
+ d="m 117.649,122.206 c 0.96,-2.998 -0.92,-6.516 -0.44,-9.514 0.44,-3.998 1.879,-5.517 4.197,-8.515 -6.076,-2.519 -4.677,-6.036 -4.197,-11.553 0.44,-4.997 -2.359,-5.517 -4.717,-10.034 -2.838,-6.516 -2.838,-17.03 -3.278,-24.065 0,-7.996 -2.838,-14.032 -8.955,-19.029 -2.798,-2.518 -7.035,-7.036 -10.793,-7.036 -5.677,-0.52 -9.435,6.037 -11.313,11.034 -1.4,4.997 -4.238,17.549 -3.278,23.066 l 9.874,48.13 1.878,1.52 c 4.238,3.477 1.88,5.516 -0.48,7.515 0.48,1 0.96,1.48 1.88,1.999 h 1.879 c 1.439,0 2.838,0 3.757,0.52 0.48,0 1.44,0.48 2.359,0.48 0,3.517 -2.359,7.035 -1.88,10.513 2.84,-0.48 5.638,-1 7.077,-3.998 -0.96,2.998 -1.44,7.036 -1.44,9.514 1.44,-1.998 2.36,-4.996 2.839,-5.996 3.278,-6.036 13.632,-8.515 15.03,-14.551 z m 3.318,47.771 c 2.798,5.996 3.717,13.032 6.076,19.028 2.798,6.037 4.197,10.554 4.197,17.55 0.48,5.037 -0.48,13.072 -3.757,17.07 -3.238,3.997 -8.875,6.036 -12.633,9.514 6.117,-5.997 13.592,1 17.79,-6.996 3.757,-7.036 4.197,-14.551 4.197,-22.067 0,-8.554 -4.677,-10.553 -7.475,-17.549 -2.799,-6.036 -4.678,-14.551 -9.834,-18.589 z m 46.931,20.388 c 1.4,4.037 4.198,18.069 -2.358,16.55 0,3.517 0.92,6.516 -0.48,10.034 -1.4,-2 -2.838,-6.037 -5.157,-2.519 1.879,1.999 0,1.999 0,3.518 0.44,1.999 0.44,3.997 0.92,5.996 -6.117,1 -7.516,6.516 -10.794,11.034 -3.798,4.517 -8.954,7.515 -9.434,14.51 1.439,-4.996 -0.48,-11.512 2.838,-15.51 0,0.48 2.798,0 3.758,-1 1.879,-1.518 1.399,-3.997 2.358,-6.036 2.359,-4.997 2.799,-2.478 6.117,-5.996 3.278,-3.518 0.92,-7.036 0,-11.513 4.237,2.479 3.757,-4.037 2.798,-6.516 4.717,0 6.596,-1 6.116,-5.517 -0.48,-2.518 -2.358,-8.514 -3.278,-10.513 2.799,1.999 5.637,0.48 7.516,-1.04 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1064" />
+ <path
+ d="m 166.06,187.846 c -0.48,-1.959 -1.4,-5.477 -0.48,-7.435 0.96,-2.519 3.318,-2.999 3.757,-4.997 0.96,-3.478 -3.278,-6.476 1.88,-8.475 -2.32,0 -4.678,1.999 -6.557,-1 1.4,5.997 -4.717,8.995 -1.879,14.472 z m 11.752,-26.544 c -0.96,4.997 -3.318,12.992 3.278,14.991 3.318,1 11.753,-9.474 13.192,-2.998 2.359,-3.998 5.157,-3.478 8.915,-4.477 1.439,-0.52 1.879,-2.999 3.798,-2.519 1.878,0.52 2.798,3.518 2.798,4.997 0.96,-1.999 3.318,-7.515 5.636,-8.515 5.197,-1.479 4.238,3.038 5.677,6.037 1.4,-2 1.879,-5.517 4.237,-5.517 2.799,-0.52 4.198,2.998 4.678,4.997 1.878,-1.999 1.878,-8.515 4.717,-8.515 2.358,-0.48 3.757,2.998 3.278,5.037 2.838,-3.038 -0.48,-9.514 3.318,-11.513 0.92,1.48 1.399,3.478 1.399,4.477 1.399,-4.997 0.92,-7.475 6.596,-6.995 4.677,0 6.116,0.999 7.036,5.996 5.636,-4.997 6.596,4.997 6.596,8.515 3.757,-4.517 5.156,-8.995 2.358,-13.992 -2.838,-4.517 -4.717,-9.514 -6.116,-15.03 -1.4,1.998 -3.758,7.995 -6.116,7.995 -3.318,0 -4.238,-7.476 -5.197,-9.515 -1.4,2.04 -3.278,10.034 -5.637,10.514 -4.237,1.519 -6.596,-4.477 -7.995,-7.476 -1.879,2.999 -1.4,9.475 -4.717,11.993 -4.677,3.998 -4.198,-1.519 -8.435,-2.998 -1.879,7.515 -2.359,10.993 -9.914,12.512 -1.879,0 -1.879,0 -3.758,0.48 -1.879,0.52 -3.757,1.999 -5.636,2.519 -9.395,3.997 -19.269,1.479 -21.627,-9.515 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1066" />
+ <path
+ d="m 263.84,161.782 c 4.238,-4.477 13.192,3.518 16.03,6.516 4.238,4.038 5.677,8.555 5.197,14.031 0,5.517 -0.48,14.552 -3.318,19.549 -0.92,1.998 -3.757,5.037 -6.116,6.516 -2.359,1.519 -6.156,1.519 -7.076,3.997 6.117,-1.479 14.631,-1 16.99,-7.995 2.359,-7.515 2.359,-16.03 2.838,-23.546 0.44,-8.035 -3.797,-11.513 -9.914,-16.03 -2.838,-2.518 -10.873,-12.552 -13.711,-15.03 -2.799,-3.039 -0.44,1.998 -5.197,1.478 z m 48.93,57.645 c 0.92,5.517 5.157,13.552 1.88,18.549 -1.88,3.038 -15.112,7.515 -13.193,0 5.157,1 5.637,-3.998 7.516,-7.516 2.838,-4.997 2.838,-3.518 1.919,-9.034 -0.96,-8.515 3.757,-17.03 2.798,-25.585 z M 292.583,79.112 c 3.757,7.036 10.353,8.555 10.793,18.07 0.96,7.035 -0.44,15.07 1.879,22.066 1.4,6.036 4.717,11.073 7.036,16.59 0.96,1.479 4.237,5.996 4.237,7.515 0.44,2.998 -2.358,4.517 -1.879,9.035 -6.116,-0.52 -1.399,5.516 -0.48,8.514 -2.358,-2.478 -7.035,-4.996 -7.955,-8.514 7.956,-2.519 2.799,-11.034 -1.439,-14.032 5.197,-9.034 -3.278,-12.073 -7.955,-17.59 3.758,-4.516 1.879,-8.034 -1.879,-11.552 5.157,-5.997 4.238,-26.584 -2.358,-31.621 z M 39.536,63.601 c 3.318,1.52 5.197,1.52 7.555,5.037 1.88,2.479 2.359,5.477 4.238,7.996 1.399,1.998 3.278,3.997 4.717,6.476 1.4,1.519 4.677,5.996 6.596,7.995 0.92,-5.997 -2.838,-9.474 -2.359,-14.991 0.44,-3.998 2.359,-8.475 3.758,-11.993 1.879,-4.997 3.278,-8.515 6.116,-11.993 3.278,-3.517 7.516,-7.995 6.596,-14.031 -1.399,6.516 -7.075,15.51 -14.59,12.512 -2.839,5.997 -4.238,7.516 -10.354,7.516 2.798,2.478 5.636,6.996 4.237,11.513 -1.879,-1.999 -5.197,-4.517 -7.555,-5.037 -3.278,-0.48 -5.637,1.519 -8.955,-1.999 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1068" />
+ <path
+ d="m 111.053,226.023 c -1.84,0.52 -3.278,2.998 -3.278,3.998 m 153.267,-88.747 c 1.439,7.556 13.672,16.07 17.909,22.067 3.318,4.517 10.833,9.035 12.233,15.03 M 121.446,164.94 c 2.839,4.517 5.197,10.514 7.076,15.03 0.92,2.52 1.4,4.998 2.359,7.516 1.399,2.519 2.798,2.999 4.677,5.517 5.157,6.996 0.48,27.503 -2.798,35.538 -0.48,1.48 -0.96,2.999 -1.88,3.478 M 52.288,6.396 c -3.278,1.52 -7.955,7.076 -9.354,10.594 -1.879,3.518 -6.076,3.997 -7.515,4.997 m 100.019,222.585 c -1.839,0.52 -2.319,3.038 -3.278,4.557 m -1.839,-7.995 c -3.278,0 -7.036,1.519 -7.995,4.957 m -11.673,-25.505 c -1.879,1 -4.237,1 -6.156,2.959 m 168.378,-16.55 c -2.319,0.52 -5.597,1.519 -6.077,3.997 m 2.799,-9.514 c -1.92,0 -3.838,1.04 -5.277,2.558 m 38.137,30.542 c -1.88,2.039 -3.758,4.037 -3.758,6.556 m -3.278,-9.594 c -1.839,1.559 -4.637,2.558 -5.117,5.596 m 21.986,-3.997 c -0.919,1.519 -1.358,2.518 -1.838,3.997 M 181.17,151.828 c -1.399,0.52 -4.717,4.038 -6.116,5.037 2.358,2.518 0.96,10.554 -2.838,11.553 0.48,2.039 -0.48,2.518 0.48,4.517 m -52.169,-7.595 c 0.92,-4.477 -5.197,-3.998 -7.076,-6.516 1.44,-1.48 3.318,-3.478 1.88,-5.477 -1.88,0.48 -3.759,0 -5.158,-1.519 1.4,-1.999 2.359,-4.997 0.48,-7.036 -1.919,1.52 -3.798,1.04 -6.156,0.52 M 11.473,32.94 c 0.44,7.076 -3.358,11.593 -8.595,9.075"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1070" />
+ <path
+ d="m 9.514,39.976 c 0.96,-1 2.359,-6.476 1.44,-7.955 -0.96,-1.52 -4.718,-1.52 -6.637,-1 -2.358,1 -3.318,2.998 -2.838,8.475 0,1.999 0.48,2.998 0.48,3.958 l 1.439,-0.96 c 2.359,0 4.717,0 6.116,-2.518 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1072" />
+ <path
+ d="m 55.566,32.54 c -2.798,-1.479 -4.197,-5.996 -7.035,-7.995 -2.799,-1.999 -2.799,0.52 -4.718,3.518"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1074" />
+ <path
+ d="M 52.848,29.102 C 49.09,38.137 42.454,27.104 45.772,25.584 m 11.233,0.96 C 55.606,22.067 50.01,18.549 46.692,19.548 m -33.98,39.136 c 3.318,-1.998 4.278,0.96 6.636,2.439 3.318,1.959 6.157,-0.48 8.955,0.52"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1076" />
+ <path
+ clip-path="url(#a)"
+ d="m 65,104.337 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.969,73.755 47.131,72.756 44.333,69.238 41.975,67.239 35.379,66.24 33.5,66.24 23.626,66.24 16.59,65.72 8.595,57.685 6.715,55.207 5.757,52.168 4.837,48.69 3.397,44.653 2,45.652 1.52,39.656 1.04,33.14 2,31.621 6.237,30.621 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.995,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.88,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.551 -1.4,6.517 -2.319,17.03 -1.879,23.546 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.36,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.839,25.544 -0.959,3.518 0,4.518 -2.358,8.035 -1.879,2.519 -9.874,3.998 -13.152,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.037 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.517 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.999 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.518 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.92,1.48 -0.92,2.479 -0.479,-0.48 -0.958,-0.48 -1.438,-0.48 -0.44,0.48 -0.44,1 -0.92,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.036,5.476 -7.036,5.476 0,0 -3.278,-2.998 -6.116,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1078" />
+ <path
+ d="m 308.533,99.18 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 v 0.52 c 0,0 0,0 0,0 v 1.519"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1080" />
+ <path
+ d="m 95.102,24.905 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.551 0,3.038 0,5.517 0.48,8.555 0.48,3.518 0,7.036 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.92,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.196,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.076,-1.519 -1.88,1.52 -0.92,3.998 -0.44,6.036 -1.44,0 -2.839,-0.52 -3.798,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.514,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.96,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1082" />
+ <path
+ d="m 81.91,41.055 c -1.399,4.038 -3.278,8.035 -5.596,11.033 -1.88,2.519 -4.238,5.037 -5.157,7.516 -0.48,1.519 0,3.038 -0.48,4.517 -0.44,1.52 -2.318,2.998 -2.798,4.517 -0.48,1 -0.48,2.519 -0.48,3.518 -0.44,1.48 -1.879,2.519 -1.879,3.998 0,1.519 1.44,2.998 1.44,4.517 0.44,1.52 0.44,2.998 0.44,4.517 0,3.518 -0.92,6.996 -0.44,10.034 0,2 0.919,3.478 0.919,5.517 0,1.999 -0.92,3.478 -0.48,5.477 0.48,1.519 0.96,2.038 1.4,3.517 0.959,1.52 0,3.518 0.479,5.037 3.278,-0.999 2.798,2.479 3.278,4.478 0.96,-2 3.758,-2.479 5.637,-2 -0.96,-0.479 -3.758,-0.998 -4.678,-1.478 -1.878,-1.52 0,-6.037 1.4,-7.516 -1.4,0 -4.238,-0.52 -4.678,-2.038 -0.959,-2 3.278,-4.478 3.718,-5.997 -1.879,-0.52 -3.278,-1 -3.718,-2.998 -1.439,-3.518 1.4,-5.037 1.84,-8.035 0,-1.999 -1.4,-1.48 -2.32,-3.518 -0.959,-1.999 0,-4.477 1.88,-5.996 -2.359,-3.518 -2.839,-5.517 -0.48,-9.035 0.92,-1.479 0.92,-0.48 0.92,-1.999 0.479,-1.998 -1.4,-3.517 0.959,-5.516 0.92,-1 1.879,-0.48 2.318,-1.999 0.48,-1 0,-3.998 0.96,-5.517 0.48,-1.998 0.92,-4.517 1.879,-6.995 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1084" />
+ <path
+ d="m 95.142,24.945 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.55 0,3.04 0,5.518 0.48,8.556 0.48,3.518 0,7.035 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.919,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.197,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.077,-1.519 -1.878,1.52 -0.919,3.998 -0.44,6.036 -1.438,0 -2.838,-0.52 -3.797,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.515,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.959,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1086" />
+ <path
+ d="m 103.058,54.087 c -0.48,2.998 0,5.997 0,9.035 v 9.994 c 0.44,6.556 1.399,13.551 3.278,19.588 0.48,1 0.959,1.999 1.399,3.478 0,1.519 0,1 -0.44,2.518 -0.48,1.999 -0.96,2.998 -0.96,5.037 0.48,1.999 0.96,2.998 0.96,4.477 -0.48,0.52 -1.44,1.52 -1.44,2.519 -0.439,1 0,2.518 -0.439,2.998 -0.48,1 -1.919,1 -2.838,2.039 -0.48,1.479 0,2.998 -0.96,4.477 -1.399,-1 -2.798,0.52 -3.757,1 -0.92,-1 -1.88,-1.48 -2.839,-1 0.96,-1 3.798,-2.478 4.718,-3.478 0.959,-2.039 0,-4.517 -0.92,-7.036 2.359,0 3.278,-2.518 3.278,-4.996 0,-2.04 -0.92,-2.04 -1.879,-3.518 -0.96,-2.519 1.4,-4.038 1.88,-6.516 0.959,-4.038 -0.92,-5.517 -2.84,-8.036 4.238,-4.517 1.92,-8.035 0.48,-12.512 -0.919,-3.038 0.96,-5.517 0.48,-9.034 0,-2.999 1.4,-6.037 1.4,-9.035 0.48,-1.999 0.959,-4.997 0.48,-7.036 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1088" />
+ <path
+ d="m 45.253,24.545 c -1.88,3.478 2.838,10.914 6.116,6.956 2.318,-2.479 -3.758,-9.954 -5.637,-6.956 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1090" />
+ <path
+ d="m 45.692,26.944 c 0,-0.52 0.44,-1 0.92,-1 0.52,0 0.92,0.48 0.92,1 0,0.56 -0.4,1 -0.92,1 -0.48,0 -0.92,-0.44 -0.92,-1 z"
+ fill="#ffffff"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1092" />
+ <path
+ d="m 2.878,39.016 c 0.96,0 2.399,0.48 3.358,0.48 0.96,0 1.44,-1.479 2.399,-1.999"
+ fill="none"
+ stroke="#ffffff"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1094" />
+ <path
+ d="m 80.111,31.46 c -1.439,-0.519 -3.358,0 -3.837,2.08 1.919,0.48 3.837,-1.04 5.277,0.48 -0.96,2.078 -2.879,3.078 -4.798,3.078 M 96.981,26.064 c -2.798,-1.519 -7.036,3.038 -1.879,3.518 1.88,0.52 3.278,-1.519 4.238,1 0.44,1.998 -3.278,5.036 -4.238,6.516 M 47.171,20.987 c -0.48,-3.438 5.677,-4.437 2.399,1.96 M 26.944,63.082 c 0,-1 0.96,-3.478 -0.48,-3.478 -1.919,-0.52 -2.878,2.478 -2.399,3.478 m 82.271,86.348 c 0,-2.04 0.48,-4.558 0.959,-6.637 2.319,0.52 2.319,4.118 1.879,6.636 m 71.516,4.917 c -3.717,-6.915 -6.556,0.48 -2.798,2.439 m 83.709,-12.952 c 0.92,-0.48 1.84,-1 2.719,-1.999 m 7.995,67.159 c -0.44,-4.037 -6.556,-4.557 -3.718,0 m 33.86,28.143 c -0.96,-1.04 -1.92,-1.599 -2.879,-1.599 m -5.116,-1.399 c -2.359,-6.116 -6.157,1.56 -2.359,2.039"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1096" />
+ <path
+ d="m 267.638,200.039 c -1.4,1.999 1.399,4.997 0.48,5.996 -1.88,1.999 -3.798,-1 -3.798,-2.478 m -155.146,16.07 c 0,1.479 0.44,2.478 0.44,3.918 -1.4,-0.48 -2.319,-0.96 -3.278,-2.439 m 1.838,4.917 c 0.52,1.52 1,2.518 2,3.518 m 18.868,10.514 c 2.318,6.036 -2.359,2.518 -4.238,-0.52"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1098" />
+ <path
+ clip-path="url(#a)"
+ d="m 135.078,244.092 c -0.44,1.999 0.96,2.519 1.4,3.998 -2.32,0.48 -3.718,-1 -5.597,-1.48"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1100" />
+ <path
+ d="m 121.926,242.573 c 0.48,2.039 1.879,3.038 3.278,3.518"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1102" />
+ </g>
+ </g>
+ <g
+ id="layer2"
+ inkscape:label="Layer 2"
+ clip-path="none"
+ inkscape:groupmode="layer"
+ transform="matrix(0.5,0,0,0.5,0,150)">
+ <circle
+ r="8"
+ cy="-284"
+ cx="34"
+ style="fill:#ffc022;stroke:#b88100;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
+ id="path3319-3" />
+ <circle
+ r="8"
+ cy="-284"
+ cx="66"
+ style="fill:#ad7fa8;stroke:#5c3566;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
+ id="path3319" />
+ <circle
+ r="12"
+ cy="-284"
+ cx="50"
+ style="fill:#ffffff;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
+ id="path3331" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="Layer 3" />
+</svg>
diff --git a/share/extensions/other/clipart/licenses/cc-by.svg b/share/extensions/other/clipart/licenses/cc-by.svg
new file mode 100644
index 0000000..bec1d6c
--- /dev/null
+++ b/share/extensions/other/clipart/licenses/cc-by.svg
@@ -0,0 +1,334 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="50"
+ height="16"
+ viewBox="0 0 50 16"
+ version="1.1"
+ id="svg5"
+ sodipodi:docname="cc-by.svg"
+ inkscape:version="1.2-alpha1 (8b0d57f509, 2022-03-02, custom)"
+ inkscape:export-filename="/home/doctormo/Projects/inkscape/extensions/main/other/clipart/licenses/cc-by-sa.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#999999"
+ borderopacity="1"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="5.8868"
+ inkscape:cx="22.338112"
+ inkscape:cy="24.376571"
+ inkscape:window-width="1472"
+ inkscape:window-height="807"
+ inkscape:window-x="64"
+ inkscape:window-y="20"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer2" />
+ <defs
+ id="defs2">
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect2486"
+ is_visible="true"
+ lpeversion="1"
+ nodesatellites_param=""
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false"
+ satellites_param="" />
+ <color-profile
+ name="AL1706"
+ xlink:href="../../../../../.local/share/icc/edid-a9cf44b399fa09c3fc2589cbaadd3747.icc"
+ id="color-profile496" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="a">
+ <path
+ d="M 0.24,1.04 H 322.045 V 255.205 H 0.24 Z"
+ id="path1048" />
+ </clipPath>
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect2486-3"
+ is_visible="true"
+ lpeversion="1"
+ nodesatellites_param=""
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false"
+ satellites_param="" />
+ </defs>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-51.633091,-21.31349)"
+ sodipodi:insensitive="true"
+ style="display:none">
+ <g
+ inkscape:label="dog.svg"
+ transform="matrix(0.24767307,0,0,0.24767307,51.414234,28.015162)"
+ id="g1104">
+ <path
+ d="m 308.493,99.14 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1058" />
+ <path
+ clip-path="url(#a)"
+ d="m 64.96,104.297 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.929,73.715 47.091,72.716 44.293,69.198 41.935,67.2 35.34,66.2 33.46,66.2 23.586,66.2 16.55,65.68 8.555,57.645 6.676,55.167 5.717,52.128 4.797,48.651 3.358,44.613 1.959,45.612 1.479,39.616 0.999,33.1 1.959,31.581 6.196,30.581 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.996,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.879,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.552 -1.4,6.516 -2.319,17.03 -1.879,23.545 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.359,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.838,25.544 -0.96,3.518 0,4.518 -2.36,8.035 -1.878,2.519 -9.873,3.998 -13.151,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.036 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.518 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.998 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.519 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.919,1.48 -0.919,2.479 -0.48,-0.48 -0.96,-0.48 -1.44,-0.48 -0.439,0.48 -0.439,1 -0.919,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.035,5.476 -7.035,5.476 0,0 -3.279,-2.998 -6.117,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1060" />
+ <path
+ d="m 147.31,59.604 c 16.95,3.038 32.461,6.556 49.85,5.557 21.627,-1.52 42.775,-5.037 64.401,0 -8.434,-2 -18.788,-2 -21.626,8.554 0.48,-3.038 -0.92,-6.036 -3.758,-7.035 -4.198,-2.04 -5.637,1.998 -9.394,2.998 -5.637,1.519 -7.036,-2.519 -12.673,4.517 -3.318,-8.555 -5.197,-1.999 -10.833,-1.48 -2.838,0 -3.758,-2.518 -6.116,-3.037 -4.678,-1 -6.557,3.518 -10.794,3.518 -1.44,0 -1.44,-2.999 -3.318,-2.999 -1.4,-0.52 -2.798,0.48 -4.677,0 -2.359,0 -2.838,-2.038 -5.637,-1.519 -3.797,0.52 -5.676,6.037 -9.434,6.516 -0.92,-6.516 0,-7.515 -5.157,-10.553 z M 47.531,15.39 C 48.011,3.959 77.633,1.96 82.79,7.956 80.471,5.957 74.835,6.437 73.875,9.955 c -2.838,-2.998 -5.636,-1.999 -7.995,0 -2.358,-1.999 -4.677,-0.52 -7.036,-1 z m -32.86,15.032 c 4.238,-2.479 9.394,-2.479 13.632,-3.478 4.717,-1 8.475,-3.478 12.672,-4.997 -2.318,2.518 -5.636,5.996 -9.394,7.995 -5.637,2.958 -10.794,-0.52 -16.43,1.999 z m 105.776,126.883 c 6.596,9.554 10.873,20.067 15.55,30.621 2.839,5.996 5.677,10.993 5.197,18.03 0,8.034 -3.278,16.03 -4.237,23.545 0.96,-3.478 4.237,-12.513 8.955,-11.513 -0.96,-1.52 -2.359,-3.998 -2.359,-5.996 0,-3.039 3.278,-4.518 3.278,-7.036 0,-1.999 -3.278,-5.517 -3.758,-8.035 0,-2.479 0.48,-4.997 0.96,-6.996 -5.197,-1.999 -6.117,-7.516 -3.798,-12.553 -4.237,-0.999 -7.515,-2.998 -9.394,-7.515 -0.96,-1.999 0,-3.998 -1.44,-5.517 -1.399,-2.518 -3.757,-2.998 -5.156,-5.516 z M 264.84,144.353 c 7.995,10.553 19.308,17.549 26.823,28.582 3.758,4.997 7.995,11.513 10.354,17.55 1.4,2.478 3.278,5.996 3.278,8.994 0.48,3.518 -1.879,7.036 -1.4,10.514 1.88,-2 3.759,-6.476 3.759,-8.995 0.44,-3.518 -2.359,-3.518 -3.318,-7.515 -0.92,-3.518 0.959,-5.517 -0.44,-8.035 -0.48,-1.48 -2.838,-2.479 -3.758,-3.998 0,-1 -0.48,-3.518 -0.96,-3.998 -1.398,-2.518 -5.636,-2.518 -7.035,-5.516 -1.879,-5.517 1.879,-5.517 -3.318,-8.515 -4.677,-2.998 -14.551,-8.035 -15.99,-14.551 z m 10.353,30.541 c -0.44,2.518 -2.358,6.556 -1.399,9.554 0.48,1 2.359,0 2.359,0.52 0.48,1 0.92,2.518 1.399,3.518 1.439,4.517 -0.92,13.072 -6.596,12.072 2.358,-0.52 4.717,0.48 5.676,2.479 0,-3.998 1.4,-7.036 4.678,-8.515 -1.88,-3.038 -1.88,-6.036 -2.32,-9.074 -0.479,-3.998 -0.959,-6.516 -1.918,-10.034 -0.44,-3.518 0.48,-4.518 -1.879,-7.036 -1.879,-2.039 -3.758,-1 -6.596,-2.039 1.92,2.519 6.156,3.518 5.677,7.076 z m -149.469,19.068 c -3.798,4.997 -1.919,11.034 -2.359,17.03 0,1.999 -0.48,6.036 -1.879,7.516 -1.918,1.998 -4.237,1.519 -6.156,2.998 2.838,-2.479 7.076,-2.479 10.394,-1.48 -1.44,-4.517 -3.318,-9.034 2.318,-10.033 -2.318,-3.518 -1.399,-4.997 -1.399,-8.515 -0.48,-2.998 -1.879,-6.996 -0.92,-10.034 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1062" />
+ <path
+ d="m 117.649,122.206 c 0.96,-2.998 -0.92,-6.516 -0.44,-9.514 0.44,-3.998 1.879,-5.517 4.197,-8.515 -6.076,-2.519 -4.677,-6.036 -4.197,-11.553 0.44,-4.997 -2.359,-5.517 -4.717,-10.034 -2.838,-6.516 -2.838,-17.03 -3.278,-24.065 0,-7.996 -2.838,-14.032 -8.955,-19.029 -2.798,-2.518 -7.035,-7.036 -10.793,-7.036 -5.677,-0.52 -9.435,6.037 -11.313,11.034 -1.4,4.997 -4.238,17.549 -3.278,23.066 l 9.874,48.13 1.878,1.52 c 4.238,3.477 1.88,5.516 -0.48,7.515 0.48,1 0.96,1.48 1.88,1.999 h 1.879 c 1.439,0 2.838,0 3.757,0.52 0.48,0 1.44,0.48 2.359,0.48 0,3.517 -2.359,7.035 -1.88,10.513 2.84,-0.48 5.638,-1 7.077,-3.998 -0.96,2.998 -1.44,7.036 -1.44,9.514 1.44,-1.998 2.36,-4.996 2.839,-5.996 3.278,-6.036 13.632,-8.515 15.03,-14.551 z m 3.318,47.771 c 2.798,5.996 3.717,13.032 6.076,19.028 2.798,6.037 4.197,10.554 4.197,17.55 0.48,5.037 -0.48,13.072 -3.757,17.07 -3.238,3.997 -8.875,6.036 -12.633,9.514 6.117,-5.997 13.592,1 17.79,-6.996 3.757,-7.036 4.197,-14.551 4.197,-22.067 0,-8.554 -4.677,-10.553 -7.475,-17.549 -2.799,-6.036 -4.678,-14.551 -9.834,-18.589 z m 46.931,20.388 c 1.4,4.037 4.198,18.069 -2.358,16.55 0,3.517 0.92,6.516 -0.48,10.034 -1.4,-2 -2.838,-6.037 -5.157,-2.519 1.879,1.999 0,1.999 0,3.518 0.44,1.999 0.44,3.997 0.92,5.996 -6.117,1 -7.516,6.516 -10.794,11.034 -3.798,4.517 -8.954,7.515 -9.434,14.51 1.439,-4.996 -0.48,-11.512 2.838,-15.51 0,0.48 2.798,0 3.758,-1 1.879,-1.518 1.399,-3.997 2.358,-6.036 2.359,-4.997 2.799,-2.478 6.117,-5.996 3.278,-3.518 0.92,-7.036 0,-11.513 4.237,2.479 3.757,-4.037 2.798,-6.516 4.717,0 6.596,-1 6.116,-5.517 -0.48,-2.518 -2.358,-8.514 -3.278,-10.513 2.799,1.999 5.637,0.48 7.516,-1.04 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1064" />
+ <path
+ d="m 166.06,187.846 c -0.48,-1.959 -1.4,-5.477 -0.48,-7.435 0.96,-2.519 3.318,-2.999 3.757,-4.997 0.96,-3.478 -3.278,-6.476 1.88,-8.475 -2.32,0 -4.678,1.999 -6.557,-1 1.4,5.997 -4.717,8.995 -1.879,14.472 z m 11.752,-26.544 c -0.96,4.997 -3.318,12.992 3.278,14.991 3.318,1 11.753,-9.474 13.192,-2.998 2.359,-3.998 5.157,-3.478 8.915,-4.477 1.439,-0.52 1.879,-2.999 3.798,-2.519 1.878,0.52 2.798,3.518 2.798,4.997 0.96,-1.999 3.318,-7.515 5.636,-8.515 5.197,-1.479 4.238,3.038 5.677,6.037 1.4,-2 1.879,-5.517 4.237,-5.517 2.799,-0.52 4.198,2.998 4.678,4.997 1.878,-1.999 1.878,-8.515 4.717,-8.515 2.358,-0.48 3.757,2.998 3.278,5.037 2.838,-3.038 -0.48,-9.514 3.318,-11.513 0.92,1.48 1.399,3.478 1.399,4.477 1.399,-4.997 0.92,-7.475 6.596,-6.995 4.677,0 6.116,0.999 7.036,5.996 5.636,-4.997 6.596,4.997 6.596,8.515 3.757,-4.517 5.156,-8.995 2.358,-13.992 -2.838,-4.517 -4.717,-9.514 -6.116,-15.03 -1.4,1.998 -3.758,7.995 -6.116,7.995 -3.318,0 -4.238,-7.476 -5.197,-9.515 -1.4,2.04 -3.278,10.034 -5.637,10.514 -4.237,1.519 -6.596,-4.477 -7.995,-7.476 -1.879,2.999 -1.4,9.475 -4.717,11.993 -4.677,3.998 -4.198,-1.519 -8.435,-2.998 -1.879,7.515 -2.359,10.993 -9.914,12.512 -1.879,0 -1.879,0 -3.758,0.48 -1.879,0.52 -3.757,1.999 -5.636,2.519 -9.395,3.997 -19.269,1.479 -21.627,-9.515 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1066" />
+ <path
+ d="m 263.84,161.782 c 4.238,-4.477 13.192,3.518 16.03,6.516 4.238,4.038 5.677,8.555 5.197,14.031 0,5.517 -0.48,14.552 -3.318,19.549 -0.92,1.998 -3.757,5.037 -6.116,6.516 -2.359,1.519 -6.156,1.519 -7.076,3.997 6.117,-1.479 14.631,-1 16.99,-7.995 2.359,-7.515 2.359,-16.03 2.838,-23.546 0.44,-8.035 -3.797,-11.513 -9.914,-16.03 -2.838,-2.518 -10.873,-12.552 -13.711,-15.03 -2.799,-3.039 -0.44,1.998 -5.197,1.478 z m 48.93,57.645 c 0.92,5.517 5.157,13.552 1.88,18.549 -1.88,3.038 -15.112,7.515 -13.193,0 5.157,1 5.637,-3.998 7.516,-7.516 2.838,-4.997 2.838,-3.518 1.919,-9.034 -0.96,-8.515 3.757,-17.03 2.798,-25.585 z M 292.583,79.112 c 3.757,7.036 10.353,8.555 10.793,18.07 0.96,7.035 -0.44,15.07 1.879,22.066 1.4,6.036 4.717,11.073 7.036,16.59 0.96,1.479 4.237,5.996 4.237,7.515 0.44,2.998 -2.358,4.517 -1.879,9.035 -6.116,-0.52 -1.399,5.516 -0.48,8.514 -2.358,-2.478 -7.035,-4.996 -7.955,-8.514 7.956,-2.519 2.799,-11.034 -1.439,-14.032 5.197,-9.034 -3.278,-12.073 -7.955,-17.59 3.758,-4.516 1.879,-8.034 -1.879,-11.552 5.157,-5.997 4.238,-26.584 -2.358,-31.621 z M 39.536,63.601 c 3.318,1.52 5.197,1.52 7.555,5.037 1.88,2.479 2.359,5.477 4.238,7.996 1.399,1.998 3.278,3.997 4.717,6.476 1.4,1.519 4.677,5.996 6.596,7.995 0.92,-5.997 -2.838,-9.474 -2.359,-14.991 0.44,-3.998 2.359,-8.475 3.758,-11.993 1.879,-4.997 3.278,-8.515 6.116,-11.993 3.278,-3.517 7.516,-7.995 6.596,-14.031 -1.399,6.516 -7.075,15.51 -14.59,12.512 -2.839,5.997 -4.238,7.516 -10.354,7.516 2.798,2.478 5.636,6.996 4.237,11.513 -1.879,-1.999 -5.197,-4.517 -7.555,-5.037 -3.278,-0.48 -5.637,1.519 -8.955,-1.999 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1068" />
+ <path
+ d="m 111.053,226.023 c -1.84,0.52 -3.278,2.998 -3.278,3.998 m 153.267,-88.747 c 1.439,7.556 13.672,16.07 17.909,22.067 3.318,4.517 10.833,9.035 12.233,15.03 M 121.446,164.94 c 2.839,4.517 5.197,10.514 7.076,15.03 0.92,2.52 1.4,4.998 2.359,7.516 1.399,2.519 2.798,2.999 4.677,5.517 5.157,6.996 0.48,27.503 -2.798,35.538 -0.48,1.48 -0.96,2.999 -1.88,3.478 M 52.288,6.396 c -3.278,1.52 -7.955,7.076 -9.354,10.594 -1.879,3.518 -6.076,3.997 -7.515,4.997 m 100.019,222.585 c -1.839,0.52 -2.319,3.038 -3.278,4.557 m -1.839,-7.995 c -3.278,0 -7.036,1.519 -7.995,4.957 m -11.673,-25.505 c -1.879,1 -4.237,1 -6.156,2.959 m 168.378,-16.55 c -2.319,0.52 -5.597,1.519 -6.077,3.997 m 2.799,-9.514 c -1.92,0 -3.838,1.04 -5.277,2.558 m 38.137,30.542 c -1.88,2.039 -3.758,4.037 -3.758,6.556 m -3.278,-9.594 c -1.839,1.559 -4.637,2.558 -5.117,5.596 m 21.986,-3.997 c -0.919,1.519 -1.358,2.518 -1.838,3.997 M 181.17,151.828 c -1.399,0.52 -4.717,4.038 -6.116,5.037 2.358,2.518 0.96,10.554 -2.838,11.553 0.48,2.039 -0.48,2.518 0.48,4.517 m -52.169,-7.595 c 0.92,-4.477 -5.197,-3.998 -7.076,-6.516 1.44,-1.48 3.318,-3.478 1.88,-5.477 -1.88,0.48 -3.759,0 -5.158,-1.519 1.4,-1.999 2.359,-4.997 0.48,-7.036 -1.919,1.52 -3.798,1.04 -6.156,0.52 M 11.473,32.94 c 0.44,7.076 -3.358,11.593 -8.595,9.075"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1070" />
+ <path
+ d="m 9.514,39.976 c 0.96,-1 2.359,-6.476 1.44,-7.955 -0.96,-1.52 -4.718,-1.52 -6.637,-1 -2.358,1 -3.318,2.998 -2.838,8.475 0,1.999 0.48,2.998 0.48,3.958 l 1.439,-0.96 c 2.359,0 4.717,0 6.116,-2.518 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1072" />
+ <path
+ d="m 55.566,32.54 c -2.798,-1.479 -4.197,-5.996 -7.035,-7.995 -2.799,-1.999 -2.799,0.52 -4.718,3.518"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1074" />
+ <path
+ d="M 52.848,29.102 C 49.09,38.137 42.454,27.104 45.772,25.584 m 11.233,0.96 C 55.606,22.067 50.01,18.549 46.692,19.548 m -33.98,39.136 c 3.318,-1.998 4.278,0.96 6.636,2.439 3.318,1.959 6.157,-0.48 8.955,0.52"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1076" />
+ <path
+ clip-path="url(#a)"
+ d="m 65,104.337 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.969,73.755 47.131,72.756 44.333,69.238 41.975,67.239 35.379,66.24 33.5,66.24 23.626,66.24 16.59,65.72 8.595,57.685 6.715,55.207 5.757,52.168 4.837,48.69 3.397,44.653 2,45.652 1.52,39.656 1.04,33.14 2,31.621 6.237,30.621 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.995,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.88,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.551 -1.4,6.517 -2.319,17.03 -1.879,23.546 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.36,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.839,25.544 -0.959,3.518 0,4.518 -2.358,8.035 -1.879,2.519 -9.874,3.998 -13.152,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.037 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.517 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.999 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.518 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.92,1.48 -0.92,2.479 -0.479,-0.48 -0.958,-0.48 -1.438,-0.48 -0.44,0.48 -0.44,1 -0.92,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.036,5.476 -7.036,5.476 0,0 -3.278,-2.998 -6.116,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1078" />
+ <path
+ d="m 308.533,99.18 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 v 0.52 c 0,0 0,0 0,0 v 1.519"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1080" />
+ <path
+ d="m 95.102,24.905 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.551 0,3.038 0,5.517 0.48,8.555 0.48,3.518 0,7.036 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.92,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.196,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.076,-1.519 -1.88,1.52 -0.92,3.998 -0.44,6.036 -1.44,0 -2.839,-0.52 -3.798,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.514,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.96,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1082" />
+ <path
+ d="m 81.91,41.055 c -1.399,4.038 -3.278,8.035 -5.596,11.033 -1.88,2.519 -4.238,5.037 -5.157,7.516 -0.48,1.519 0,3.038 -0.48,4.517 -0.44,1.52 -2.318,2.998 -2.798,4.517 -0.48,1 -0.48,2.519 -0.48,3.518 -0.44,1.48 -1.879,2.519 -1.879,3.998 0,1.519 1.44,2.998 1.44,4.517 0.44,1.52 0.44,2.998 0.44,4.517 0,3.518 -0.92,6.996 -0.44,10.034 0,2 0.919,3.478 0.919,5.517 0,1.999 -0.92,3.478 -0.48,5.477 0.48,1.519 0.96,2.038 1.4,3.517 0.959,1.52 0,3.518 0.479,5.037 3.278,-0.999 2.798,2.479 3.278,4.478 0.96,-2 3.758,-2.479 5.637,-2 -0.96,-0.479 -3.758,-0.998 -4.678,-1.478 -1.878,-1.52 0,-6.037 1.4,-7.516 -1.4,0 -4.238,-0.52 -4.678,-2.038 -0.959,-2 3.278,-4.478 3.718,-5.997 -1.879,-0.52 -3.278,-1 -3.718,-2.998 -1.439,-3.518 1.4,-5.037 1.84,-8.035 0,-1.999 -1.4,-1.48 -2.32,-3.518 -0.959,-1.999 0,-4.477 1.88,-5.996 -2.359,-3.518 -2.839,-5.517 -0.48,-9.035 0.92,-1.479 0.92,-0.48 0.92,-1.999 0.479,-1.998 -1.4,-3.517 0.959,-5.516 0.92,-1 1.879,-0.48 2.318,-1.999 0.48,-1 0,-3.998 0.96,-5.517 0.48,-1.998 0.92,-4.517 1.879,-6.995 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1084" />
+ <path
+ d="m 95.142,24.945 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.55 0,3.04 0,5.518 0.48,8.556 0.48,3.518 0,7.035 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.919,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.197,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.077,-1.519 -1.878,1.52 -0.919,3.998 -0.44,6.036 -1.438,0 -2.838,-0.52 -3.797,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.515,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.959,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1086" />
+ <path
+ d="m 103.058,54.087 c -0.48,2.998 0,5.997 0,9.035 v 9.994 c 0.44,6.556 1.399,13.551 3.278,19.588 0.48,1 0.959,1.999 1.399,3.478 0,1.519 0,1 -0.44,2.518 -0.48,1.999 -0.96,2.998 -0.96,5.037 0.48,1.999 0.96,2.998 0.96,4.477 -0.48,0.52 -1.44,1.52 -1.44,2.519 -0.439,1 0,2.518 -0.439,2.998 -0.48,1 -1.919,1 -2.838,2.039 -0.48,1.479 0,2.998 -0.96,4.477 -1.399,-1 -2.798,0.52 -3.757,1 -0.92,-1 -1.88,-1.48 -2.839,-1 0.96,-1 3.798,-2.478 4.718,-3.478 0.959,-2.039 0,-4.517 -0.92,-7.036 2.359,0 3.278,-2.518 3.278,-4.996 0,-2.04 -0.92,-2.04 -1.879,-3.518 -0.96,-2.519 1.4,-4.038 1.88,-6.516 0.959,-4.038 -0.92,-5.517 -2.84,-8.036 4.238,-4.517 1.92,-8.035 0.48,-12.512 -0.919,-3.038 0.96,-5.517 0.48,-9.034 0,-2.999 1.4,-6.037 1.4,-9.035 0.48,-1.999 0.959,-4.997 0.48,-7.036 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1088" />
+ <path
+ d="m 45.253,24.545 c -1.88,3.478 2.838,10.914 6.116,6.956 2.318,-2.479 -3.758,-9.954 -5.637,-6.956 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1090" />
+ <path
+ d="m 45.692,26.944 c 0,-0.52 0.44,-1 0.92,-1 0.52,0 0.92,0.48 0.92,1 0,0.56 -0.4,1 -0.92,1 -0.48,0 -0.92,-0.44 -0.92,-1 z"
+ fill="#ffffff"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1092" />
+ <path
+ d="m 2.878,39.016 c 0.96,0 2.399,0.48 3.358,0.48 0.96,0 1.44,-1.479 2.399,-1.999"
+ fill="none"
+ stroke="#ffffff"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1094" />
+ <path
+ d="m 80.111,31.46 c -1.439,-0.519 -3.358,0 -3.837,2.08 1.919,0.48 3.837,-1.04 5.277,0.48 -0.96,2.078 -2.879,3.078 -4.798,3.078 M 96.981,26.064 c -2.798,-1.519 -7.036,3.038 -1.879,3.518 1.88,0.52 3.278,-1.519 4.238,1 0.44,1.998 -3.278,5.036 -4.238,6.516 M 47.171,20.987 c -0.48,-3.438 5.677,-4.437 2.399,1.96 M 26.944,63.082 c 0,-1 0.96,-3.478 -0.48,-3.478 -1.919,-0.52 -2.878,2.478 -2.399,3.478 m 82.271,86.348 c 0,-2.04 0.48,-4.558 0.959,-6.637 2.319,0.52 2.319,4.118 1.879,6.636 m 71.516,4.917 c -3.717,-6.915 -6.556,0.48 -2.798,2.439 m 83.709,-12.952 c 0.92,-0.48 1.84,-1 2.719,-1.999 m 7.995,67.159 c -0.44,-4.037 -6.556,-4.557 -3.718,0 m 33.86,28.143 c -0.96,-1.04 -1.92,-1.599 -2.879,-1.599 m -5.116,-1.399 c -2.359,-6.116 -6.157,1.56 -2.359,2.039"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1096" />
+ <path
+ d="m 267.638,200.039 c -1.4,1.999 1.399,4.997 0.48,5.996 -1.88,1.999 -3.798,-1 -3.798,-2.478 m -155.146,16.07 c 0,1.479 0.44,2.478 0.44,3.918 -1.4,-0.48 -2.319,-0.96 -3.278,-2.439 m 1.838,4.917 c 0.52,1.52 1,2.518 2,3.518 m 18.868,10.514 c 2.318,6.036 -2.359,2.518 -4.238,-0.52"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1098" />
+ <path
+ clip-path="url(#a)"
+ d="m 135.078,244.092 c -0.44,1.999 0.96,2.519 1.4,3.998 -2.32,0.48 -3.718,-1 -5.597,-1.48"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1100" />
+ <path
+ d="m 121.926,242.573 c 0.48,2.039 1.879,3.038 3.278,3.518"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1102" />
+ </g>
+ </g>
+ <g
+ id="layer2"
+ inkscape:label="Layer 2"
+ clip-path="none"
+ inkscape:groupmode="layer"
+ transform="matrix(0.5,0,0,0.5,0,150)">
+ <circle
+ r="8"
+ cy="-284"
+ cx="34"
+ style="fill:#ffc022;stroke:#b88100;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
+ id="path3319-3" />
+ <circle
+ r="12"
+ cy="-284"
+ cx="50"
+ style="fill:#ffffff;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
+ id="path3331" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="Layer 3" />
+</svg>
diff --git a/share/extensions/other/clipart/licenses/cc0.svg b/share/extensions/other/clipart/licenses/cc0.svg
new file mode 100644
index 0000000..a0fafc4
--- /dev/null
+++ b/share/extensions/other/clipart/licenses/cc0.svg
@@ -0,0 +1,334 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="50"
+ height="16"
+ viewBox="0 0 50 16"
+ version="1.1"
+ id="svg5"
+ sodipodi:docname="cc0.svg"
+ inkscape:version="1.2-alpha1 (8b0d57f509, 2022-03-02, custom)"
+ inkscape:export-filename="/home/doctormo/Projects/inkscape/extensions/main/other/clipart/licenses/cc-by-sa.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#999999"
+ borderopacity="1"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="2.9434"
+ inkscape:cx="12.060882"
+ inkscape:cy="27.009581"
+ inkscape:window-width="1472"
+ inkscape:window-height="807"
+ inkscape:window-x="64"
+ inkscape:window-y="20"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer2" />
+ <defs
+ id="defs2">
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect2486"
+ is_visible="true"
+ lpeversion="1"
+ nodesatellites_param=""
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false"
+ satellites_param="" />
+ <color-profile
+ name="AL1706"
+ xlink:href="../../../../../.local/share/icc/edid-a9cf44b399fa09c3fc2589cbaadd3747.icc"
+ id="color-profile855" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="a">
+ <path
+ d="M 0.24,1.04 H 322.045 V 255.205 H 0.24 Z"
+ id="path1048" />
+ </clipPath>
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect2486-3"
+ is_visible="true"
+ lpeversion="1"
+ nodesatellites_param=""
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false"
+ satellites_param="" />
+ </defs>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-51.633091,-21.31349)"
+ sodipodi:insensitive="true"
+ style="display:none">
+ <g
+ inkscape:label="dog.svg"
+ transform="matrix(0.24767307,0,0,0.24767307,51.414234,28.015162)"
+ id="g1104">
+ <path
+ d="m 308.493,99.14 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1058" />
+ <path
+ clip-path="url(#a)"
+ d="m 64.96,104.297 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.929,73.715 47.091,72.716 44.293,69.198 41.935,67.2 35.34,66.2 33.46,66.2 23.586,66.2 16.55,65.68 8.555,57.645 6.676,55.167 5.717,52.128 4.797,48.651 3.358,44.613 1.959,45.612 1.479,39.616 0.999,33.1 1.959,31.581 6.196,30.581 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.996,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.879,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.552 -1.4,6.516 -2.319,17.03 -1.879,23.545 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.359,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.838,25.544 -0.96,3.518 0,4.518 -2.36,8.035 -1.878,2.519 -9.873,3.998 -13.151,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.036 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.518 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.998 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.519 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.919,1.48 -0.919,2.479 -0.48,-0.48 -0.96,-0.48 -1.44,-0.48 -0.439,0.48 -0.439,1 -0.919,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.035,5.476 -7.035,5.476 0,0 -3.279,-2.998 -6.117,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1060" />
+ <path
+ d="m 147.31,59.604 c 16.95,3.038 32.461,6.556 49.85,5.557 21.627,-1.52 42.775,-5.037 64.401,0 -8.434,-2 -18.788,-2 -21.626,8.554 0.48,-3.038 -0.92,-6.036 -3.758,-7.035 -4.198,-2.04 -5.637,1.998 -9.394,2.998 -5.637,1.519 -7.036,-2.519 -12.673,4.517 -3.318,-8.555 -5.197,-1.999 -10.833,-1.48 -2.838,0 -3.758,-2.518 -6.116,-3.037 -4.678,-1 -6.557,3.518 -10.794,3.518 -1.44,0 -1.44,-2.999 -3.318,-2.999 -1.4,-0.52 -2.798,0.48 -4.677,0 -2.359,0 -2.838,-2.038 -5.637,-1.519 -3.797,0.52 -5.676,6.037 -9.434,6.516 -0.92,-6.516 0,-7.515 -5.157,-10.553 z M 47.531,15.39 C 48.011,3.959 77.633,1.96 82.79,7.956 80.471,5.957 74.835,6.437 73.875,9.955 c -2.838,-2.998 -5.636,-1.999 -7.995,0 -2.358,-1.999 -4.677,-0.52 -7.036,-1 z m -32.86,15.032 c 4.238,-2.479 9.394,-2.479 13.632,-3.478 4.717,-1 8.475,-3.478 12.672,-4.997 -2.318,2.518 -5.636,5.996 -9.394,7.995 -5.637,2.958 -10.794,-0.52 -16.43,1.999 z m 105.776,126.883 c 6.596,9.554 10.873,20.067 15.55,30.621 2.839,5.996 5.677,10.993 5.197,18.03 0,8.034 -3.278,16.03 -4.237,23.545 0.96,-3.478 4.237,-12.513 8.955,-11.513 -0.96,-1.52 -2.359,-3.998 -2.359,-5.996 0,-3.039 3.278,-4.518 3.278,-7.036 0,-1.999 -3.278,-5.517 -3.758,-8.035 0,-2.479 0.48,-4.997 0.96,-6.996 -5.197,-1.999 -6.117,-7.516 -3.798,-12.553 -4.237,-0.999 -7.515,-2.998 -9.394,-7.515 -0.96,-1.999 0,-3.998 -1.44,-5.517 -1.399,-2.518 -3.757,-2.998 -5.156,-5.516 z M 264.84,144.353 c 7.995,10.553 19.308,17.549 26.823,28.582 3.758,4.997 7.995,11.513 10.354,17.55 1.4,2.478 3.278,5.996 3.278,8.994 0.48,3.518 -1.879,7.036 -1.4,10.514 1.88,-2 3.759,-6.476 3.759,-8.995 0.44,-3.518 -2.359,-3.518 -3.318,-7.515 -0.92,-3.518 0.959,-5.517 -0.44,-8.035 -0.48,-1.48 -2.838,-2.479 -3.758,-3.998 0,-1 -0.48,-3.518 -0.96,-3.998 -1.398,-2.518 -5.636,-2.518 -7.035,-5.516 -1.879,-5.517 1.879,-5.517 -3.318,-8.515 -4.677,-2.998 -14.551,-8.035 -15.99,-14.551 z m 10.353,30.541 c -0.44,2.518 -2.358,6.556 -1.399,9.554 0.48,1 2.359,0 2.359,0.52 0.48,1 0.92,2.518 1.399,3.518 1.439,4.517 -0.92,13.072 -6.596,12.072 2.358,-0.52 4.717,0.48 5.676,2.479 0,-3.998 1.4,-7.036 4.678,-8.515 -1.88,-3.038 -1.88,-6.036 -2.32,-9.074 -0.479,-3.998 -0.959,-6.516 -1.918,-10.034 -0.44,-3.518 0.48,-4.518 -1.879,-7.036 -1.879,-2.039 -3.758,-1 -6.596,-2.039 1.92,2.519 6.156,3.518 5.677,7.076 z m -149.469,19.068 c -3.798,4.997 -1.919,11.034 -2.359,17.03 0,1.999 -0.48,6.036 -1.879,7.516 -1.918,1.998 -4.237,1.519 -6.156,2.998 2.838,-2.479 7.076,-2.479 10.394,-1.48 -1.44,-4.517 -3.318,-9.034 2.318,-10.033 -2.318,-3.518 -1.399,-4.997 -1.399,-8.515 -0.48,-2.998 -1.879,-6.996 -0.92,-10.034 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1062" />
+ <path
+ d="m 117.649,122.206 c 0.96,-2.998 -0.92,-6.516 -0.44,-9.514 0.44,-3.998 1.879,-5.517 4.197,-8.515 -6.076,-2.519 -4.677,-6.036 -4.197,-11.553 0.44,-4.997 -2.359,-5.517 -4.717,-10.034 -2.838,-6.516 -2.838,-17.03 -3.278,-24.065 0,-7.996 -2.838,-14.032 -8.955,-19.029 -2.798,-2.518 -7.035,-7.036 -10.793,-7.036 -5.677,-0.52 -9.435,6.037 -11.313,11.034 -1.4,4.997 -4.238,17.549 -3.278,23.066 l 9.874,48.13 1.878,1.52 c 4.238,3.477 1.88,5.516 -0.48,7.515 0.48,1 0.96,1.48 1.88,1.999 h 1.879 c 1.439,0 2.838,0 3.757,0.52 0.48,0 1.44,0.48 2.359,0.48 0,3.517 -2.359,7.035 -1.88,10.513 2.84,-0.48 5.638,-1 7.077,-3.998 -0.96,2.998 -1.44,7.036 -1.44,9.514 1.44,-1.998 2.36,-4.996 2.839,-5.996 3.278,-6.036 13.632,-8.515 15.03,-14.551 z m 3.318,47.771 c 2.798,5.996 3.717,13.032 6.076,19.028 2.798,6.037 4.197,10.554 4.197,17.55 0.48,5.037 -0.48,13.072 -3.757,17.07 -3.238,3.997 -8.875,6.036 -12.633,9.514 6.117,-5.997 13.592,1 17.79,-6.996 3.757,-7.036 4.197,-14.551 4.197,-22.067 0,-8.554 -4.677,-10.553 -7.475,-17.549 -2.799,-6.036 -4.678,-14.551 -9.834,-18.589 z m 46.931,20.388 c 1.4,4.037 4.198,18.069 -2.358,16.55 0,3.517 0.92,6.516 -0.48,10.034 -1.4,-2 -2.838,-6.037 -5.157,-2.519 1.879,1.999 0,1.999 0,3.518 0.44,1.999 0.44,3.997 0.92,5.996 -6.117,1 -7.516,6.516 -10.794,11.034 -3.798,4.517 -8.954,7.515 -9.434,14.51 1.439,-4.996 -0.48,-11.512 2.838,-15.51 0,0.48 2.798,0 3.758,-1 1.879,-1.518 1.399,-3.997 2.358,-6.036 2.359,-4.997 2.799,-2.478 6.117,-5.996 3.278,-3.518 0.92,-7.036 0,-11.513 4.237,2.479 3.757,-4.037 2.798,-6.516 4.717,0 6.596,-1 6.116,-5.517 -0.48,-2.518 -2.358,-8.514 -3.278,-10.513 2.799,1.999 5.637,0.48 7.516,-1.04 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1064" />
+ <path
+ d="m 166.06,187.846 c -0.48,-1.959 -1.4,-5.477 -0.48,-7.435 0.96,-2.519 3.318,-2.999 3.757,-4.997 0.96,-3.478 -3.278,-6.476 1.88,-8.475 -2.32,0 -4.678,1.999 -6.557,-1 1.4,5.997 -4.717,8.995 -1.879,14.472 z m 11.752,-26.544 c -0.96,4.997 -3.318,12.992 3.278,14.991 3.318,1 11.753,-9.474 13.192,-2.998 2.359,-3.998 5.157,-3.478 8.915,-4.477 1.439,-0.52 1.879,-2.999 3.798,-2.519 1.878,0.52 2.798,3.518 2.798,4.997 0.96,-1.999 3.318,-7.515 5.636,-8.515 5.197,-1.479 4.238,3.038 5.677,6.037 1.4,-2 1.879,-5.517 4.237,-5.517 2.799,-0.52 4.198,2.998 4.678,4.997 1.878,-1.999 1.878,-8.515 4.717,-8.515 2.358,-0.48 3.757,2.998 3.278,5.037 2.838,-3.038 -0.48,-9.514 3.318,-11.513 0.92,1.48 1.399,3.478 1.399,4.477 1.399,-4.997 0.92,-7.475 6.596,-6.995 4.677,0 6.116,0.999 7.036,5.996 5.636,-4.997 6.596,4.997 6.596,8.515 3.757,-4.517 5.156,-8.995 2.358,-13.992 -2.838,-4.517 -4.717,-9.514 -6.116,-15.03 -1.4,1.998 -3.758,7.995 -6.116,7.995 -3.318,0 -4.238,-7.476 -5.197,-9.515 -1.4,2.04 -3.278,10.034 -5.637,10.514 -4.237,1.519 -6.596,-4.477 -7.995,-7.476 -1.879,2.999 -1.4,9.475 -4.717,11.993 -4.677,3.998 -4.198,-1.519 -8.435,-2.998 -1.879,7.515 -2.359,10.993 -9.914,12.512 -1.879,0 -1.879,0 -3.758,0.48 -1.879,0.52 -3.757,1.999 -5.636,2.519 -9.395,3.997 -19.269,1.479 -21.627,-9.515 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1066" />
+ <path
+ d="m 263.84,161.782 c 4.238,-4.477 13.192,3.518 16.03,6.516 4.238,4.038 5.677,8.555 5.197,14.031 0,5.517 -0.48,14.552 -3.318,19.549 -0.92,1.998 -3.757,5.037 -6.116,6.516 -2.359,1.519 -6.156,1.519 -7.076,3.997 6.117,-1.479 14.631,-1 16.99,-7.995 2.359,-7.515 2.359,-16.03 2.838,-23.546 0.44,-8.035 -3.797,-11.513 -9.914,-16.03 -2.838,-2.518 -10.873,-12.552 -13.711,-15.03 -2.799,-3.039 -0.44,1.998 -5.197,1.478 z m 48.93,57.645 c 0.92,5.517 5.157,13.552 1.88,18.549 -1.88,3.038 -15.112,7.515 -13.193,0 5.157,1 5.637,-3.998 7.516,-7.516 2.838,-4.997 2.838,-3.518 1.919,-9.034 -0.96,-8.515 3.757,-17.03 2.798,-25.585 z M 292.583,79.112 c 3.757,7.036 10.353,8.555 10.793,18.07 0.96,7.035 -0.44,15.07 1.879,22.066 1.4,6.036 4.717,11.073 7.036,16.59 0.96,1.479 4.237,5.996 4.237,7.515 0.44,2.998 -2.358,4.517 -1.879,9.035 -6.116,-0.52 -1.399,5.516 -0.48,8.514 -2.358,-2.478 -7.035,-4.996 -7.955,-8.514 7.956,-2.519 2.799,-11.034 -1.439,-14.032 5.197,-9.034 -3.278,-12.073 -7.955,-17.59 3.758,-4.516 1.879,-8.034 -1.879,-11.552 5.157,-5.997 4.238,-26.584 -2.358,-31.621 z M 39.536,63.601 c 3.318,1.52 5.197,1.52 7.555,5.037 1.88,2.479 2.359,5.477 4.238,7.996 1.399,1.998 3.278,3.997 4.717,6.476 1.4,1.519 4.677,5.996 6.596,7.995 0.92,-5.997 -2.838,-9.474 -2.359,-14.991 0.44,-3.998 2.359,-8.475 3.758,-11.993 1.879,-4.997 3.278,-8.515 6.116,-11.993 3.278,-3.517 7.516,-7.995 6.596,-14.031 -1.399,6.516 -7.075,15.51 -14.59,12.512 -2.839,5.997 -4.238,7.516 -10.354,7.516 2.798,2.478 5.636,6.996 4.237,11.513 -1.879,-1.999 -5.197,-4.517 -7.555,-5.037 -3.278,-0.48 -5.637,1.519 -8.955,-1.999 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1068" />
+ <path
+ d="m 111.053,226.023 c -1.84,0.52 -3.278,2.998 -3.278,3.998 m 153.267,-88.747 c 1.439,7.556 13.672,16.07 17.909,22.067 3.318,4.517 10.833,9.035 12.233,15.03 M 121.446,164.94 c 2.839,4.517 5.197,10.514 7.076,15.03 0.92,2.52 1.4,4.998 2.359,7.516 1.399,2.519 2.798,2.999 4.677,5.517 5.157,6.996 0.48,27.503 -2.798,35.538 -0.48,1.48 -0.96,2.999 -1.88,3.478 M 52.288,6.396 c -3.278,1.52 -7.955,7.076 -9.354,10.594 -1.879,3.518 -6.076,3.997 -7.515,4.997 m 100.019,222.585 c -1.839,0.52 -2.319,3.038 -3.278,4.557 m -1.839,-7.995 c -3.278,0 -7.036,1.519 -7.995,4.957 m -11.673,-25.505 c -1.879,1 -4.237,1 -6.156,2.959 m 168.378,-16.55 c -2.319,0.52 -5.597,1.519 -6.077,3.997 m 2.799,-9.514 c -1.92,0 -3.838,1.04 -5.277,2.558 m 38.137,30.542 c -1.88,2.039 -3.758,4.037 -3.758,6.556 m -3.278,-9.594 c -1.839,1.559 -4.637,2.558 -5.117,5.596 m 21.986,-3.997 c -0.919,1.519 -1.358,2.518 -1.838,3.997 M 181.17,151.828 c -1.399,0.52 -4.717,4.038 -6.116,5.037 2.358,2.518 0.96,10.554 -2.838,11.553 0.48,2.039 -0.48,2.518 0.48,4.517 m -52.169,-7.595 c 0.92,-4.477 -5.197,-3.998 -7.076,-6.516 1.44,-1.48 3.318,-3.478 1.88,-5.477 -1.88,0.48 -3.759,0 -5.158,-1.519 1.4,-1.999 2.359,-4.997 0.48,-7.036 -1.919,1.52 -3.798,1.04 -6.156,0.52 M 11.473,32.94 c 0.44,7.076 -3.358,11.593 -8.595,9.075"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1070" />
+ <path
+ d="m 9.514,39.976 c 0.96,-1 2.359,-6.476 1.44,-7.955 -0.96,-1.52 -4.718,-1.52 -6.637,-1 -2.358,1 -3.318,2.998 -2.838,8.475 0,1.999 0.48,2.998 0.48,3.958 l 1.439,-0.96 c 2.359,0 4.717,0 6.116,-2.518 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1072" />
+ <path
+ d="m 55.566,32.54 c -2.798,-1.479 -4.197,-5.996 -7.035,-7.995 -2.799,-1.999 -2.799,0.52 -4.718,3.518"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1074" />
+ <path
+ d="M 52.848,29.102 C 49.09,38.137 42.454,27.104 45.772,25.584 m 11.233,0.96 C 55.606,22.067 50.01,18.549 46.692,19.548 m -33.98,39.136 c 3.318,-1.998 4.278,0.96 6.636,2.439 3.318,1.959 6.157,-0.48 8.955,0.52"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1076" />
+ <path
+ clip-path="url(#a)"
+ d="m 65,104.337 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.969,73.755 47.131,72.756 44.333,69.238 41.975,67.239 35.379,66.24 33.5,66.24 23.626,66.24 16.59,65.72 8.595,57.685 6.715,55.207 5.757,52.168 4.837,48.69 3.397,44.653 2,45.652 1.52,39.656 1.04,33.14 2,31.621 6.237,30.621 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.995,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.88,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.551 -1.4,6.517 -2.319,17.03 -1.879,23.546 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.36,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.839,25.544 -0.959,3.518 0,4.518 -2.358,8.035 -1.879,2.519 -9.874,3.998 -13.152,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.037 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.517 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.999 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.518 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.92,1.48 -0.92,2.479 -0.479,-0.48 -0.958,-0.48 -1.438,-0.48 -0.44,0.48 -0.44,1 -0.92,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.036,5.476 -7.036,5.476 0,0 -3.278,-2.998 -6.116,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1078" />
+ <path
+ d="m 308.533,99.18 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 v 0.52 c 0,0 0,0 0,0 v 1.519"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1080" />
+ <path
+ d="m 95.102,24.905 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.551 0,3.038 0,5.517 0.48,8.555 0.48,3.518 0,7.036 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.92,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.196,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.076,-1.519 -1.88,1.52 -0.92,3.998 -0.44,6.036 -1.44,0 -2.839,-0.52 -3.798,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.514,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.96,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1082" />
+ <path
+ d="m 81.91,41.055 c -1.399,4.038 -3.278,8.035 -5.596,11.033 -1.88,2.519 -4.238,5.037 -5.157,7.516 -0.48,1.519 0,3.038 -0.48,4.517 -0.44,1.52 -2.318,2.998 -2.798,4.517 -0.48,1 -0.48,2.519 -0.48,3.518 -0.44,1.48 -1.879,2.519 -1.879,3.998 0,1.519 1.44,2.998 1.44,4.517 0.44,1.52 0.44,2.998 0.44,4.517 0,3.518 -0.92,6.996 -0.44,10.034 0,2 0.919,3.478 0.919,5.517 0,1.999 -0.92,3.478 -0.48,5.477 0.48,1.519 0.96,2.038 1.4,3.517 0.959,1.52 0,3.518 0.479,5.037 3.278,-0.999 2.798,2.479 3.278,4.478 0.96,-2 3.758,-2.479 5.637,-2 -0.96,-0.479 -3.758,-0.998 -4.678,-1.478 -1.878,-1.52 0,-6.037 1.4,-7.516 -1.4,0 -4.238,-0.52 -4.678,-2.038 -0.959,-2 3.278,-4.478 3.718,-5.997 -1.879,-0.52 -3.278,-1 -3.718,-2.998 -1.439,-3.518 1.4,-5.037 1.84,-8.035 0,-1.999 -1.4,-1.48 -2.32,-3.518 -0.959,-1.999 0,-4.477 1.88,-5.996 -2.359,-3.518 -2.839,-5.517 -0.48,-9.035 0.92,-1.479 0.92,-0.48 0.92,-1.999 0.479,-1.998 -1.4,-3.517 0.959,-5.516 0.92,-1 1.879,-0.48 2.318,-1.999 0.48,-1 0,-3.998 0.96,-5.517 0.48,-1.998 0.92,-4.517 1.879,-6.995 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1084" />
+ <path
+ d="m 95.142,24.945 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.55 0,3.04 0,5.518 0.48,8.556 0.48,3.518 0,7.035 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.919,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.197,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.077,-1.519 -1.878,1.52 -0.919,3.998 -0.44,6.036 -1.438,0 -2.838,-0.52 -3.797,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.515,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.959,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1086" />
+ <path
+ d="m 103.058,54.087 c -0.48,2.998 0,5.997 0,9.035 v 9.994 c 0.44,6.556 1.399,13.551 3.278,19.588 0.48,1 0.959,1.999 1.399,3.478 0,1.519 0,1 -0.44,2.518 -0.48,1.999 -0.96,2.998 -0.96,5.037 0.48,1.999 0.96,2.998 0.96,4.477 -0.48,0.52 -1.44,1.52 -1.44,2.519 -0.439,1 0,2.518 -0.439,2.998 -0.48,1 -1.919,1 -2.838,2.039 -0.48,1.479 0,2.998 -0.96,4.477 -1.399,-1 -2.798,0.52 -3.757,1 -0.92,-1 -1.88,-1.48 -2.839,-1 0.96,-1 3.798,-2.478 4.718,-3.478 0.959,-2.039 0,-4.517 -0.92,-7.036 2.359,0 3.278,-2.518 3.278,-4.996 0,-2.04 -0.92,-2.04 -1.879,-3.518 -0.96,-2.519 1.4,-4.038 1.88,-6.516 0.959,-4.038 -0.92,-5.517 -2.84,-8.036 4.238,-4.517 1.92,-8.035 0.48,-12.512 -0.919,-3.038 0.96,-5.517 0.48,-9.034 0,-2.999 1.4,-6.037 1.4,-9.035 0.48,-1.999 0.959,-4.997 0.48,-7.036 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1088" />
+ <path
+ d="m 45.253,24.545 c -1.88,3.478 2.838,10.914 6.116,6.956 2.318,-2.479 -3.758,-9.954 -5.637,-6.956 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1090" />
+ <path
+ d="m 45.692,26.944 c 0,-0.52 0.44,-1 0.92,-1 0.52,0 0.92,0.48 0.92,1 0,0.56 -0.4,1 -0.92,1 -0.48,0 -0.92,-0.44 -0.92,-1 z"
+ fill="#ffffff"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1092" />
+ <path
+ d="m 2.878,39.016 c 0.96,0 2.399,0.48 3.358,0.48 0.96,0 1.44,-1.479 2.399,-1.999"
+ fill="none"
+ stroke="#ffffff"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1094" />
+ <path
+ d="m 80.111,31.46 c -1.439,-0.519 -3.358,0 -3.837,2.08 1.919,0.48 3.837,-1.04 5.277,0.48 -0.96,2.078 -2.879,3.078 -4.798,3.078 M 96.981,26.064 c -2.798,-1.519 -7.036,3.038 -1.879,3.518 1.88,0.52 3.278,-1.519 4.238,1 0.44,1.998 -3.278,5.036 -4.238,6.516 M 47.171,20.987 c -0.48,-3.438 5.677,-4.437 2.399,1.96 M 26.944,63.082 c 0,-1 0.96,-3.478 -0.48,-3.478 -1.919,-0.52 -2.878,2.478 -2.399,3.478 m 82.271,86.348 c 0,-2.04 0.48,-4.558 0.959,-6.637 2.319,0.52 2.319,4.118 1.879,6.636 m 71.516,4.917 c -3.717,-6.915 -6.556,0.48 -2.798,2.439 m 83.709,-12.952 c 0.92,-0.48 1.84,-1 2.719,-1.999 m 7.995,67.159 c -0.44,-4.037 -6.556,-4.557 -3.718,0 m 33.86,28.143 c -0.96,-1.04 -1.92,-1.599 -2.879,-1.599 m -5.116,-1.399 c -2.359,-6.116 -6.157,1.56 -2.359,2.039"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1096" />
+ <path
+ d="m 267.638,200.039 c -1.4,1.999 1.399,4.997 0.48,5.996 -1.88,1.999 -3.798,-1 -3.798,-2.478 m -155.146,16.07 c 0,1.479 0.44,2.478 0.44,3.918 -1.4,-0.48 -2.319,-0.96 -3.278,-2.439 m 1.838,4.917 c 0.52,1.52 1,2.518 2,3.518 m 18.868,10.514 c 2.318,6.036 -2.359,2.518 -4.238,-0.52"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1098" />
+ <path
+ clip-path="url(#a)"
+ d="m 135.078,244.092 c -0.44,1.999 0.96,2.519 1.4,3.998 -2.32,0.48 -3.718,-1 -5.597,-1.48"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1100" />
+ <path
+ d="m 121.926,242.573 c 0.48,2.039 1.879,3.038 3.278,3.518"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1102" />
+ </g>
+ </g>
+ <g
+ id="layer2"
+ inkscape:label="Layer 2"
+ clip-path="none"
+ inkscape:groupmode="layer"
+ transform="matrix(0.5,0,0,0.5,0,150)">
+ <circle
+ r="12"
+ cy="-284"
+ cx="50"
+ style="fill:#ffffff;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
+ id="path3331" />
+ <circle
+ r="8"
+ cy="-284"
+ cx="50"
+ style="fill:#73d216;stroke:#4e9a06;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
+ id="path3319-3" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="Layer 3" />
+</svg>
diff --git a/share/extensions/other/clipart/licenses/gpl.svg b/share/extensions/other/clipart/licenses/gpl.svg
new file mode 100644
index 0000000..1f9f083
--- /dev/null
+++ b/share/extensions/other/clipart/licenses/gpl.svg
@@ -0,0 +1,347 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="50"
+ height="16"
+ viewBox="0 0 50 16"
+ version="1.1"
+ id="svg5"
+ sodipodi:docname="gpl.svg"
+ inkscape:version="1.2-alpha1 (8b0d57f509, 2022-03-02, custom)"
+ inkscape:export-filename="/home/doctormo/Projects/inkscape/extensions/main/other/clipart/licenses/cc-by-sa.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#999999"
+ borderopacity="1"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="2.9434"
+ inkscape:cx="-26.669838"
+ inkscape:cy="27.689067"
+ inkscape:window-width="1472"
+ inkscape:window-height="807"
+ inkscape:window-x="64"
+ inkscape:window-y="20"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer2" />
+ <defs
+ id="defs2">
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect2486"
+ is_visible="true"
+ lpeversion="1"
+ nodesatellites_param=""
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false"
+ satellites_param="" />
+ <color-profile
+ name="AL1706"
+ xlink:href="../../../../../.local/share/icc/edid-a9cf44b399fa09c3fc2589cbaadd3747.icc"
+ id="color-profile2156" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="a">
+ <path
+ d="M 0.24,1.04 H 322.045 V 255.205 H 0.24 Z"
+ id="path1048" />
+ </clipPath>
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect2486-3"
+ is_visible="true"
+ lpeversion="1"
+ nodesatellites_param=""
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false"
+ satellites_param="" />
+ </defs>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-51.633091,-21.31349)"
+ sodipodi:insensitive="true"
+ style="display:none">
+ <g
+ inkscape:label="dog.svg"
+ transform="matrix(0.24767307,0,0,0.24767307,51.414234,28.015162)"
+ id="g1104">
+ <path
+ d="m 308.493,99.14 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1058" />
+ <path
+ clip-path="url(#a)"
+ d="m 64.96,104.297 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.929,73.715 47.091,72.716 44.293,69.198 41.935,67.2 35.34,66.2 33.46,66.2 23.586,66.2 16.55,65.68 8.555,57.645 6.676,55.167 5.717,52.128 4.797,48.651 3.358,44.613 1.959,45.612 1.479,39.616 0.999,33.1 1.959,31.581 6.196,30.581 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.996,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.879,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.552 -1.4,6.516 -2.319,17.03 -1.879,23.545 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.359,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.838,25.544 -0.96,3.518 0,4.518 -2.36,8.035 -1.878,2.519 -9.873,3.998 -13.151,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.036 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.518 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.998 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.519 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.919,1.48 -0.919,2.479 -0.48,-0.48 -0.96,-0.48 -1.44,-0.48 -0.439,0.48 -0.439,1 -0.919,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.035,5.476 -7.035,5.476 0,0 -3.279,-2.998 -6.117,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1060" />
+ <path
+ d="m 147.31,59.604 c 16.95,3.038 32.461,6.556 49.85,5.557 21.627,-1.52 42.775,-5.037 64.401,0 -8.434,-2 -18.788,-2 -21.626,8.554 0.48,-3.038 -0.92,-6.036 -3.758,-7.035 -4.198,-2.04 -5.637,1.998 -9.394,2.998 -5.637,1.519 -7.036,-2.519 -12.673,4.517 -3.318,-8.555 -5.197,-1.999 -10.833,-1.48 -2.838,0 -3.758,-2.518 -6.116,-3.037 -4.678,-1 -6.557,3.518 -10.794,3.518 -1.44,0 -1.44,-2.999 -3.318,-2.999 -1.4,-0.52 -2.798,0.48 -4.677,0 -2.359,0 -2.838,-2.038 -5.637,-1.519 -3.797,0.52 -5.676,6.037 -9.434,6.516 -0.92,-6.516 0,-7.515 -5.157,-10.553 z M 47.531,15.39 C 48.011,3.959 77.633,1.96 82.79,7.956 80.471,5.957 74.835,6.437 73.875,9.955 c -2.838,-2.998 -5.636,-1.999 -7.995,0 -2.358,-1.999 -4.677,-0.52 -7.036,-1 z m -32.86,15.032 c 4.238,-2.479 9.394,-2.479 13.632,-3.478 4.717,-1 8.475,-3.478 12.672,-4.997 -2.318,2.518 -5.636,5.996 -9.394,7.995 -5.637,2.958 -10.794,-0.52 -16.43,1.999 z m 105.776,126.883 c 6.596,9.554 10.873,20.067 15.55,30.621 2.839,5.996 5.677,10.993 5.197,18.03 0,8.034 -3.278,16.03 -4.237,23.545 0.96,-3.478 4.237,-12.513 8.955,-11.513 -0.96,-1.52 -2.359,-3.998 -2.359,-5.996 0,-3.039 3.278,-4.518 3.278,-7.036 0,-1.999 -3.278,-5.517 -3.758,-8.035 0,-2.479 0.48,-4.997 0.96,-6.996 -5.197,-1.999 -6.117,-7.516 -3.798,-12.553 -4.237,-0.999 -7.515,-2.998 -9.394,-7.515 -0.96,-1.999 0,-3.998 -1.44,-5.517 -1.399,-2.518 -3.757,-2.998 -5.156,-5.516 z M 264.84,144.353 c 7.995,10.553 19.308,17.549 26.823,28.582 3.758,4.997 7.995,11.513 10.354,17.55 1.4,2.478 3.278,5.996 3.278,8.994 0.48,3.518 -1.879,7.036 -1.4,10.514 1.88,-2 3.759,-6.476 3.759,-8.995 0.44,-3.518 -2.359,-3.518 -3.318,-7.515 -0.92,-3.518 0.959,-5.517 -0.44,-8.035 -0.48,-1.48 -2.838,-2.479 -3.758,-3.998 0,-1 -0.48,-3.518 -0.96,-3.998 -1.398,-2.518 -5.636,-2.518 -7.035,-5.516 -1.879,-5.517 1.879,-5.517 -3.318,-8.515 -4.677,-2.998 -14.551,-8.035 -15.99,-14.551 z m 10.353,30.541 c -0.44,2.518 -2.358,6.556 -1.399,9.554 0.48,1 2.359,0 2.359,0.52 0.48,1 0.92,2.518 1.399,3.518 1.439,4.517 -0.92,13.072 -6.596,12.072 2.358,-0.52 4.717,0.48 5.676,2.479 0,-3.998 1.4,-7.036 4.678,-8.515 -1.88,-3.038 -1.88,-6.036 -2.32,-9.074 -0.479,-3.998 -0.959,-6.516 -1.918,-10.034 -0.44,-3.518 0.48,-4.518 -1.879,-7.036 -1.879,-2.039 -3.758,-1 -6.596,-2.039 1.92,2.519 6.156,3.518 5.677,7.076 z m -149.469,19.068 c -3.798,4.997 -1.919,11.034 -2.359,17.03 0,1.999 -0.48,6.036 -1.879,7.516 -1.918,1.998 -4.237,1.519 -6.156,2.998 2.838,-2.479 7.076,-2.479 10.394,-1.48 -1.44,-4.517 -3.318,-9.034 2.318,-10.033 -2.318,-3.518 -1.399,-4.997 -1.399,-8.515 -0.48,-2.998 -1.879,-6.996 -0.92,-10.034 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1062" />
+ <path
+ d="m 117.649,122.206 c 0.96,-2.998 -0.92,-6.516 -0.44,-9.514 0.44,-3.998 1.879,-5.517 4.197,-8.515 -6.076,-2.519 -4.677,-6.036 -4.197,-11.553 0.44,-4.997 -2.359,-5.517 -4.717,-10.034 -2.838,-6.516 -2.838,-17.03 -3.278,-24.065 0,-7.996 -2.838,-14.032 -8.955,-19.029 -2.798,-2.518 -7.035,-7.036 -10.793,-7.036 -5.677,-0.52 -9.435,6.037 -11.313,11.034 -1.4,4.997 -4.238,17.549 -3.278,23.066 l 9.874,48.13 1.878,1.52 c 4.238,3.477 1.88,5.516 -0.48,7.515 0.48,1 0.96,1.48 1.88,1.999 h 1.879 c 1.439,0 2.838,0 3.757,0.52 0.48,0 1.44,0.48 2.359,0.48 0,3.517 -2.359,7.035 -1.88,10.513 2.84,-0.48 5.638,-1 7.077,-3.998 -0.96,2.998 -1.44,7.036 -1.44,9.514 1.44,-1.998 2.36,-4.996 2.839,-5.996 3.278,-6.036 13.632,-8.515 15.03,-14.551 z m 3.318,47.771 c 2.798,5.996 3.717,13.032 6.076,19.028 2.798,6.037 4.197,10.554 4.197,17.55 0.48,5.037 -0.48,13.072 -3.757,17.07 -3.238,3.997 -8.875,6.036 -12.633,9.514 6.117,-5.997 13.592,1 17.79,-6.996 3.757,-7.036 4.197,-14.551 4.197,-22.067 0,-8.554 -4.677,-10.553 -7.475,-17.549 -2.799,-6.036 -4.678,-14.551 -9.834,-18.589 z m 46.931,20.388 c 1.4,4.037 4.198,18.069 -2.358,16.55 0,3.517 0.92,6.516 -0.48,10.034 -1.4,-2 -2.838,-6.037 -5.157,-2.519 1.879,1.999 0,1.999 0,3.518 0.44,1.999 0.44,3.997 0.92,5.996 -6.117,1 -7.516,6.516 -10.794,11.034 -3.798,4.517 -8.954,7.515 -9.434,14.51 1.439,-4.996 -0.48,-11.512 2.838,-15.51 0,0.48 2.798,0 3.758,-1 1.879,-1.518 1.399,-3.997 2.358,-6.036 2.359,-4.997 2.799,-2.478 6.117,-5.996 3.278,-3.518 0.92,-7.036 0,-11.513 4.237,2.479 3.757,-4.037 2.798,-6.516 4.717,0 6.596,-1 6.116,-5.517 -0.48,-2.518 -2.358,-8.514 -3.278,-10.513 2.799,1.999 5.637,0.48 7.516,-1.04 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1064" />
+ <path
+ d="m 166.06,187.846 c -0.48,-1.959 -1.4,-5.477 -0.48,-7.435 0.96,-2.519 3.318,-2.999 3.757,-4.997 0.96,-3.478 -3.278,-6.476 1.88,-8.475 -2.32,0 -4.678,1.999 -6.557,-1 1.4,5.997 -4.717,8.995 -1.879,14.472 z m 11.752,-26.544 c -0.96,4.997 -3.318,12.992 3.278,14.991 3.318,1 11.753,-9.474 13.192,-2.998 2.359,-3.998 5.157,-3.478 8.915,-4.477 1.439,-0.52 1.879,-2.999 3.798,-2.519 1.878,0.52 2.798,3.518 2.798,4.997 0.96,-1.999 3.318,-7.515 5.636,-8.515 5.197,-1.479 4.238,3.038 5.677,6.037 1.4,-2 1.879,-5.517 4.237,-5.517 2.799,-0.52 4.198,2.998 4.678,4.997 1.878,-1.999 1.878,-8.515 4.717,-8.515 2.358,-0.48 3.757,2.998 3.278,5.037 2.838,-3.038 -0.48,-9.514 3.318,-11.513 0.92,1.48 1.399,3.478 1.399,4.477 1.399,-4.997 0.92,-7.475 6.596,-6.995 4.677,0 6.116,0.999 7.036,5.996 5.636,-4.997 6.596,4.997 6.596,8.515 3.757,-4.517 5.156,-8.995 2.358,-13.992 -2.838,-4.517 -4.717,-9.514 -6.116,-15.03 -1.4,1.998 -3.758,7.995 -6.116,7.995 -3.318,0 -4.238,-7.476 -5.197,-9.515 -1.4,2.04 -3.278,10.034 -5.637,10.514 -4.237,1.519 -6.596,-4.477 -7.995,-7.476 -1.879,2.999 -1.4,9.475 -4.717,11.993 -4.677,3.998 -4.198,-1.519 -8.435,-2.998 -1.879,7.515 -2.359,10.993 -9.914,12.512 -1.879,0 -1.879,0 -3.758,0.48 -1.879,0.52 -3.757,1.999 -5.636,2.519 -9.395,3.997 -19.269,1.479 -21.627,-9.515 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1066" />
+ <path
+ d="m 263.84,161.782 c 4.238,-4.477 13.192,3.518 16.03,6.516 4.238,4.038 5.677,8.555 5.197,14.031 0,5.517 -0.48,14.552 -3.318,19.549 -0.92,1.998 -3.757,5.037 -6.116,6.516 -2.359,1.519 -6.156,1.519 -7.076,3.997 6.117,-1.479 14.631,-1 16.99,-7.995 2.359,-7.515 2.359,-16.03 2.838,-23.546 0.44,-8.035 -3.797,-11.513 -9.914,-16.03 -2.838,-2.518 -10.873,-12.552 -13.711,-15.03 -2.799,-3.039 -0.44,1.998 -5.197,1.478 z m 48.93,57.645 c 0.92,5.517 5.157,13.552 1.88,18.549 -1.88,3.038 -15.112,7.515 -13.193,0 5.157,1 5.637,-3.998 7.516,-7.516 2.838,-4.997 2.838,-3.518 1.919,-9.034 -0.96,-8.515 3.757,-17.03 2.798,-25.585 z M 292.583,79.112 c 3.757,7.036 10.353,8.555 10.793,18.07 0.96,7.035 -0.44,15.07 1.879,22.066 1.4,6.036 4.717,11.073 7.036,16.59 0.96,1.479 4.237,5.996 4.237,7.515 0.44,2.998 -2.358,4.517 -1.879,9.035 -6.116,-0.52 -1.399,5.516 -0.48,8.514 -2.358,-2.478 -7.035,-4.996 -7.955,-8.514 7.956,-2.519 2.799,-11.034 -1.439,-14.032 5.197,-9.034 -3.278,-12.073 -7.955,-17.59 3.758,-4.516 1.879,-8.034 -1.879,-11.552 5.157,-5.997 4.238,-26.584 -2.358,-31.621 z M 39.536,63.601 c 3.318,1.52 5.197,1.52 7.555,5.037 1.88,2.479 2.359,5.477 4.238,7.996 1.399,1.998 3.278,3.997 4.717,6.476 1.4,1.519 4.677,5.996 6.596,7.995 0.92,-5.997 -2.838,-9.474 -2.359,-14.991 0.44,-3.998 2.359,-8.475 3.758,-11.993 1.879,-4.997 3.278,-8.515 6.116,-11.993 3.278,-3.517 7.516,-7.995 6.596,-14.031 -1.399,6.516 -7.075,15.51 -14.59,12.512 -2.839,5.997 -4.238,7.516 -10.354,7.516 2.798,2.478 5.636,6.996 4.237,11.513 -1.879,-1.999 -5.197,-4.517 -7.555,-5.037 -3.278,-0.48 -5.637,1.519 -8.955,-1.999 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1068" />
+ <path
+ d="m 111.053,226.023 c -1.84,0.52 -3.278,2.998 -3.278,3.998 m 153.267,-88.747 c 1.439,7.556 13.672,16.07 17.909,22.067 3.318,4.517 10.833,9.035 12.233,15.03 M 121.446,164.94 c 2.839,4.517 5.197,10.514 7.076,15.03 0.92,2.52 1.4,4.998 2.359,7.516 1.399,2.519 2.798,2.999 4.677,5.517 5.157,6.996 0.48,27.503 -2.798,35.538 -0.48,1.48 -0.96,2.999 -1.88,3.478 M 52.288,6.396 c -3.278,1.52 -7.955,7.076 -9.354,10.594 -1.879,3.518 -6.076,3.997 -7.515,4.997 m 100.019,222.585 c -1.839,0.52 -2.319,3.038 -3.278,4.557 m -1.839,-7.995 c -3.278,0 -7.036,1.519 -7.995,4.957 m -11.673,-25.505 c -1.879,1 -4.237,1 -6.156,2.959 m 168.378,-16.55 c -2.319,0.52 -5.597,1.519 -6.077,3.997 m 2.799,-9.514 c -1.92,0 -3.838,1.04 -5.277,2.558 m 38.137,30.542 c -1.88,2.039 -3.758,4.037 -3.758,6.556 m -3.278,-9.594 c -1.839,1.559 -4.637,2.558 -5.117,5.596 m 21.986,-3.997 c -0.919,1.519 -1.358,2.518 -1.838,3.997 M 181.17,151.828 c -1.399,0.52 -4.717,4.038 -6.116,5.037 2.358,2.518 0.96,10.554 -2.838,11.553 0.48,2.039 -0.48,2.518 0.48,4.517 m -52.169,-7.595 c 0.92,-4.477 -5.197,-3.998 -7.076,-6.516 1.44,-1.48 3.318,-3.478 1.88,-5.477 -1.88,0.48 -3.759,0 -5.158,-1.519 1.4,-1.999 2.359,-4.997 0.48,-7.036 -1.919,1.52 -3.798,1.04 -6.156,0.52 M 11.473,32.94 c 0.44,7.076 -3.358,11.593 -8.595,9.075"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1070" />
+ <path
+ d="m 9.514,39.976 c 0.96,-1 2.359,-6.476 1.44,-7.955 -0.96,-1.52 -4.718,-1.52 -6.637,-1 -2.358,1 -3.318,2.998 -2.838,8.475 0,1.999 0.48,2.998 0.48,3.958 l 1.439,-0.96 c 2.359,0 4.717,0 6.116,-2.518 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1072" />
+ <path
+ d="m 55.566,32.54 c -2.798,-1.479 -4.197,-5.996 -7.035,-7.995 -2.799,-1.999 -2.799,0.52 -4.718,3.518"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1074" />
+ <path
+ d="M 52.848,29.102 C 49.09,38.137 42.454,27.104 45.772,25.584 m 11.233,0.96 C 55.606,22.067 50.01,18.549 46.692,19.548 m -33.98,39.136 c 3.318,-1.998 4.278,0.96 6.636,2.439 3.318,1.959 6.157,-0.48 8.955,0.52"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1076" />
+ <path
+ clip-path="url(#a)"
+ d="m 65,104.337 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.969,73.755 47.131,72.756 44.333,69.238 41.975,67.239 35.379,66.24 33.5,66.24 23.626,66.24 16.59,65.72 8.595,57.685 6.715,55.207 5.757,52.168 4.837,48.69 3.397,44.653 2,45.652 1.52,39.656 1.04,33.14 2,31.621 6.237,30.621 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.995,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.88,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.551 -1.4,6.517 -2.319,17.03 -1.879,23.546 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.36,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.839,25.544 -0.959,3.518 0,4.518 -2.358,8.035 -1.879,2.519 -9.874,3.998 -13.152,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.037 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.517 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.999 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.518 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.92,1.48 -0.92,2.479 -0.479,-0.48 -0.958,-0.48 -1.438,-0.48 -0.44,0.48 -0.44,1 -0.92,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.036,5.476 -7.036,5.476 0,0 -3.278,-2.998 -6.116,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1078" />
+ <path
+ d="m 308.533,99.18 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 v 0.52 c 0,0 0,0 0,0 v 1.519"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1080" />
+ <path
+ d="m 95.102,24.905 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.551 0,3.038 0,5.517 0.48,8.555 0.48,3.518 0,7.036 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.92,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.196,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.076,-1.519 -1.88,1.52 -0.92,3.998 -0.44,6.036 -1.44,0 -2.839,-0.52 -3.798,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.514,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.96,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1082" />
+ <path
+ d="m 81.91,41.055 c -1.399,4.038 -3.278,8.035 -5.596,11.033 -1.88,2.519 -4.238,5.037 -5.157,7.516 -0.48,1.519 0,3.038 -0.48,4.517 -0.44,1.52 -2.318,2.998 -2.798,4.517 -0.48,1 -0.48,2.519 -0.48,3.518 -0.44,1.48 -1.879,2.519 -1.879,3.998 0,1.519 1.44,2.998 1.44,4.517 0.44,1.52 0.44,2.998 0.44,4.517 0,3.518 -0.92,6.996 -0.44,10.034 0,2 0.919,3.478 0.919,5.517 0,1.999 -0.92,3.478 -0.48,5.477 0.48,1.519 0.96,2.038 1.4,3.517 0.959,1.52 0,3.518 0.479,5.037 3.278,-0.999 2.798,2.479 3.278,4.478 0.96,-2 3.758,-2.479 5.637,-2 -0.96,-0.479 -3.758,-0.998 -4.678,-1.478 -1.878,-1.52 0,-6.037 1.4,-7.516 -1.4,0 -4.238,-0.52 -4.678,-2.038 -0.959,-2 3.278,-4.478 3.718,-5.997 -1.879,-0.52 -3.278,-1 -3.718,-2.998 -1.439,-3.518 1.4,-5.037 1.84,-8.035 0,-1.999 -1.4,-1.48 -2.32,-3.518 -0.959,-1.999 0,-4.477 1.88,-5.996 -2.359,-3.518 -2.839,-5.517 -0.48,-9.035 0.92,-1.479 0.92,-0.48 0.92,-1.999 0.479,-1.998 -1.4,-3.517 0.959,-5.516 0.92,-1 1.879,-0.48 2.318,-1.999 0.48,-1 0,-3.998 0.96,-5.517 0.48,-1.998 0.92,-4.517 1.879,-6.995 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1084" />
+ <path
+ d="m 95.142,24.945 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.55 0,3.04 0,5.518 0.48,8.556 0.48,3.518 0,7.035 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.919,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.197,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.077,-1.519 -1.878,1.52 -0.919,3.998 -0.44,6.036 -1.438,0 -2.838,-0.52 -3.797,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.515,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.959,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1086" />
+ <path
+ d="m 103.058,54.087 c -0.48,2.998 0,5.997 0,9.035 v 9.994 c 0.44,6.556 1.399,13.551 3.278,19.588 0.48,1 0.959,1.999 1.399,3.478 0,1.519 0,1 -0.44,2.518 -0.48,1.999 -0.96,2.998 -0.96,5.037 0.48,1.999 0.96,2.998 0.96,4.477 -0.48,0.52 -1.44,1.52 -1.44,2.519 -0.439,1 0,2.518 -0.439,2.998 -0.48,1 -1.919,1 -2.838,2.039 -0.48,1.479 0,2.998 -0.96,4.477 -1.399,-1 -2.798,0.52 -3.757,1 -0.92,-1 -1.88,-1.48 -2.839,-1 0.96,-1 3.798,-2.478 4.718,-3.478 0.959,-2.039 0,-4.517 -0.92,-7.036 2.359,0 3.278,-2.518 3.278,-4.996 0,-2.04 -0.92,-2.04 -1.879,-3.518 -0.96,-2.519 1.4,-4.038 1.88,-6.516 0.959,-4.038 -0.92,-5.517 -2.84,-8.036 4.238,-4.517 1.92,-8.035 0.48,-12.512 -0.919,-3.038 0.96,-5.517 0.48,-9.034 0,-2.999 1.4,-6.037 1.4,-9.035 0.48,-1.999 0.959,-4.997 0.48,-7.036 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1088" />
+ <path
+ d="m 45.253,24.545 c -1.88,3.478 2.838,10.914 6.116,6.956 2.318,-2.479 -3.758,-9.954 -5.637,-6.956 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1090" />
+ <path
+ d="m 45.692,26.944 c 0,-0.52 0.44,-1 0.92,-1 0.52,0 0.92,0.48 0.92,1 0,0.56 -0.4,1 -0.92,1 -0.48,0 -0.92,-0.44 -0.92,-1 z"
+ fill="#ffffff"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1092" />
+ <path
+ d="m 2.878,39.016 c 0.96,0 2.399,0.48 3.358,0.48 0.96,0 1.44,-1.479 2.399,-1.999"
+ fill="none"
+ stroke="#ffffff"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1094" />
+ <path
+ d="m 80.111,31.46 c -1.439,-0.519 -3.358,0 -3.837,2.08 1.919,0.48 3.837,-1.04 5.277,0.48 -0.96,2.078 -2.879,3.078 -4.798,3.078 M 96.981,26.064 c -2.798,-1.519 -7.036,3.038 -1.879,3.518 1.88,0.52 3.278,-1.519 4.238,1 0.44,1.998 -3.278,5.036 -4.238,6.516 M 47.171,20.987 c -0.48,-3.438 5.677,-4.437 2.399,1.96 M 26.944,63.082 c 0,-1 0.96,-3.478 -0.48,-3.478 -1.919,-0.52 -2.878,2.478 -2.399,3.478 m 82.271,86.348 c 0,-2.04 0.48,-4.558 0.959,-6.637 2.319,0.52 2.319,4.118 1.879,6.636 m 71.516,4.917 c -3.717,-6.915 -6.556,0.48 -2.798,2.439 m 83.709,-12.952 c 0.92,-0.48 1.84,-1 2.719,-1.999 m 7.995,67.159 c -0.44,-4.037 -6.556,-4.557 -3.718,0 m 33.86,28.143 c -0.96,-1.04 -1.92,-1.599 -2.879,-1.599 m -5.116,-1.399 c -2.359,-6.116 -6.157,1.56 -2.359,2.039"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1096" />
+ <path
+ d="m 267.638,200.039 c -1.4,1.999 1.399,4.997 0.48,5.996 -1.88,1.999 -3.798,-1 -3.798,-2.478 m -155.146,16.07 c 0,1.479 0.44,2.478 0.44,3.918 -1.4,-0.48 -2.319,-0.96 -3.278,-2.439 m 1.838,4.917 c 0.52,1.52 1,2.518 2,3.518 m 18.868,10.514 c 2.318,6.036 -2.359,2.518 -4.238,-0.52"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1098" />
+ <path
+ clip-path="url(#a)"
+ d="m 135.078,244.092 c -0.44,1.999 0.96,2.519 1.4,3.998 -2.32,0.48 -3.718,-1 -5.597,-1.48"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1100" />
+ <path
+ d="m 121.926,242.573 c 0.48,2.039 1.879,3.038 3.278,3.518"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1102" />
+ </g>
+ </g>
+ <g
+ id="layer2"
+ inkscape:label="Layer 2"
+ clip-path="none"
+ inkscape:groupmode="layer"
+ transform="matrix(0.5,0,0,0.5,0,150)">
+ <rect
+ style="opacity:0.8;fill:#ffffff;stroke-width:2.06559;stop-color:#000000"
+ id="rect1552"
+ width="100"
+ height="32"
+ x="0"
+ y="-300" />
+ <g
+ aria-label="GPL"
+ transform="scale(0.9922273,1.0078336)"
+ id="text1448"
+ style="font-size:36.0397px;line-height:1.25;font-family:'Arial Black';-inkscape-font-specification:'Arial Black, ';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#a40000;stroke-width:1.68935">
+ <path
+ d="m 25.165647,-278.23786 v -5.36724 h 12.318256 v 10.99844 q -3.537099,2.41086 -6.264713,3.29073 -2.710017,0.86228 -6.440689,0.86228 -4.59295,0 -7.496539,-1.56618 -2.885991,-1.56617 -4.487365,-4.66334 -1.583775,-3.09716 -1.583775,-7.10939 0,-4.2234 1.742153,-7.33816 1.742153,-3.13236 5.103278,-4.75133 2.622029,-1.24942 7.056601,-1.24942 4.276195,0 6.387896,0.77429 2.129299,0.77429 3.519502,2.41086 1.407801,1.61897 2.111701,4.11781 l -7.690112,1.37261 q -0.475132,-1.46059 -1.61897,-2.23488 -1.126241,-0.77429 -2.885992,-0.77429 -2.622029,0 -4.188207,1.83014 -1.548581,1.81254 -1.548581,5.75438 0,4.18821 1.566178,5.98316 1.583776,1.79494 4.399378,1.79494 1.33741,0 2.551639,-0.38714 1.214228,-0.38715 2.780406,-1.31982 v -2.42845 z"
+ style="fill:#204a87"
+ id="path2147" />
+ <path
+ d="m 42.182438,-294.69153 h 13.250925 q 4.328987,0 6.475883,2.0589 2.164494,2.05891 2.164494,5.85998 0,3.90664 -2.358066,6.10633 -2.340469,2.19969 -7.162187,2.19969 h -4.364182 v 9.57304 h -8.006867 z m 8.006867,10.99844 h 1.953323 q 2.305274,0 3.237942,-0.79189 0.932668,-0.80948 0.932668,-2.05891 0,-1.21423 -0.809485,-2.05891 -0.809486,-0.84468 -3.044369,-0.84468 h -2.270079 z"
+ style="fill:#204a87"
+ id="path2149" />
+ <path
+ d="m 68.244347,-294.69153 h 7.971672 v 19.44524 h 12.441439 v 6.3527 H 68.244347 Z"
+ style="fill:#204a87"
+ id="path2151" />
+ </g>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="Layer 3" />
+</svg>
diff --git a/share/extensions/other/clipart/licenses/mit.svg b/share/extensions/other/clipart/licenses/mit.svg
new file mode 100644
index 0000000..5f6c855
--- /dev/null
+++ b/share/extensions/other/clipart/licenses/mit.svg
@@ -0,0 +1,308 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="50"
+ height="16"
+ viewBox="0 0 50 16"
+ version="1.1"
+ id="svg5"
+ sodipodi:docname="mit.svg"
+ inkscape:version="1.2-alpha1 (8b0d57f509, 2022-03-02, custom)"
+ inkscape:export-filename="/home/doctormo/Projects/inkscape/extensions/main/other/clipart/licenses/cc-by-sa.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#999999"
+ borderopacity="1"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="2.9434"
+ inkscape:cx="-40.259564"
+ inkscape:cy="28.02881"
+ inkscape:window-width="1472"
+ inkscape:window-height="807"
+ inkscape:window-x="64"
+ inkscape:window-y="20"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer2" />
+ <defs
+ id="defs2">
+ <color-profile
+ name="AL1706"
+ xlink:href="../../../../../.local/share/icc/edid-a9cf44b399fa09c3fc2589cbaadd3747.icc"
+ id="color-profile167" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="a">
+ <path
+ d="M 0.24,1.04 H 322.045 V 255.205 H 0.24 Z"
+ id="path1048" />
+ </clipPath>
+ </defs>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-51.633091,-21.31349)"
+ sodipodi:insensitive="true"
+ style="display:none">
+ <g
+ inkscape:label="dog.svg"
+ transform="matrix(0.24767307,0,0,0.24767307,51.414234,28.015162)"
+ id="g1104">
+ <path
+ d="m 308.493,99.14 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1058" />
+ <path
+ clip-path="url(#a)"
+ d="m 64.96,104.297 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.929,73.715 47.091,72.716 44.293,69.198 41.935,67.2 35.34,66.2 33.46,66.2 23.586,66.2 16.55,65.68 8.555,57.645 6.676,55.167 5.717,52.128 4.797,48.651 3.358,44.613 1.959,45.612 1.479,39.616 0.999,33.1 1.959,31.581 6.196,30.581 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.996,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.879,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.552 -1.4,6.516 -2.319,17.03 -1.879,23.545 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.359,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.838,25.544 -0.96,3.518 0,4.518 -2.36,8.035 -1.878,2.519 -9.873,3.998 -13.151,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.036 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.518 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.998 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.519 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.919,1.48 -0.919,2.479 -0.48,-0.48 -0.96,-0.48 -1.44,-0.48 -0.439,0.48 -0.439,1 -0.919,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.035,5.476 -7.035,5.476 0,0 -3.279,-2.998 -6.117,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1060" />
+ <path
+ d="m 147.31,59.604 c 16.95,3.038 32.461,6.556 49.85,5.557 21.627,-1.52 42.775,-5.037 64.401,0 -8.434,-2 -18.788,-2 -21.626,8.554 0.48,-3.038 -0.92,-6.036 -3.758,-7.035 -4.198,-2.04 -5.637,1.998 -9.394,2.998 -5.637,1.519 -7.036,-2.519 -12.673,4.517 -3.318,-8.555 -5.197,-1.999 -10.833,-1.48 -2.838,0 -3.758,-2.518 -6.116,-3.037 -4.678,-1 -6.557,3.518 -10.794,3.518 -1.44,0 -1.44,-2.999 -3.318,-2.999 -1.4,-0.52 -2.798,0.48 -4.677,0 -2.359,0 -2.838,-2.038 -5.637,-1.519 -3.797,0.52 -5.676,6.037 -9.434,6.516 -0.92,-6.516 0,-7.515 -5.157,-10.553 z M 47.531,15.39 C 48.011,3.959 77.633,1.96 82.79,7.956 80.471,5.957 74.835,6.437 73.875,9.955 c -2.838,-2.998 -5.636,-1.999 -7.995,0 -2.358,-1.999 -4.677,-0.52 -7.036,-1 z m -32.86,15.032 c 4.238,-2.479 9.394,-2.479 13.632,-3.478 4.717,-1 8.475,-3.478 12.672,-4.997 -2.318,2.518 -5.636,5.996 -9.394,7.995 -5.637,2.958 -10.794,-0.52 -16.43,1.999 z m 105.776,126.883 c 6.596,9.554 10.873,20.067 15.55,30.621 2.839,5.996 5.677,10.993 5.197,18.03 0,8.034 -3.278,16.03 -4.237,23.545 0.96,-3.478 4.237,-12.513 8.955,-11.513 -0.96,-1.52 -2.359,-3.998 -2.359,-5.996 0,-3.039 3.278,-4.518 3.278,-7.036 0,-1.999 -3.278,-5.517 -3.758,-8.035 0,-2.479 0.48,-4.997 0.96,-6.996 -5.197,-1.999 -6.117,-7.516 -3.798,-12.553 -4.237,-0.999 -7.515,-2.998 -9.394,-7.515 -0.96,-1.999 0,-3.998 -1.44,-5.517 -1.399,-2.518 -3.757,-2.998 -5.156,-5.516 z M 264.84,144.353 c 7.995,10.553 19.308,17.549 26.823,28.582 3.758,4.997 7.995,11.513 10.354,17.55 1.4,2.478 3.278,5.996 3.278,8.994 0.48,3.518 -1.879,7.036 -1.4,10.514 1.88,-2 3.759,-6.476 3.759,-8.995 0.44,-3.518 -2.359,-3.518 -3.318,-7.515 -0.92,-3.518 0.959,-5.517 -0.44,-8.035 -0.48,-1.48 -2.838,-2.479 -3.758,-3.998 0,-1 -0.48,-3.518 -0.96,-3.998 -1.398,-2.518 -5.636,-2.518 -7.035,-5.516 -1.879,-5.517 1.879,-5.517 -3.318,-8.515 -4.677,-2.998 -14.551,-8.035 -15.99,-14.551 z m 10.353,30.541 c -0.44,2.518 -2.358,6.556 -1.399,9.554 0.48,1 2.359,0 2.359,0.52 0.48,1 0.92,2.518 1.399,3.518 1.439,4.517 -0.92,13.072 -6.596,12.072 2.358,-0.52 4.717,0.48 5.676,2.479 0,-3.998 1.4,-7.036 4.678,-8.515 -1.88,-3.038 -1.88,-6.036 -2.32,-9.074 -0.479,-3.998 -0.959,-6.516 -1.918,-10.034 -0.44,-3.518 0.48,-4.518 -1.879,-7.036 -1.879,-2.039 -3.758,-1 -6.596,-2.039 1.92,2.519 6.156,3.518 5.677,7.076 z m -149.469,19.068 c -3.798,4.997 -1.919,11.034 -2.359,17.03 0,1.999 -0.48,6.036 -1.879,7.516 -1.918,1.998 -4.237,1.519 -6.156,2.998 2.838,-2.479 7.076,-2.479 10.394,-1.48 -1.44,-4.517 -3.318,-9.034 2.318,-10.033 -2.318,-3.518 -1.399,-4.997 -1.399,-8.515 -0.48,-2.998 -1.879,-6.996 -0.92,-10.034 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1062" />
+ <path
+ d="m 117.649,122.206 c 0.96,-2.998 -0.92,-6.516 -0.44,-9.514 0.44,-3.998 1.879,-5.517 4.197,-8.515 -6.076,-2.519 -4.677,-6.036 -4.197,-11.553 0.44,-4.997 -2.359,-5.517 -4.717,-10.034 -2.838,-6.516 -2.838,-17.03 -3.278,-24.065 0,-7.996 -2.838,-14.032 -8.955,-19.029 -2.798,-2.518 -7.035,-7.036 -10.793,-7.036 -5.677,-0.52 -9.435,6.037 -11.313,11.034 -1.4,4.997 -4.238,17.549 -3.278,23.066 l 9.874,48.13 1.878,1.52 c 4.238,3.477 1.88,5.516 -0.48,7.515 0.48,1 0.96,1.48 1.88,1.999 h 1.879 c 1.439,0 2.838,0 3.757,0.52 0.48,0 1.44,0.48 2.359,0.48 0,3.517 -2.359,7.035 -1.88,10.513 2.84,-0.48 5.638,-1 7.077,-3.998 -0.96,2.998 -1.44,7.036 -1.44,9.514 1.44,-1.998 2.36,-4.996 2.839,-5.996 3.278,-6.036 13.632,-8.515 15.03,-14.551 z m 3.318,47.771 c 2.798,5.996 3.717,13.032 6.076,19.028 2.798,6.037 4.197,10.554 4.197,17.55 0.48,5.037 -0.48,13.072 -3.757,17.07 -3.238,3.997 -8.875,6.036 -12.633,9.514 6.117,-5.997 13.592,1 17.79,-6.996 3.757,-7.036 4.197,-14.551 4.197,-22.067 0,-8.554 -4.677,-10.553 -7.475,-17.549 -2.799,-6.036 -4.678,-14.551 -9.834,-18.589 z m 46.931,20.388 c 1.4,4.037 4.198,18.069 -2.358,16.55 0,3.517 0.92,6.516 -0.48,10.034 -1.4,-2 -2.838,-6.037 -5.157,-2.519 1.879,1.999 0,1.999 0,3.518 0.44,1.999 0.44,3.997 0.92,5.996 -6.117,1 -7.516,6.516 -10.794,11.034 -3.798,4.517 -8.954,7.515 -9.434,14.51 1.439,-4.996 -0.48,-11.512 2.838,-15.51 0,0.48 2.798,0 3.758,-1 1.879,-1.518 1.399,-3.997 2.358,-6.036 2.359,-4.997 2.799,-2.478 6.117,-5.996 3.278,-3.518 0.92,-7.036 0,-11.513 4.237,2.479 3.757,-4.037 2.798,-6.516 4.717,0 6.596,-1 6.116,-5.517 -0.48,-2.518 -2.358,-8.514 -3.278,-10.513 2.799,1.999 5.637,0.48 7.516,-1.04 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1064" />
+ <path
+ d="m 166.06,187.846 c -0.48,-1.959 -1.4,-5.477 -0.48,-7.435 0.96,-2.519 3.318,-2.999 3.757,-4.997 0.96,-3.478 -3.278,-6.476 1.88,-8.475 -2.32,0 -4.678,1.999 -6.557,-1 1.4,5.997 -4.717,8.995 -1.879,14.472 z m 11.752,-26.544 c -0.96,4.997 -3.318,12.992 3.278,14.991 3.318,1 11.753,-9.474 13.192,-2.998 2.359,-3.998 5.157,-3.478 8.915,-4.477 1.439,-0.52 1.879,-2.999 3.798,-2.519 1.878,0.52 2.798,3.518 2.798,4.997 0.96,-1.999 3.318,-7.515 5.636,-8.515 5.197,-1.479 4.238,3.038 5.677,6.037 1.4,-2 1.879,-5.517 4.237,-5.517 2.799,-0.52 4.198,2.998 4.678,4.997 1.878,-1.999 1.878,-8.515 4.717,-8.515 2.358,-0.48 3.757,2.998 3.278,5.037 2.838,-3.038 -0.48,-9.514 3.318,-11.513 0.92,1.48 1.399,3.478 1.399,4.477 1.399,-4.997 0.92,-7.475 6.596,-6.995 4.677,0 6.116,0.999 7.036,5.996 5.636,-4.997 6.596,4.997 6.596,8.515 3.757,-4.517 5.156,-8.995 2.358,-13.992 -2.838,-4.517 -4.717,-9.514 -6.116,-15.03 -1.4,1.998 -3.758,7.995 -6.116,7.995 -3.318,0 -4.238,-7.476 -5.197,-9.515 -1.4,2.04 -3.278,10.034 -5.637,10.514 -4.237,1.519 -6.596,-4.477 -7.995,-7.476 -1.879,2.999 -1.4,9.475 -4.717,11.993 -4.677,3.998 -4.198,-1.519 -8.435,-2.998 -1.879,7.515 -2.359,10.993 -9.914,12.512 -1.879,0 -1.879,0 -3.758,0.48 -1.879,0.52 -3.757,1.999 -5.636,2.519 -9.395,3.997 -19.269,1.479 -21.627,-9.515 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1066" />
+ <path
+ d="m 263.84,161.782 c 4.238,-4.477 13.192,3.518 16.03,6.516 4.238,4.038 5.677,8.555 5.197,14.031 0,5.517 -0.48,14.552 -3.318,19.549 -0.92,1.998 -3.757,5.037 -6.116,6.516 -2.359,1.519 -6.156,1.519 -7.076,3.997 6.117,-1.479 14.631,-1 16.99,-7.995 2.359,-7.515 2.359,-16.03 2.838,-23.546 0.44,-8.035 -3.797,-11.513 -9.914,-16.03 -2.838,-2.518 -10.873,-12.552 -13.711,-15.03 -2.799,-3.039 -0.44,1.998 -5.197,1.478 z m 48.93,57.645 c 0.92,5.517 5.157,13.552 1.88,18.549 -1.88,3.038 -15.112,7.515 -13.193,0 5.157,1 5.637,-3.998 7.516,-7.516 2.838,-4.997 2.838,-3.518 1.919,-9.034 -0.96,-8.515 3.757,-17.03 2.798,-25.585 z M 292.583,79.112 c 3.757,7.036 10.353,8.555 10.793,18.07 0.96,7.035 -0.44,15.07 1.879,22.066 1.4,6.036 4.717,11.073 7.036,16.59 0.96,1.479 4.237,5.996 4.237,7.515 0.44,2.998 -2.358,4.517 -1.879,9.035 -6.116,-0.52 -1.399,5.516 -0.48,8.514 -2.358,-2.478 -7.035,-4.996 -7.955,-8.514 7.956,-2.519 2.799,-11.034 -1.439,-14.032 5.197,-9.034 -3.278,-12.073 -7.955,-17.59 3.758,-4.516 1.879,-8.034 -1.879,-11.552 5.157,-5.997 4.238,-26.584 -2.358,-31.621 z M 39.536,63.601 c 3.318,1.52 5.197,1.52 7.555,5.037 1.88,2.479 2.359,5.477 4.238,7.996 1.399,1.998 3.278,3.997 4.717,6.476 1.4,1.519 4.677,5.996 6.596,7.995 0.92,-5.997 -2.838,-9.474 -2.359,-14.991 0.44,-3.998 2.359,-8.475 3.758,-11.993 1.879,-4.997 3.278,-8.515 6.116,-11.993 3.278,-3.517 7.516,-7.995 6.596,-14.031 -1.399,6.516 -7.075,15.51 -14.59,12.512 -2.839,5.997 -4.238,7.516 -10.354,7.516 2.798,2.478 5.636,6.996 4.237,11.513 -1.879,-1.999 -5.197,-4.517 -7.555,-5.037 -3.278,-0.48 -5.637,1.519 -8.955,-1.999 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1068" />
+ <path
+ d="m 111.053,226.023 c -1.84,0.52 -3.278,2.998 -3.278,3.998 m 153.267,-88.747 c 1.439,7.556 13.672,16.07 17.909,22.067 3.318,4.517 10.833,9.035 12.233,15.03 M 121.446,164.94 c 2.839,4.517 5.197,10.514 7.076,15.03 0.92,2.52 1.4,4.998 2.359,7.516 1.399,2.519 2.798,2.999 4.677,5.517 5.157,6.996 0.48,27.503 -2.798,35.538 -0.48,1.48 -0.96,2.999 -1.88,3.478 M 52.288,6.396 c -3.278,1.52 -7.955,7.076 -9.354,10.594 -1.879,3.518 -6.076,3.997 -7.515,4.997 m 100.019,222.585 c -1.839,0.52 -2.319,3.038 -3.278,4.557 m -1.839,-7.995 c -3.278,0 -7.036,1.519 -7.995,4.957 m -11.673,-25.505 c -1.879,1 -4.237,1 -6.156,2.959 m 168.378,-16.55 c -2.319,0.52 -5.597,1.519 -6.077,3.997 m 2.799,-9.514 c -1.92,0 -3.838,1.04 -5.277,2.558 m 38.137,30.542 c -1.88,2.039 -3.758,4.037 -3.758,6.556 m -3.278,-9.594 c -1.839,1.559 -4.637,2.558 -5.117,5.596 m 21.986,-3.997 c -0.919,1.519 -1.358,2.518 -1.838,3.997 M 181.17,151.828 c -1.399,0.52 -4.717,4.038 -6.116,5.037 2.358,2.518 0.96,10.554 -2.838,11.553 0.48,2.039 -0.48,2.518 0.48,4.517 m -52.169,-7.595 c 0.92,-4.477 -5.197,-3.998 -7.076,-6.516 1.44,-1.48 3.318,-3.478 1.88,-5.477 -1.88,0.48 -3.759,0 -5.158,-1.519 1.4,-1.999 2.359,-4.997 0.48,-7.036 -1.919,1.52 -3.798,1.04 -6.156,0.52 M 11.473,32.94 c 0.44,7.076 -3.358,11.593 -8.595,9.075"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1070" />
+ <path
+ d="m 9.514,39.976 c 0.96,-1 2.359,-6.476 1.44,-7.955 -0.96,-1.52 -4.718,-1.52 -6.637,-1 -2.358,1 -3.318,2.998 -2.838,8.475 0,1.999 0.48,2.998 0.48,3.958 l 1.439,-0.96 c 2.359,0 4.717,0 6.116,-2.518 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1072" />
+ <path
+ d="m 55.566,32.54 c -2.798,-1.479 -4.197,-5.996 -7.035,-7.995 -2.799,-1.999 -2.799,0.52 -4.718,3.518"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1074" />
+ <path
+ d="M 52.848,29.102 C 49.09,38.137 42.454,27.104 45.772,25.584 m 11.233,0.96 C 55.606,22.067 50.01,18.549 46.692,19.548 m -33.98,39.136 c 3.318,-1.998 4.278,0.96 6.636,2.439 3.318,1.959 6.157,-0.48 8.955,0.52"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1076" />
+ <path
+ clip-path="url(#a)"
+ d="m 65,104.337 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.969,73.755 47.131,72.756 44.333,69.238 41.975,67.239 35.379,66.24 33.5,66.24 23.626,66.24 16.59,65.72 8.595,57.685 6.715,55.207 5.757,52.168 4.837,48.69 3.397,44.653 2,45.652 1.52,39.656 1.04,33.14 2,31.621 6.237,30.621 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.995,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.88,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.551 -1.4,6.517 -2.319,17.03 -1.879,23.546 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.36,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.839,25.544 -0.959,3.518 0,4.518 -2.358,8.035 -1.879,2.519 -9.874,3.998 -13.152,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.037 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.517 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.999 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.518 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.92,1.48 -0.92,2.479 -0.479,-0.48 -0.958,-0.48 -1.438,-0.48 -0.44,0.48 -0.44,1 -0.92,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.036,5.476 -7.036,5.476 0,0 -3.278,-2.998 -6.116,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1078" />
+ <path
+ d="m 308.533,99.18 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 v 0.52 c 0,0 0,0 0,0 v 1.519"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1080" />
+ <path
+ d="m 95.102,24.905 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.551 0,3.038 0,5.517 0.48,8.555 0.48,3.518 0,7.036 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.92,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.196,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.076,-1.519 -1.88,1.52 -0.92,3.998 -0.44,6.036 -1.44,0 -2.839,-0.52 -3.798,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.514,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.96,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1082" />
+ <path
+ d="m 81.91,41.055 c -1.399,4.038 -3.278,8.035 -5.596,11.033 -1.88,2.519 -4.238,5.037 -5.157,7.516 -0.48,1.519 0,3.038 -0.48,4.517 -0.44,1.52 -2.318,2.998 -2.798,4.517 -0.48,1 -0.48,2.519 -0.48,3.518 -0.44,1.48 -1.879,2.519 -1.879,3.998 0,1.519 1.44,2.998 1.44,4.517 0.44,1.52 0.44,2.998 0.44,4.517 0,3.518 -0.92,6.996 -0.44,10.034 0,2 0.919,3.478 0.919,5.517 0,1.999 -0.92,3.478 -0.48,5.477 0.48,1.519 0.96,2.038 1.4,3.517 0.959,1.52 0,3.518 0.479,5.037 3.278,-0.999 2.798,2.479 3.278,4.478 0.96,-2 3.758,-2.479 5.637,-2 -0.96,-0.479 -3.758,-0.998 -4.678,-1.478 -1.878,-1.52 0,-6.037 1.4,-7.516 -1.4,0 -4.238,-0.52 -4.678,-2.038 -0.959,-2 3.278,-4.478 3.718,-5.997 -1.879,-0.52 -3.278,-1 -3.718,-2.998 -1.439,-3.518 1.4,-5.037 1.84,-8.035 0,-1.999 -1.4,-1.48 -2.32,-3.518 -0.959,-1.999 0,-4.477 1.88,-5.996 -2.359,-3.518 -2.839,-5.517 -0.48,-9.035 0.92,-1.479 0.92,-0.48 0.92,-1.999 0.479,-1.998 -1.4,-3.517 0.959,-5.516 0.92,-1 1.879,-0.48 2.318,-1.999 0.48,-1 0,-3.998 0.96,-5.517 0.48,-1.998 0.92,-4.517 1.879,-6.995 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1084" />
+ <path
+ d="m 95.142,24.945 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.55 0,3.04 0,5.518 0.48,8.556 0.48,3.518 0,7.035 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.919,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.197,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.077,-1.519 -1.878,1.52 -0.919,3.998 -0.44,6.036 -1.438,0 -2.838,-0.52 -3.797,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.515,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.959,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1086" />
+ <path
+ d="m 103.058,54.087 c -0.48,2.998 0,5.997 0,9.035 v 9.994 c 0.44,6.556 1.399,13.551 3.278,19.588 0.48,1 0.959,1.999 1.399,3.478 0,1.519 0,1 -0.44,2.518 -0.48,1.999 -0.96,2.998 -0.96,5.037 0.48,1.999 0.96,2.998 0.96,4.477 -0.48,0.52 -1.44,1.52 -1.44,2.519 -0.439,1 0,2.518 -0.439,2.998 -0.48,1 -1.919,1 -2.838,2.039 -0.48,1.479 0,2.998 -0.96,4.477 -1.399,-1 -2.798,0.52 -3.757,1 -0.92,-1 -1.88,-1.48 -2.839,-1 0.96,-1 3.798,-2.478 4.718,-3.478 0.959,-2.039 0,-4.517 -0.92,-7.036 2.359,0 3.278,-2.518 3.278,-4.996 0,-2.04 -0.92,-2.04 -1.879,-3.518 -0.96,-2.519 1.4,-4.038 1.88,-6.516 0.959,-4.038 -0.92,-5.517 -2.84,-8.036 4.238,-4.517 1.92,-8.035 0.48,-12.512 -0.919,-3.038 0.96,-5.517 0.48,-9.034 0,-2.999 1.4,-6.037 1.4,-9.035 0.48,-1.999 0.959,-4.997 0.48,-7.036 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1088" />
+ <path
+ d="m 45.253,24.545 c -1.88,3.478 2.838,10.914 6.116,6.956 2.318,-2.479 -3.758,-9.954 -5.637,-6.956 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1090" />
+ <path
+ d="m 45.692,26.944 c 0,-0.52 0.44,-1 0.92,-1 0.52,0 0.92,0.48 0.92,1 0,0.56 -0.4,1 -0.92,1 -0.48,0 -0.92,-0.44 -0.92,-1 z"
+ fill="#ffffff"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1092" />
+ <path
+ d="m 2.878,39.016 c 0.96,0 2.399,0.48 3.358,0.48 0.96,0 1.44,-1.479 2.399,-1.999"
+ fill="none"
+ stroke="#ffffff"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1094" />
+ <path
+ d="m 80.111,31.46 c -1.439,-0.519 -3.358,0 -3.837,2.08 1.919,0.48 3.837,-1.04 5.277,0.48 -0.96,2.078 -2.879,3.078 -4.798,3.078 M 96.981,26.064 c -2.798,-1.519 -7.036,3.038 -1.879,3.518 1.88,0.52 3.278,-1.519 4.238,1 0.44,1.998 -3.278,5.036 -4.238,6.516 M 47.171,20.987 c -0.48,-3.438 5.677,-4.437 2.399,1.96 M 26.944,63.082 c 0,-1 0.96,-3.478 -0.48,-3.478 -1.919,-0.52 -2.878,2.478 -2.399,3.478 m 82.271,86.348 c 0,-2.04 0.48,-4.558 0.959,-6.637 2.319,0.52 2.319,4.118 1.879,6.636 m 71.516,4.917 c -3.717,-6.915 -6.556,0.48 -2.798,2.439 m 83.709,-12.952 c 0.92,-0.48 1.84,-1 2.719,-1.999 m 7.995,67.159 c -0.44,-4.037 -6.556,-4.557 -3.718,0 m 33.86,28.143 c -0.96,-1.04 -1.92,-1.599 -2.879,-1.599 m -5.116,-1.399 c -2.359,-6.116 -6.157,1.56 -2.359,2.039"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1096" />
+ <path
+ d="m 267.638,200.039 c -1.4,1.999 1.399,4.997 0.48,5.996 -1.88,1.999 -3.798,-1 -3.798,-2.478 m -155.146,16.07 c 0,1.479 0.44,2.478 0.44,3.918 -1.4,-0.48 -2.319,-0.96 -3.278,-2.439 m 1.838,4.917 c 0.52,1.52 1,2.518 2,3.518 m 18.868,10.514 c 2.318,6.036 -2.359,2.518 -4.238,-0.52"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1098" />
+ <path
+ clip-path="url(#a)"
+ d="m 135.078,244.092 c -0.44,1.999 0.96,2.519 1.4,3.998 -2.32,0.48 -3.718,-1 -5.597,-1.48"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1100" />
+ <path
+ d="m 121.926,242.573 c 0.48,2.039 1.879,3.038 3.278,3.518"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1102" />
+ </g>
+ </g>
+ <g
+ id="layer2"
+ inkscape:label="Layer 2"
+ clip-path="none"
+ inkscape:groupmode="layer"
+ transform="matrix(0.5,0,0,0.5,0,150)">
+ <rect
+ style="opacity:0.8;fill:#ffffff;stroke-width:2.06559;stop-color:#000000"
+ id="rect1552"
+ width="100"
+ height="32"
+ x="0"
+ y="-300" />
+ <g
+ aria-label="MIT"
+ transform="scale(0.9922273,1.0078336)"
+ id="text1448"
+ style="font-size:36.0397px;line-height:1.25;font-family:'Arial Black';-inkscape-font-specification:'Arial Black, ';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#a40000;stroke-width:1.68935">
+ <path
+ d="m 15.117469,-294.69153 h 10.488115 l 4.047428,15.69697 4.029829,-15.69697 h 10.452921 v 25.79794 h -6.511079 v -19.67401 l -5.050485,19.67401 h -5.895166 l -5.032887,-19.67401 v 19.67401 h -6.528676 z"
+ id="path2044" />
+ <path
+ d="m 49.538199,-294.69153 h 7.989269 v 25.79794 h -7.989269 z"
+ id="path2046" />
+ <path
+ d="m 61.434115,-294.69153 h 24.231771 v 6.37029 h -8.130049 v 19.42765 h -7.971672 v -19.42765 h -8.13005 z"
+ id="path2048" />
+ </g>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="Layer 3" />
+</svg>
diff --git a/share/extensions/other/clipart/licenses/perm-by.svg b/share/extensions/other/clipart/licenses/perm-by.svg
new file mode 100644
index 0000000..b474dd4
--- /dev/null
+++ b/share/extensions/other/clipart/licenses/perm-by.svg
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="1.2-alpha1 (8b0d57f509, 2022-03-02, custom)"
+ width="48"
+ height="48"
+ version="1.0"
+ sodipodi:docname="perm-by.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/doctormo/Desktop/small-pd.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ 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/">
+ <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:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs5">
+ <foreignObject
+ requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/"
+ x="0"
+ y="0"
+ width="1"
+ height="1"
+ id="foreignObject8" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:window-height="807"
+ inkscape:window-width="1472"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:zoom="1.4717"
+ inkscape:cx="6.4551199"
+ inkscape:cy="103.62166"
+ inkscape:window-x="64"
+ inkscape:window-y="20"
+ inkscape:current-layer="svg2"
+ inkscape:window-maximized="1"
+ showguides="false"
+ inkscape:pagecheckerboard="true"
+ inkscape:deskcolor="#d3d3d3" />
+ <g
+ id="g3325"
+ transform="matrix(1.5682857,0,0,1.5682857,-45.004568,-0.3084253)"
+ style="stroke-width:0.349094">
+ <circle
+ id="path3319"
+ style="fill:#ffffff;stroke:#000000;stroke-width:2.47001;stroke-linecap:round;stroke-linejoin:round"
+ cx="54.028732"
+ cy="-37.690372"
+ r="10.621033"
+ transform="matrix(1.2907631,0,0,1.2907631,-25.738294,64.149342)" />
+ <g
+ transform="translate(-8.3313295,52.164232)"
+ id="g3321">
+ <path
+ d="m 54.475669,-44.112479 c 0,1.184305 -0.960069,2.144374 -2.144375,2.144374 -1.184305,0 -2.144375,-0.960069 -2.144375,-2.144374 0,-1.184306 0.96007,-2.144375 2.144375,-2.144375 1.184306,0 2.144375,0.960069 2.144375,2.144375 z"
+ style="fill:#000000"
+ id="path2838"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 50.112832,-27.071611 h 4.437001 v -7.130405 h 1.341335 c 0,0 -4.91e-4,-5.09567 0,-5.897662 -0.0013,-0.211567 0.0191,-0.632908 -0.287804,-0.939811 -0.306903,-0.306903 -0.721155,-0.288301 -0.939812,-0.287805 -0.218652,4.91e-4 -4.445792,4.91e-4 -4.664444,0 -0.218652,-4.96e-4 -0.632908,-0.0191 -0.939811,0.287805 -0.306908,0.306903 -0.286489,0.728244 -0.287806,0.939811 4.93e-4,0.801992 0,5.897662 0,5.897662 h 1.341341 z"
+ style="fill:#000000"
+ id="path3572"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+</svg>
diff --git a/share/extensions/other/clipart/licenses/perm-nc.svg b/share/extensions/other/clipart/licenses/perm-nc.svg
new file mode 100644
index 0000000..3bca9e2
--- /dev/null
+++ b/share/extensions/other/clipart/licenses/perm-nc.svg
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="1.2-alpha1 (8b0d57f509, 2022-03-02, custom)"
+ width="48"
+ height="48"
+ version="1.0"
+ sodipodi:docname="perm-nc.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/doctormo/Desktop/small-pd.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ 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/">
+ <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:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs5">
+ <foreignObject
+ requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/"
+ x="0"
+ y="0"
+ width="1"
+ height="1"
+ id="foreignObject8" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:window-height="807"
+ inkscape:window-width="1472"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:zoom="1.4717"
+ inkscape:cx="63.53197"
+ inkscape:cy="79.160155"
+ inkscape:window-x="64"
+ inkscape:window-y="20"
+ inkscape:current-layer="svg2"
+ inkscape:window-maximized="1"
+ showguides="false"
+ inkscape:pagecheckerboard="true"
+ inkscape:deskcolor="#d3d3d3" />
+ <g
+ transform="matrix(2.8641615,0,0,2.8641615,-176.49808,-8.3421525)"
+ id="g2841"
+ style="stroke-width:0.349142">
+ <g
+ id="g3344"
+ transform="matrix(0.5475549,0,0,0.5475549,45.131672,27.061294)">
+ <circle
+ r="10.621033"
+ cy="-37.690372"
+ cx="54.028732"
+ transform="matrix(1.2907631,0,0,1.2907631,-24.316921,19.849894)"
+ id="path3342"
+ style="color:#000000;overflow:visible;color-interpolation-filters:linearRGB;fill:#ce5c00;stroke:#000000;stroke-width:2.47001;stroke-linecap:round;marker:none;image-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:53.8144px;line-height:100%;font-family:'Arial Narrow';text-align:start;text-anchor:start;fill:#000000"
+ d="m 68.347895,13.042872 c 0.534935,0.748147 2.167565,0.802173 2.728104,0.484958 0.205745,-0.116433 0.257136,-0.453455 0.257141,-0.681932 -5e-6,-0.156795 -0.04127,-0.279992 -0.123795,-0.369593 -0.08712,-0.0896 -0.30873,-0.317014 -0.565486,-0.384215 -1.302141,-0.335991 -2.204242,-0.755651 -2.557285,-1.060288 -0.440161,-0.380789 -0.51122,-0.629494 -0.51122,-1.2925255 0,-0.6630209 0.190658,-1.2187262 0.621648,-1.6174449 0.430988,-0.3987052 1.05684,-0.5980609 1.877556,-0.5980679 0.784031,7e-6 1.88669,0.2069574 2.424306,0.8451414 l -0.896336,0.9750272 c -0.50552,-0.4244029 -0.881489,-0.4627499 -1.50046,-0.4627556 -0.389727,5.7e-6 -0.592609,0.056005 -0.757667,0.1679966 -0.165062,0.1075235 -0.247591,0.2486406 -0.247589,0.4233514 -2e-6,0.1568021 0.07565,0.2867193 0.226957,0.3897524 0.151302,0.1075227 0.546754,0.2687989 1.335376,0.4838309 0.8849,0.241919 1.485534,0.535353 1.801904,0.880302 0.311774,0.344956 0.467664,0.804147 0.46767,1.377572 -6e-6,0.689908 -0.243011,1.258856 -0.729015,1.706846 -0.481429,0.447992 -1.074035,0.796171 -1.926841,0.796171 -1.097743,-10e-7 -2.563006,-0.387795 -2.967262,-1.104583"
+ id="text1367-0"
+ sodipodi:nodetypes="cssscssssccscscscscsc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#000000;stroke-width:1.74571"
+ d="M 77.095393,13.39675 76.470518,14.767318 63.200249,8.788107 63.825124,7.4175399 Z"
+ id="rect2247"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#000000"
+ d="m 69.575608,6.328068 v 1.7764877 h 0.843629 V 6.328068 Z m 0,8.330835 v 1.598027 h 0.843629 v -1.598027 z"
+ id="rect2278-1" />
+ </g>
+</svg>
diff --git a/share/extensions/other/clipart/licenses/perm-nd.svg b/share/extensions/other/clipart/licenses/perm-nd.svg
new file mode 100644
index 0000000..aa89ad2
--- /dev/null
+++ b/share/extensions/other/clipart/licenses/perm-nd.svg
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="1.2-alpha1 (8b0d57f509, 2022-03-02, custom)"
+ width="48"
+ height="48"
+ version="1.0"
+ sodipodi:docname="perm-nd.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/doctormo/Desktop/small-pd.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ 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/">
+ <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:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs5">
+ <foreignObject
+ requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/"
+ x="0"
+ y="0"
+ width="1"
+ height="1"
+ id="foreignObject8" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:window-height="807"
+ inkscape:window-width="1472"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:zoom="1.4717"
+ inkscape:cx="63.53197"
+ inkscape:cy="79.160155"
+ inkscape:window-x="64"
+ inkscape:window-y="20"
+ inkscape:current-layer="svg2"
+ inkscape:window-maximized="1"
+ showguides="false"
+ inkscape:pagecheckerboard="true"
+ inkscape:deskcolor="#d3d3d3" />
+ <g
+ id="g4105"
+ transform="matrix(2.8641615,0,0,2.8641615,-206.74641,-15.465032)"
+ style="stroke-width:0.349143">
+ <g
+ id="g3344"
+ transform="matrix(0.5475549,0,0,0.5475549,55.692639,29.548189)">
+ <circle
+ r="10.621033"
+ cy="-37.690372"
+ cx="54.028732"
+ transform="matrix(1.2907631,0,0,1.2907631,-24.316921,19.849894)"
+ id="path3342"
+ style="color:#000000;overflow:visible;fill:#fe2424;stroke:#000000;stroke-width:2.47;stroke-linecap:round;marker:none;enable-background:accumulate" />
+ </g>
+ <g
+ style="font-weight:bold;font-size:14.585px;font-family:'Trebuchet MS';-inkscape-font-specification:'Trebuchet MS Bold';letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000"
+ id="text6606"
+ transform="translate(35.273334,3.8994101)">
+ <path
+ d="M 41.8,9.033 V 7.469 h 6.98 v 1.564 z m 0,3.257 v -1.56 h 6.98 v 1.56 z"
+ id="path6063"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+</svg>
diff --git a/share/extensions/other/clipart/licenses/perm-ne.svg b/share/extensions/other/clipart/licenses/perm-ne.svg
new file mode 100644
index 0000000..5d16f83
--- /dev/null
+++ b/share/extensions/other/clipart/licenses/perm-ne.svg
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="1.2-alpha1 (8b0d57f509, 2022-03-02, custom)"
+ width="48"
+ height="48"
+ version="1.0"
+ sodipodi:docname="perm-ne.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/doctormo/Desktop/small-pd.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ 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/">
+ <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:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs5">
+ <foreignObject
+ requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/"
+ x="0"
+ y="0"
+ width="1"
+ height="1"
+ id="foreignObject8" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:window-height="807"
+ inkscape:window-width="1472"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:zoom="1.4717"
+ inkscape:cx="78.480669"
+ inkscape:cy="18.006387"
+ inkscape:window-x="64"
+ inkscape:window-y="20"
+ inkscape:current-layer="svg2"
+ inkscape:window-maximized="1"
+ showguides="false"
+ inkscape:pagecheckerboard="true"
+ inkscape:deskcolor="#d3d3d3" />
+ <g
+ id="g3344"
+ transform="matrix(1.5682857,0,0,1.5682857,-47.233683,69.165764)"
+ style="fill:#ffffff;stroke-width:0.349142">
+ <circle
+ r="10.621033"
+ cy="-37.690372"
+ cx="54.028732"
+ transform="matrix(1.2907631,0,0,1.2907631,-24.316921,19.849894)"
+ id="path3342"
+ style="color:#000000;overflow:visible;color-interpolation-filters:linearRGB;stroke:#000000;stroke-width:2.47001;stroke-linecap:round;marker:none;image-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#000000;stroke-width:5"
+ d="M 44.315576,30.028303 42.525834,33.953831 4.51764,16.828405 6.3073829,12.90288 Z"
+ id="rect2247"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ id="path9953"
+ style="opacity:0.8;fill:#000000;stroke-width:5;stop-color:#000000"
+ inkscape:transform-center-y="-4.0093488"
+ d="m 28.435058,8.3588897 c -1.811949,0.1347295 -3.869563,2.4224093 -5.670766,2.6939023 -2.180369,0.328644 -5.488969,-1.746164 -7.330993,-0.534161 -1.739088,1.144271 -0.929741,4.851041 -1.970623,6.653911 -1.102491,1.909587 -4.7870042,3.203529 -4.9879087,5.399355 -0.1896692,2.073112 3.2124387,3.751669 3.9730007,5.689534 0.805584,2.052572 -0.479872,5.738438 1.111635,7.264586 1.502563,1.440858 4.936034,-0.171842 6.925322,0.441765 2.107037,0.649928 4.18836,3.953918 6.373836,3.661167 2.063343,-0.276391 2.941599,-3.966784 4.661636,-5.139493 1.821851,-1.242124 5.702073,-0.809919 6.835814,-2.701121 1.070381,-1.785513 -1.265753,-4.772856 -1.110188,-6.848807 0.164773,-2.198832 2.922806,-4.963727 2.15108,-7.029267 -0.728599,-1.950106 -4.522959,-1.985345 -6.04901,-3.401304 C 31.731511,13.009182 31.290499,9.129993 29.194432,8.44551 28.947066,8.3647313 28.693908,8.3396427 28.435058,8.3588897 Z M 24.00008,15.002694 a 8.9976648,8.9976648 0 0 1 8.996999,8.997 8.9976648,8.9976648 0 0 1 -8.996999,8.996999 8.9976648,8.9976648 0 0 1 -8.997003,-8.996999 8.9976648,8.9976648 0 0 1 8.997003,-8.997 z" />
+</svg>
diff --git a/share/extensions/other/clipart/licenses/perm-notice.svg b/share/extensions/other/clipart/licenses/perm-notice.svg
new file mode 100644
index 0000000..55043a9
--- /dev/null
+++ b/share/extensions/other/clipart/licenses/perm-notice.svg
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="1.2-alpha1 (8b0d57f509, 2022-03-02, custom)"
+ width="48"
+ height="48"
+ version="1.0"
+ sodipodi:docname="perm-notice.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/doctormo/Desktop/small-pd.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ 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/">
+ <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:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs5">
+ <foreignObject
+ requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/"
+ x="0"
+ y="0"
+ width="1"
+ height="1"
+ id="foreignObject8" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:window-height="807"
+ inkscape:window-width="1472"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:zoom="1.4717"
+ inkscape:cx="-20.724332"
+ inkscape:cy="103.62166"
+ inkscape:window-x="64"
+ inkscape:window-y="20"
+ inkscape:current-layer="g4434"
+ inkscape:window-maximized="1"
+ showguides="false"
+ inkscape:pagecheckerboard="true"
+ inkscape:deskcolor="#d3d3d3" />
+ <g
+ id="g4434"
+ transform="matrix(1.4590285,0,0,1.4590289,-0.40977954,-29.731304)"
+ style="stroke-width:0.979788">
+ <circle
+ r="14.735833"
+ cy="36.826759"
+ cx="16.730156"
+ id="path4394"
+ style="color:#000000;overflow:visible;color-interpolation-filters:linearRGB;fill:#ffffff;stroke:#000000;stroke-width:3.42693;stroke-linecap:round;marker:none;image-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+ <path
+ id="text4416"
+ style="font-weight:bold;line-height:0%;font-family:'Century Schoolbook L';-inkscape-font-specification:'Century Schoolbook L Bold';text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;stroke:#000000"
+ d="M 17.048758 27.603478 C 14.569925 27.603478 12.606038 28.432764 11.15737 30.090685 C 9.708701 31.748606 8.9847445 34.001805 8.9847445 36.850854 C 8.9847445 39.683805 9.7007016 41.929006 11.133274 43.586926 C 12.565846 45.228751 14.505735 46.050037 16.952375 46.050037 C 18.88579 46.050037 20.492334 45.590485 21.772845 44.673908 L 19.783615 42.05953 C 19.77296 42.069431 19.763624 42.080549 19.752826 42.090319 C 19.07678 42.701979 18.1755 43.007292 17.048758 43.007292 C 15.648378 43.007292 14.553775 42.46866 13.765055 41.390206 C 12.992432 40.311753 12.605786 38.814507 12.605786 36.899045 C 12.605786 34.95139 13.008431 33.430146 13.813246 32.335596 C 14.618062 31.241047 15.736664 30.694415 17.169236 30.694415 C 18.592033 30.694415 19.622387 31.209552 20.277576 32.215118 L 22.538551 29.632868 C 22.412103 29.508056 22.282856 29.385819 22.14365 29.270094 C 20.823752 28.159448 19.125183 27.603478 17.048758 27.603478 z " />
+ </g>
+</svg>
diff --git a/share/extensions/other/clipart/licenses/perm-pd.svg b/share/extensions/other/clipart/licenses/perm-pd.svg
new file mode 100644
index 0000000..e8e25ce
--- /dev/null
+++ b/share/extensions/other/clipart/licenses/perm-pd.svg
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="1.2-alpha1 (8b0d57f509, 2022-03-02, custom)"
+ width="48"
+ height="48"
+ version="1.0"
+ sodipodi:docname="perm-pd.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/doctormo/Desktop/small-pd.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ 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/">
+ <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:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs5">
+ <foreignObject
+ requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/"
+ x="0"
+ y="0"
+ width="1"
+ height="1"
+ id="foreignObject8" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:window-height="807"
+ inkscape:window-width="1472"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:zoom="1.4717"
+ inkscape:cx="-20.724332"
+ inkscape:cy="103.62166"
+ inkscape:window-x="64"
+ inkscape:window-y="20"
+ inkscape:current-layer="g4434"
+ inkscape:window-maximized="1"
+ showguides="false"
+ inkscape:pagecheckerboard="true"
+ inkscape:deskcolor="#d3d3d3" />
+ <g
+ id="g4434"
+ transform="matrix(1.4590285,0,0,1.4590289,-0.40977954,-29.731304)"
+ style="stroke-width:0.979788">
+ <circle
+ r="14.735833"
+ cy="36.826759"
+ cx="16.730156"
+ id="path4394"
+ style="color:#000000;overflow:visible;color-interpolation-filters:linearRGB;fill:#73d216;stroke:#000000;stroke-width:3.42693;stroke-linecap:round;marker:none;image-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+ <path
+ id="text4416"
+ style="font-weight:bold;line-height:0%;font-family:'Century Schoolbook L';-inkscape-font-specification:'Century Schoolbook L Bold';text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;stroke:#000000"
+ d="M 17.048758 27.603478 C 14.569925 27.603478 12.606038 28.432764 11.15737 30.090685 C 9.708701 31.748606 8.9847445 34.001805 8.9847445 36.850854 C 8.9847445 39.683805 9.7007016 41.929006 11.133274 43.586926 C 12.565846 45.228751 14.505735 46.050037 16.952375 46.050037 C 18.88579 46.050037 20.492334 45.590485 21.772845 44.673908 L 19.783615 42.05953 C 19.77296 42.069431 19.763624 42.080549 19.752826 42.090319 C 19.07678 42.701979 18.1755 43.007292 17.048758 43.007292 C 15.648378 43.007292 14.553775 42.46866 13.765055 41.390206 C 12.992432 40.311753 12.605786 38.814507 12.605786 36.899045 C 12.605786 34.95139 13.008431 33.430146 13.813246 32.335596 C 14.618062 31.241047 15.736664 30.694415 17.169236 30.694415 C 18.592033 30.694415 19.622387 31.209552 20.277576 32.215118 L 22.538551 29.632868 C 22.412103 29.508056 22.282856 29.385819 22.14365 29.270094 C 20.823752 28.159448 19.125183 27.603478 17.048758 27.603478 z " />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4396"
+ d="M 3.6562595,31.009984 29.804054,42.643536"
+ style="color:#000000;overflow:visible;color-interpolation-filters:linearRGB;fill:#ffffff;stroke:#000000;stroke-width:3.42693;stroke-linecap:round;image-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+ </g>
+</svg>
diff --git a/share/extensions/other/clipart/licenses/perm-sa.svg b/share/extensions/other/clipart/licenses/perm-sa.svg
new file mode 100644
index 0000000..c5a308c
--- /dev/null
+++ b/share/extensions/other/clipart/licenses/perm-sa.svg
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="1.2-alpha1 (8b0d57f509, 2022-03-02, custom)"
+ width="48"
+ height="48"
+ version="1.0"
+ sodipodi:docname="perm-sa.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/doctormo/Desktop/small-pd.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ 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/">
+ <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:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs5">
+ <foreignObject
+ requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/"
+ x="0"
+ y="0"
+ width="1"
+ height="1"
+ id="foreignObject8" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:window-height="807"
+ inkscape:window-width="1472"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:zoom="1.4717"
+ inkscape:cx="6.4551199"
+ inkscape:cy="103.62166"
+ inkscape:window-x="64"
+ inkscape:window-y="20"
+ inkscape:current-layer="svg2"
+ inkscape:window-maximized="1"
+ showguides="false"
+ inkscape:pagecheckerboard="true"
+ inkscape:deskcolor="#d3d3d3" />
+ <g
+ id="g3344-1"
+ transform="matrix(1.5682857,0,0,1.5682857,-47.233687,69.165766)"
+ style="stroke-width:0.349143">
+ <circle
+ id="path3342-7-8"
+ style="fill:#ffffff;stroke:#000000;stroke-width:2.47001;stroke-linecap:round;stroke-linejoin:round"
+ cx="54.028732"
+ cy="-37.690372"
+ r="10.621033"
+ transform="matrix(1.2907631,0,0,1.2907631,-24.316921,19.849894)" />
+ <path
+ id="path2371"
+ style="fill:#000000"
+ d="m 38.983973,-31.217586 h -1.270757 l 2.883314,3.231051 2.883314,-3.231051 h -1.040359 c 0.22538,-1.576313 1.612048,-2.590138 3.213713,-2.463133 0.06331,0.005 0.12419,0 0.188357,0 2.60915,0 3.638167,1.973226 3.723677,4.8828 0.08924,3.036526 -1.670752,4.924122 -3.723677,4.882799 -2.16681,-0.04275 -2.987776,-1.079146 -3.303497,-2.651491 H 38.66949 c 0.636671,3.621667 3.302965,5.745552 7.08513,5.752141 4.281601,0.0075 7.37491,-3.574428 7.37491,-7.983449 0,-4.708303 -3.092243,-7.98345 -7.37491,-7.98345 -0.127153,0 -0.251135,-0.0069 -0.376714,0 -0.03041,0.0017 -0.05655,-4.97e-4 -0.08693,0 -2.676278,0.0445 -6.30698,1.919385 -6.306999,5.563783 z"
+ inkscape:connector-curvature="0" />
+ </g>
+</svg>
diff --git a/share/extensions/other/clipart/licenses/unknown.svg b/share/extensions/other/clipart/licenses/unknown.svg
new file mode 100644
index 0000000..2a96487
--- /dev/null
+++ b/share/extensions/other/clipart/licenses/unknown.svg
@@ -0,0 +1,340 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="50"
+ height="16"
+ viewBox="0 0 50 16"
+ version="1.1"
+ id="svg5"
+ sodipodi:docname="unknown.svg"
+ inkscape:version="1.2-alpha1 (8b0d57f509, 2022-03-02, custom)"
+ inkscape:export-filename="/home/doctormo/Projects/inkscape/extensions/main/other/clipart/licenses/cc-by-sa.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#999999"
+ borderopacity="1"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="2.9434"
+ inkscape:cx="-51.810831"
+ inkscape:cy="28.02881"
+ inkscape:window-width="1472"
+ inkscape:window-height="807"
+ inkscape:window-x="64"
+ inkscape:window-y="20"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer2" />
+ <defs
+ id="defs2">
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect2486"
+ is_visible="true"
+ lpeversion="1"
+ nodesatellites_param=""
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false"
+ satellites_param="" />
+ <color-profile
+ name="AL1706"
+ xlink:href="../../../../../.local/share/icc/edid-a9cf44b399fa09c3fc2589cbaadd3747.icc"
+ id="color-profile580" />
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="a">
+ <path
+ d="M 0.24,1.04 H 322.045 V 255.205 H 0.24 Z"
+ id="path1048" />
+ </clipPath>
+ <inkscape:path-effect
+ effect="fillet_chamfer"
+ id="path-effect2486-3"
+ is_visible="true"
+ lpeversion="1"
+ nodesatellites_param=""
+ unit="px"
+ method="auto"
+ mode="F"
+ radius="0"
+ chamfer_steps="1"
+ flexible="false"
+ use_knot_distance="true"
+ apply_no_radius="true"
+ apply_with_radius="true"
+ only_selected="false"
+ hide_knots="false"
+ satellites_param="" />
+ </defs>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-51.633091,-21.31349)"
+ sodipodi:insensitive="true"
+ style="display:none">
+ <g
+ inkscape:label="dog.svg"
+ transform="matrix(0.24767307,0,0,0.24767307,51.414234,28.015162)"
+ id="g1104">
+ <path
+ d="m 308.493,99.14 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1058" />
+ <path
+ clip-path="url(#a)"
+ d="m 64.96,104.297 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.929,73.715 47.091,72.716 44.293,69.198 41.935,67.2 35.34,66.2 33.46,66.2 23.586,66.2 16.55,65.68 8.555,57.645 6.676,55.167 5.717,52.128 4.797,48.651 3.358,44.613 1.959,45.612 1.479,39.616 0.999,33.1 1.959,31.581 6.196,30.581 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.996,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.879,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.552 -1.4,6.516 -2.319,17.03 -1.879,23.545 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.359,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.838,25.544 -0.96,3.518 0,4.518 -2.36,8.035 -1.878,2.519 -9.873,3.998 -13.151,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.036 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.518 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.998 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.519 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.919,1.48 -0.919,2.479 -0.48,-0.48 -0.96,-0.48 -1.44,-0.48 -0.439,0.48 -0.439,1 -0.919,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.035,5.476 -7.035,5.476 0,0 -3.279,-2.998 -6.117,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1060" />
+ <path
+ d="m 147.31,59.604 c 16.95,3.038 32.461,6.556 49.85,5.557 21.627,-1.52 42.775,-5.037 64.401,0 -8.434,-2 -18.788,-2 -21.626,8.554 0.48,-3.038 -0.92,-6.036 -3.758,-7.035 -4.198,-2.04 -5.637,1.998 -9.394,2.998 -5.637,1.519 -7.036,-2.519 -12.673,4.517 -3.318,-8.555 -5.197,-1.999 -10.833,-1.48 -2.838,0 -3.758,-2.518 -6.116,-3.037 -4.678,-1 -6.557,3.518 -10.794,3.518 -1.44,0 -1.44,-2.999 -3.318,-2.999 -1.4,-0.52 -2.798,0.48 -4.677,0 -2.359,0 -2.838,-2.038 -5.637,-1.519 -3.797,0.52 -5.676,6.037 -9.434,6.516 -0.92,-6.516 0,-7.515 -5.157,-10.553 z M 47.531,15.39 C 48.011,3.959 77.633,1.96 82.79,7.956 80.471,5.957 74.835,6.437 73.875,9.955 c -2.838,-2.998 -5.636,-1.999 -7.995,0 -2.358,-1.999 -4.677,-0.52 -7.036,-1 z m -32.86,15.032 c 4.238,-2.479 9.394,-2.479 13.632,-3.478 4.717,-1 8.475,-3.478 12.672,-4.997 -2.318,2.518 -5.636,5.996 -9.394,7.995 -5.637,2.958 -10.794,-0.52 -16.43,1.999 z m 105.776,126.883 c 6.596,9.554 10.873,20.067 15.55,30.621 2.839,5.996 5.677,10.993 5.197,18.03 0,8.034 -3.278,16.03 -4.237,23.545 0.96,-3.478 4.237,-12.513 8.955,-11.513 -0.96,-1.52 -2.359,-3.998 -2.359,-5.996 0,-3.039 3.278,-4.518 3.278,-7.036 0,-1.999 -3.278,-5.517 -3.758,-8.035 0,-2.479 0.48,-4.997 0.96,-6.996 -5.197,-1.999 -6.117,-7.516 -3.798,-12.553 -4.237,-0.999 -7.515,-2.998 -9.394,-7.515 -0.96,-1.999 0,-3.998 -1.44,-5.517 -1.399,-2.518 -3.757,-2.998 -5.156,-5.516 z M 264.84,144.353 c 7.995,10.553 19.308,17.549 26.823,28.582 3.758,4.997 7.995,11.513 10.354,17.55 1.4,2.478 3.278,5.996 3.278,8.994 0.48,3.518 -1.879,7.036 -1.4,10.514 1.88,-2 3.759,-6.476 3.759,-8.995 0.44,-3.518 -2.359,-3.518 -3.318,-7.515 -0.92,-3.518 0.959,-5.517 -0.44,-8.035 -0.48,-1.48 -2.838,-2.479 -3.758,-3.998 0,-1 -0.48,-3.518 -0.96,-3.998 -1.398,-2.518 -5.636,-2.518 -7.035,-5.516 -1.879,-5.517 1.879,-5.517 -3.318,-8.515 -4.677,-2.998 -14.551,-8.035 -15.99,-14.551 z m 10.353,30.541 c -0.44,2.518 -2.358,6.556 -1.399,9.554 0.48,1 2.359,0 2.359,0.52 0.48,1 0.92,2.518 1.399,3.518 1.439,4.517 -0.92,13.072 -6.596,12.072 2.358,-0.52 4.717,0.48 5.676,2.479 0,-3.998 1.4,-7.036 4.678,-8.515 -1.88,-3.038 -1.88,-6.036 -2.32,-9.074 -0.479,-3.998 -0.959,-6.516 -1.918,-10.034 -0.44,-3.518 0.48,-4.518 -1.879,-7.036 -1.879,-2.039 -3.758,-1 -6.596,-2.039 1.92,2.519 6.156,3.518 5.677,7.076 z m -149.469,19.068 c -3.798,4.997 -1.919,11.034 -2.359,17.03 0,1.999 -0.48,6.036 -1.879,7.516 -1.918,1.998 -4.237,1.519 -6.156,2.998 2.838,-2.479 7.076,-2.479 10.394,-1.48 -1.44,-4.517 -3.318,-9.034 2.318,-10.033 -2.318,-3.518 -1.399,-4.997 -1.399,-8.515 -0.48,-2.998 -1.879,-6.996 -0.92,-10.034 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1062" />
+ <path
+ d="m 117.649,122.206 c 0.96,-2.998 -0.92,-6.516 -0.44,-9.514 0.44,-3.998 1.879,-5.517 4.197,-8.515 -6.076,-2.519 -4.677,-6.036 -4.197,-11.553 0.44,-4.997 -2.359,-5.517 -4.717,-10.034 -2.838,-6.516 -2.838,-17.03 -3.278,-24.065 0,-7.996 -2.838,-14.032 -8.955,-19.029 -2.798,-2.518 -7.035,-7.036 -10.793,-7.036 -5.677,-0.52 -9.435,6.037 -11.313,11.034 -1.4,4.997 -4.238,17.549 -3.278,23.066 l 9.874,48.13 1.878,1.52 c 4.238,3.477 1.88,5.516 -0.48,7.515 0.48,1 0.96,1.48 1.88,1.999 h 1.879 c 1.439,0 2.838,0 3.757,0.52 0.48,0 1.44,0.48 2.359,0.48 0,3.517 -2.359,7.035 -1.88,10.513 2.84,-0.48 5.638,-1 7.077,-3.998 -0.96,2.998 -1.44,7.036 -1.44,9.514 1.44,-1.998 2.36,-4.996 2.839,-5.996 3.278,-6.036 13.632,-8.515 15.03,-14.551 z m 3.318,47.771 c 2.798,5.996 3.717,13.032 6.076,19.028 2.798,6.037 4.197,10.554 4.197,17.55 0.48,5.037 -0.48,13.072 -3.757,17.07 -3.238,3.997 -8.875,6.036 -12.633,9.514 6.117,-5.997 13.592,1 17.79,-6.996 3.757,-7.036 4.197,-14.551 4.197,-22.067 0,-8.554 -4.677,-10.553 -7.475,-17.549 -2.799,-6.036 -4.678,-14.551 -9.834,-18.589 z m 46.931,20.388 c 1.4,4.037 4.198,18.069 -2.358,16.55 0,3.517 0.92,6.516 -0.48,10.034 -1.4,-2 -2.838,-6.037 -5.157,-2.519 1.879,1.999 0,1.999 0,3.518 0.44,1.999 0.44,3.997 0.92,5.996 -6.117,1 -7.516,6.516 -10.794,11.034 -3.798,4.517 -8.954,7.515 -9.434,14.51 1.439,-4.996 -0.48,-11.512 2.838,-15.51 0,0.48 2.798,0 3.758,-1 1.879,-1.518 1.399,-3.997 2.358,-6.036 2.359,-4.997 2.799,-2.478 6.117,-5.996 3.278,-3.518 0.92,-7.036 0,-11.513 4.237,2.479 3.757,-4.037 2.798,-6.516 4.717,0 6.596,-1 6.116,-5.517 -0.48,-2.518 -2.358,-8.514 -3.278,-10.513 2.799,1.999 5.637,0.48 7.516,-1.04 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1064" />
+ <path
+ d="m 166.06,187.846 c -0.48,-1.959 -1.4,-5.477 -0.48,-7.435 0.96,-2.519 3.318,-2.999 3.757,-4.997 0.96,-3.478 -3.278,-6.476 1.88,-8.475 -2.32,0 -4.678,1.999 -6.557,-1 1.4,5.997 -4.717,8.995 -1.879,14.472 z m 11.752,-26.544 c -0.96,4.997 -3.318,12.992 3.278,14.991 3.318,1 11.753,-9.474 13.192,-2.998 2.359,-3.998 5.157,-3.478 8.915,-4.477 1.439,-0.52 1.879,-2.999 3.798,-2.519 1.878,0.52 2.798,3.518 2.798,4.997 0.96,-1.999 3.318,-7.515 5.636,-8.515 5.197,-1.479 4.238,3.038 5.677,6.037 1.4,-2 1.879,-5.517 4.237,-5.517 2.799,-0.52 4.198,2.998 4.678,4.997 1.878,-1.999 1.878,-8.515 4.717,-8.515 2.358,-0.48 3.757,2.998 3.278,5.037 2.838,-3.038 -0.48,-9.514 3.318,-11.513 0.92,1.48 1.399,3.478 1.399,4.477 1.399,-4.997 0.92,-7.475 6.596,-6.995 4.677,0 6.116,0.999 7.036,5.996 5.636,-4.997 6.596,4.997 6.596,8.515 3.757,-4.517 5.156,-8.995 2.358,-13.992 -2.838,-4.517 -4.717,-9.514 -6.116,-15.03 -1.4,1.998 -3.758,7.995 -6.116,7.995 -3.318,0 -4.238,-7.476 -5.197,-9.515 -1.4,2.04 -3.278,10.034 -5.637,10.514 -4.237,1.519 -6.596,-4.477 -7.995,-7.476 -1.879,2.999 -1.4,9.475 -4.717,11.993 -4.677,3.998 -4.198,-1.519 -8.435,-2.998 -1.879,7.515 -2.359,10.993 -9.914,12.512 -1.879,0 -1.879,0 -3.758,0.48 -1.879,0.52 -3.757,1.999 -5.636,2.519 -9.395,3.997 -19.269,1.479 -21.627,-9.515 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1066" />
+ <path
+ d="m 263.84,161.782 c 4.238,-4.477 13.192,3.518 16.03,6.516 4.238,4.038 5.677,8.555 5.197,14.031 0,5.517 -0.48,14.552 -3.318,19.549 -0.92,1.998 -3.757,5.037 -6.116,6.516 -2.359,1.519 -6.156,1.519 -7.076,3.997 6.117,-1.479 14.631,-1 16.99,-7.995 2.359,-7.515 2.359,-16.03 2.838,-23.546 0.44,-8.035 -3.797,-11.513 -9.914,-16.03 -2.838,-2.518 -10.873,-12.552 -13.711,-15.03 -2.799,-3.039 -0.44,1.998 -5.197,1.478 z m 48.93,57.645 c 0.92,5.517 5.157,13.552 1.88,18.549 -1.88,3.038 -15.112,7.515 -13.193,0 5.157,1 5.637,-3.998 7.516,-7.516 2.838,-4.997 2.838,-3.518 1.919,-9.034 -0.96,-8.515 3.757,-17.03 2.798,-25.585 z M 292.583,79.112 c 3.757,7.036 10.353,8.555 10.793,18.07 0.96,7.035 -0.44,15.07 1.879,22.066 1.4,6.036 4.717,11.073 7.036,16.59 0.96,1.479 4.237,5.996 4.237,7.515 0.44,2.998 -2.358,4.517 -1.879,9.035 -6.116,-0.52 -1.399,5.516 -0.48,8.514 -2.358,-2.478 -7.035,-4.996 -7.955,-8.514 7.956,-2.519 2.799,-11.034 -1.439,-14.032 5.197,-9.034 -3.278,-12.073 -7.955,-17.59 3.758,-4.516 1.879,-8.034 -1.879,-11.552 5.157,-5.997 4.238,-26.584 -2.358,-31.621 z M 39.536,63.601 c 3.318,1.52 5.197,1.52 7.555,5.037 1.88,2.479 2.359,5.477 4.238,7.996 1.399,1.998 3.278,3.997 4.717,6.476 1.4,1.519 4.677,5.996 6.596,7.995 0.92,-5.997 -2.838,-9.474 -2.359,-14.991 0.44,-3.998 2.359,-8.475 3.758,-11.993 1.879,-4.997 3.278,-8.515 6.116,-11.993 3.278,-3.517 7.516,-7.995 6.596,-14.031 -1.399,6.516 -7.075,15.51 -14.59,12.512 -2.839,5.997 -4.238,7.516 -10.354,7.516 2.798,2.478 5.636,6.996 4.237,11.513 -1.879,-1.999 -5.197,-4.517 -7.555,-5.037 -3.278,-0.48 -5.637,1.519 -8.955,-1.999 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1068" />
+ <path
+ d="m 111.053,226.023 c -1.84,0.52 -3.278,2.998 -3.278,3.998 m 153.267,-88.747 c 1.439,7.556 13.672,16.07 17.909,22.067 3.318,4.517 10.833,9.035 12.233,15.03 M 121.446,164.94 c 2.839,4.517 5.197,10.514 7.076,15.03 0.92,2.52 1.4,4.998 2.359,7.516 1.399,2.519 2.798,2.999 4.677,5.517 5.157,6.996 0.48,27.503 -2.798,35.538 -0.48,1.48 -0.96,2.999 -1.88,3.478 M 52.288,6.396 c -3.278,1.52 -7.955,7.076 -9.354,10.594 -1.879,3.518 -6.076,3.997 -7.515,4.997 m 100.019,222.585 c -1.839,0.52 -2.319,3.038 -3.278,4.557 m -1.839,-7.995 c -3.278,0 -7.036,1.519 -7.995,4.957 m -11.673,-25.505 c -1.879,1 -4.237,1 -6.156,2.959 m 168.378,-16.55 c -2.319,0.52 -5.597,1.519 -6.077,3.997 m 2.799,-9.514 c -1.92,0 -3.838,1.04 -5.277,2.558 m 38.137,30.542 c -1.88,2.039 -3.758,4.037 -3.758,6.556 m -3.278,-9.594 c -1.839,1.559 -4.637,2.558 -5.117,5.596 m 21.986,-3.997 c -0.919,1.519 -1.358,2.518 -1.838,3.997 M 181.17,151.828 c -1.399,0.52 -4.717,4.038 -6.116,5.037 2.358,2.518 0.96,10.554 -2.838,11.553 0.48,2.039 -0.48,2.518 0.48,4.517 m -52.169,-7.595 c 0.92,-4.477 -5.197,-3.998 -7.076,-6.516 1.44,-1.48 3.318,-3.478 1.88,-5.477 -1.88,0.48 -3.759,0 -5.158,-1.519 1.4,-1.999 2.359,-4.997 0.48,-7.036 -1.919,1.52 -3.798,1.04 -6.156,0.52 M 11.473,32.94 c 0.44,7.076 -3.358,11.593 -8.595,9.075"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1070" />
+ <path
+ d="m 9.514,39.976 c 0.96,-1 2.359,-6.476 1.44,-7.955 -0.96,-1.52 -4.718,-1.52 -6.637,-1 -2.358,1 -3.318,2.998 -2.838,8.475 0,1.999 0.48,2.998 0.48,3.958 l 1.439,-0.96 c 2.359,0 4.717,0 6.116,-2.518 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1072" />
+ <path
+ d="m 55.566,32.54 c -2.798,-1.479 -4.197,-5.996 -7.035,-7.995 -2.799,-1.999 -2.799,0.52 -4.718,3.518"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1074" />
+ <path
+ d="M 52.848,29.102 C 49.09,38.137 42.454,27.104 45.772,25.584 m 11.233,0.96 C 55.606,22.067 50.01,18.549 46.692,19.548 m -33.98,39.136 c 3.318,-1.998 4.278,0.96 6.636,2.439 3.318,1.959 6.157,-0.48 8.955,0.52"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1076" />
+ <path
+ clip-path="url(#a)"
+ d="m 65,104.337 c -2.318,-2.519 0.48,-14.551 -5.156,-12.553 -0.48,-2.518 -1.88,-5.516 -3.278,-7.515 -0.96,1.519 -1.88,2.998 -2.839,3.998 2.359,-2.999 0,-7.996 -2.358,-10.514 0,0.52 -0.92,1.519 -0.44,1.519 C 49.969,73.755 47.131,72.756 44.333,69.238 41.975,67.239 35.379,66.24 33.5,66.24 23.626,66.24 16.59,65.72 8.595,57.685 6.715,55.207 5.757,52.168 4.837,48.69 3.397,44.653 2,45.652 1.52,39.656 1.04,33.14 2,31.621 6.237,30.621 c 1.4,-0.48 5.157,-2.478 9.395,-3.477 3.757,-1.04 7.995,-1.04 11.752,-2.519 7.076,-2.518 8.475,-1.999 12.233,-7.036 3.758,-5.516 6.596,-8.514 15.99,-12.512 8.955,-3.518 21.627,-4.038 32.94,1 7.995,2.998 13.632,7.515 15.031,10.033 1.4,2.479 3.318,7.516 5.197,10.514 1.879,3.518 4.198,7.036 9.394,10.034 4.718,3.518 8.475,4.997 9.874,7.515 1.4,2.519 2.359,2.998 2.359,2.998 l 1.879,2 c 0,0 2.358,0.519 13.152,4.516 10.833,2.999 24.945,8.515 38.097,8.036 13.192,-0.52 54.087,-6.516 73.355,-4.038 19.788,3.038 33.42,13.552 41.895,22.067 8.915,9.034 10.314,18.069 9.874,24.585 -0.48,4.997 -2.838,18.549 5.637,29.062 l 5.636,12.033 c -4.237,3.518 -4.237,5.517 -1.879,9.514 -0.48,0 -1.879,0 -2.838,-0.48 1.44,3.998 3.318,7.516 5.637,10.994 -1.4,-0.48 -2.799,0.52 -3.758,0 0.96,3.038 2.838,4.517 3.318,7.515 -5.197,0 -1.88,5.037 -1.44,8.035 0.48,3.998 -0.919,10.034 -1.878,14.551 -1.4,6.517 -2.319,17.03 -1.879,23.546 0,3.518 2.359,6.516 2.838,9.514 0.92,5.037 -0.48,5.517 -2.838,9.555 -2.798,3.997 -2.359,4.477 -7.515,4.997 -2.36,0 -7.996,1.519 -8.915,-1.52 -3.798,4.038 -11.793,-3.997 -10.354,-8.994 1.4,-5.037 10.354,-5.037 12.673,-10.034 1.878,-2.518 0.48,-6.036 0.48,-9.034 -0.48,-3.998 0.959,-7.516 0.959,-11.034 0,-9.514 -8.475,-17.55 -11.753,-25.544 2.798,5.996 -1.92,19.028 -2.839,25.544 -0.959,3.518 0,4.518 -2.358,8.035 -1.879,2.519 -9.874,3.998 -13.152,3.998 -6.116,-0.48 -11.753,-3.518 -9.434,-12.033 1.878,-7.995 13.671,-1.999 11.792,-14.031 -5.196,6.516 -2.358,-15.031 -1.918,-16.03 -1.4,1.998 -2.319,-0.52 -4.198,0.999 -1.439,-3.998 -1.439,-3.518 -2.358,-7.516 -0.48,1 -4.718,4.997 -4.718,4.997 0,0 0.96,-8.514 0.48,-9.994 -0.96,-3.517 -4.237,-5.037 -8.475,-1.039 -0.92,-1.999 -0.92,-4.997 -1.879,-7.515 -1.399,-2 -4.237,3.517 -5.156,2.038 l -1.88,-1.519 c 0,3.518 0.44,7.516 0,11.034 -0.959,-2.519 -1.878,-4.518 -3.317,-6.516 0,4.517 -0.92,8.994 -3.758,13.032 -0.48,-2.999 -1.4,-6.516 -3.278,-8.515 -0.96,3.997 -3.318,7.515 -5.637,10.993 -0.48,-2.478 0,-6.516 -2.838,-7.995 -1.399,2.998 -3.278,6.516 -6.596,8.515 -0.44,-2.519 -1.879,-5.517 -2.798,-8.515 -2.838,2.518 -4.238,7.515 -7.076,10.514 -0.48,-2.519 -1.879,-4.518 -3.758,-5.997 -0.48,1 -0.92,1.48 -0.92,2.479 -0.479,-0.48 -0.958,-0.48 -1.438,-0.48 -0.44,0.48 -0.44,1 -0.92,1.48 -4.237,-2.999 -6.596,2.518 -7.075,5.516 -0.44,-2.479 -1.4,-3.998 -4.238,-4.477 -3.278,-1.04 -7.036,5.476 -7.036,5.476 0,0 -3.278,-2.998 -6.116,-1.479 -1.879,0.48 -2.838,-6.036 -5.157,-5.037 3.758,4.517 -2.358,4.517 -4.237,7.556 1.879,3.997 3.278,2.478 4.237,6.995 -1.439,-0.48 -1.879,3.998 -2.838,3.998 3.278,3.038 1.4,13.552 1.4,18.069 -2.36,-1.52 -0.92,-1 -3.279,-0.52 2.359,3.518 1.4,6.037 -1.399,11.034 -3.318,-3.998 0.92,-2.999 -4.717,-1.48 1.879,3.478 6.116,9.515 1.879,7.516 -2.359,-1.52 -3.278,3.478 -7.036,4.517 -4.717,1.48 -5.197,11.993 -9.434,10.994 -0.44,3.517 -1.4,9.034 -4.238,11.033 0.48,0 -0.44,0 0,0 -4.197,2.998 -9.394,0 -13.152,-0.48 -3.278,-0.52 -7.035,-1 -9.874,-5.037 -2.838,-4.997 0.48,-8.515 5.157,-11.033 2.838,-1.48 4.717,-1.999 5.677,-3.998 l -3.798,-0.48 c -2.798,1.48 -6.556,0 -9.874,0.48 -2.319,0.52 -6.556,3.518 -8.915,2 -3.757,-1.48 -7.515,-9.515 -4.717,-13.033 3.758,-5.517 12.713,-1.48 16.47,-6.516 3.278,-4.517 0,-21.027 4.238,-25.545 -6.596,-0.999 -7.516,-15.03 -7.516,-20.547 -3.797,6.996 -6.116,3.478 -6.116,3.478 0,0 1.879,-7.516 0,-9.994 -4.717,2.998 -2.838,-3.038 -3.318,-5.517 -0.44,-2.518 -1.4,-4.037 -2.798,-6.036 -3.318,-3.518 -4.238,-1.999 -4.717,-6.996 0,-2.518 0.48,-7.036 1.399,-10.034 -1.4,2.998 -4.238,3.518 -7.036,3.998 -0.48,-3.518 1.879,-6.996 1.879,-10.514 -3.758,-0.52 -7.516,-1 -10.834,-1.519 1.88,-2.998 6.596,-4.517 1.44,-8.995 z"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1078" />
+ <path
+ d="m 308.533,99.18 v 5.037 c 0,2.518 -0.96,7.555 -0.48,13.072 0.96,-2.519 4.797,-5.037 4.797,-8.035 0,-4.038 -2.398,-8.075 -4.317,-12.113 v 0.52 c 0,0 0,0 0,0 v 1.519"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1080" />
+ <path
+ d="m 95.102,24.905 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.551 0,3.038 0,5.517 0.48,8.555 0.48,3.518 0,7.036 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.92,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.196,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.076,-1.519 -1.88,1.52 -0.92,3.998 -0.44,6.036 -1.44,0 -2.839,-0.52 -3.798,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.514,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.96,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514 z"
+ fill="#ce9249"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1082" />
+ <path
+ d="m 81.91,41.055 c -1.399,4.038 -3.278,8.035 -5.596,11.033 -1.88,2.519 -4.238,5.037 -5.157,7.516 -0.48,1.519 0,3.038 -0.48,4.517 -0.44,1.52 -2.318,2.998 -2.798,4.517 -0.48,1 -0.48,2.519 -0.48,3.518 -0.44,1.48 -1.879,2.519 -1.879,3.998 0,1.519 1.44,2.998 1.44,4.517 0.44,1.52 0.44,2.998 0.44,4.517 0,3.518 -0.92,6.996 -0.44,10.034 0,2 0.919,3.478 0.919,5.517 0,1.999 -0.92,3.478 -0.48,5.477 0.48,1.519 0.96,2.038 1.4,3.517 0.959,1.52 0,3.518 0.479,5.037 3.278,-0.999 2.798,2.479 3.278,4.478 0.96,-2 3.758,-2.479 5.637,-2 -0.96,-0.479 -3.758,-0.998 -4.678,-1.478 -1.878,-1.52 0,-6.037 1.4,-7.516 -1.4,0 -4.238,-0.52 -4.678,-2.038 -0.959,-2 3.278,-4.478 3.718,-5.997 -1.879,-0.52 -3.278,-1 -3.718,-2.998 -1.439,-3.518 1.4,-5.037 1.84,-8.035 0,-1.999 -1.4,-1.48 -2.32,-3.518 -0.959,-1.999 0,-4.477 1.88,-5.996 -2.359,-3.518 -2.839,-5.517 -0.48,-9.035 0.92,-1.479 0.92,-0.48 0.92,-1.999 0.479,-1.998 -1.4,-3.517 0.959,-5.516 0.92,-1 1.879,-0.48 2.318,-1.999 0.48,-1 0,-3.998 0.96,-5.517 0.48,-1.998 0.92,-4.517 1.879,-6.995 z"
+ fill="#dfb781"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1084" />
+ <path
+ d="m 95.142,24.945 c -2.358,4.517 5.677,10.074 7.556,14.071 2.358,5.037 2.838,10.034 2.358,15.55 0,3.04 0,5.518 0.48,8.556 0.48,3.518 0,7.035 0.48,10.513 0.44,3.039 1.399,6.037 1.879,9.035 0.48,4.037 0.919,10.554 3.757,13.552 -3.757,1.04 -1.399,5.037 0,8.035 -5.197,1.519 -1.399,9.554 1.88,11.073 -0.92,-2.039 -4.718,-3.038 -7.077,-1.519 -1.878,1.52 -0.919,3.998 -0.44,6.036 -1.438,0 -2.838,-0.52 -3.797,0.48 -0.92,1.52 -0.44,4.517 -0.44,6.036 -3.797,-5.037 -8.515,-6.036 -10.873,1 0,-6.037 -7.995,-4.038 -9.434,0.48 0.959,-5.997 -7.996,-5.517 -11.793,-6.517 0,-2.518 -1.4,-5.996 -4.238,-5.996 0,-1.519 0.96,-3.038 0.48,-5.037 -0.48,-1.519 -1.44,-2.518 -1.879,-3.997 -0.48,-3.039 0.92,-6.556 0.44,-10.074 0,-2.479 -0.92,-4.997 0,-7.516 0.96,-4.517 0,-4.997 -2.359,-8.515 1.44,-2.038 2.359,-5.037 2.359,-7.555 -0.44,-2.998 -0.92,-3.518 0.48,-5.996 2.358,-3.039 2.838,-4.038 3.318,-7.556 0.48,-2.998 0.92,-3.997 2.838,-5.996 3.758,-4.038 7.076,-7.556 8.475,-13.072 0.96,-3.518 -1.4,-6.516 -0.96,-9.514"
+ fill="none"
+ stroke="#333333"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1086" />
+ <path
+ d="m 103.058,54.087 c -0.48,2.998 0,5.997 0,9.035 v 9.994 c 0.44,6.556 1.399,13.551 3.278,19.588 0.48,1 0.959,1.999 1.399,3.478 0,1.519 0,1 -0.44,2.518 -0.48,1.999 -0.96,2.998 -0.96,5.037 0.48,1.999 0.96,2.998 0.96,4.477 -0.48,0.52 -1.44,1.52 -1.44,2.519 -0.439,1 0,2.518 -0.439,2.998 -0.48,1 -1.919,1 -2.838,2.039 -0.48,1.479 0,2.998 -0.96,4.477 -1.399,-1 -2.798,0.52 -3.757,1 -0.92,-1 -1.88,-1.48 -2.839,-1 0.96,-1 3.798,-2.478 4.718,-3.478 0.959,-2.039 0,-4.517 -0.92,-7.036 2.359,0 3.278,-2.518 3.278,-4.996 0,-2.04 -0.92,-2.04 -1.879,-3.518 -0.96,-2.519 1.4,-4.038 1.88,-6.516 0.959,-4.038 -0.92,-5.517 -2.84,-8.036 4.238,-4.517 1.92,-8.035 0.48,-12.512 -0.919,-3.038 0.96,-5.517 0.48,-9.034 0,-2.999 1.4,-6.037 1.4,-9.035 0.48,-1.999 0.959,-4.997 0.48,-7.036 z"
+ fill="#bd7220"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1088" />
+ <path
+ d="m 45.253,24.545 c -1.88,3.478 2.838,10.914 6.116,6.956 2.318,-2.479 -3.758,-9.954 -5.637,-6.956 z"
+ fill="#333333"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1090" />
+ <path
+ d="m 45.692,26.944 c 0,-0.52 0.44,-1 0.92,-1 0.52,0 0.92,0.48 0.92,1 0,0.56 -0.4,1 -0.92,1 -0.48,0 -0.92,-0.44 -0.92,-1 z"
+ fill="#ffffff"
+ fill-rule="evenodd"
+ fill-opacity="1"
+ stroke="none"
+ id="path1092" />
+ <path
+ d="m 2.878,39.016 c 0.96,0 2.399,0.48 3.358,0.48 0.96,0 1.44,-1.479 2.399,-1.999"
+ fill="none"
+ stroke="#ffffff"
+ stroke-width="1.03937px"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-miterlimit="4"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1094" />
+ <path
+ d="m 80.111,31.46 c -1.439,-0.519 -3.358,0 -3.837,2.08 1.919,0.48 3.837,-1.04 5.277,0.48 -0.96,2.078 -2.879,3.078 -4.798,3.078 M 96.981,26.064 c -2.798,-1.519 -7.036,3.038 -1.879,3.518 1.88,0.52 3.278,-1.519 4.238,1 0.44,1.998 -3.278,5.036 -4.238,6.516 M 47.171,20.987 c -0.48,-3.438 5.677,-4.437 2.399,1.96 M 26.944,63.082 c 0,-1 0.96,-3.478 -0.48,-3.478 -1.919,-0.52 -2.878,2.478 -2.399,3.478 m 82.271,86.348 c 0,-2.04 0.48,-4.558 0.959,-6.637 2.319,0.52 2.319,4.118 1.879,6.636 m 71.516,4.917 c -3.717,-6.915 -6.556,0.48 -2.798,2.439 m 83.709,-12.952 c 0.92,-0.48 1.84,-1 2.719,-1.999 m 7.995,67.159 c -0.44,-4.037 -6.556,-4.557 -3.718,0 m 33.86,28.143 c -0.96,-1.04 -1.92,-1.599 -2.879,-1.599 m -5.116,-1.399 c -2.359,-6.116 -6.157,1.56 -2.359,2.039"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1096" />
+ <path
+ d="m 267.638,200.039 c -1.4,1.999 1.399,4.997 0.48,5.996 -1.88,1.999 -3.798,-1 -3.798,-2.478 m -155.146,16.07 c 0,1.479 0.44,2.478 0.44,3.918 -1.4,-0.48 -2.319,-0.96 -3.278,-2.439 m 1.838,4.917 c 0.52,1.52 1,2.518 2,3.518 m 18.868,10.514 c 2.318,6.036 -2.359,2.518 -4.238,-0.52"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1098" />
+ <path
+ clip-path="url(#a)"
+ d="m 135.078,244.092 c -0.44,1.999 0.96,2.519 1.4,3.998 -2.32,0.48 -3.718,-1 -5.597,-1.48"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1100" />
+ <path
+ d="m 121.926,242.573 c 0.48,2.039 1.879,3.038 3.278,3.518"
+ fill="none"
+ stroke="#ce9249"
+ stroke-width="2.15869px"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ stroke-miterlimit="8"
+ stroke-dasharray="none"
+ stroke-opacity="1"
+ id="path1102" />
+ </g>
+ </g>
+ <g
+ id="layer2"
+ inkscape:label="Layer 2"
+ clip-path="none"
+ inkscape:groupmode="layer"
+ transform="matrix(0.5,0,0,0.5,0,150)">
+ <rect
+ style="opacity:0.8;fill:#ffffff;stroke-width:2.06559;stop-color:#000000"
+ id="rect1552"
+ width="100"
+ height="32"
+ x="0"
+ y="-300" />
+ <text
+ xml:space="preserve"
+ style="font-size:32.9658px;line-height:1.25;font-family:'Arial Black';-inkscape-font-specification:'Arial Black, ';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#2e3436;stroke-width:1.54527"
+ x="50"
+ y="-272"
+ id="text510"><tspan
+ sodipodi:role="line"
+ id="tspan508"
+ x="50"
+ y="-272"
+ style="-inkscape-font-specification:'Arial Black, '">?</tspan></text>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="Layer 3" />
+</svg>
diff --git a/share/extensions/other/clipart/pyproject.toml b/share/extensions/other/clipart/pyproject.toml
new file mode 100644
index 0000000..fd36dc6
--- /dev/null
+++ b/share/extensions/other/clipart/pyproject.toml
@@ -0,0 +1,19 @@
+[tool.poetry]
+name = "import-web-image"
+version = "1.0.0"
+description = "A GTK3 based web image importer."
+authors = ["Martin Owens <doctormo@geek-2.com>"]
+maintainers = ["Martin Owens <doctormo@geek-2.com>"]
+license = "GPL-3.0-or-later"
+
+# The dependencies below are NOT used for packaging, they are abstract.
+# They are merely for packagers' convenience and are used in CI for extensions.
+[tool.poetry.dependencies]
+python = ">=3.7"
+appdirs = "1.4.4"
+requests = "*"
+CacheControl = {extras = ["filecache"], version = "*"}
+
+[build-system]
+requires = ["poetry-core>=1.0.0"]
+build-backend = "poetry.core.masonry.api"
diff --git a/share/extensions/other/clipart/sources/bioicons.py b/share/extensions/other/clipart/sources/bioicons.py
new file mode 100644
index 0000000..232f024
--- /dev/null
+++ b/share/extensions/other/clipart/sources/bioicons.py
@@ -0,0 +1,97 @@
+#
+# Copyright 2022 Simon Duerr dev@simonduerr.eu
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>
+#
+"""
+Access Bioicons.
+
+Downloads the database to cache and uses it locally for searching.
+"""
+
+import json
+import requests
+from datetime import datetime
+import os
+
+
+from cachecontrol import CacheControl, CacheControlAdapter
+from cachecontrol.caches.file_cache import FileCache
+from cachecontrol.heuristics import ExpiresAfter
+
+from import_sources import RemoteSource
+
+
+def local_search(query, db):
+ for item in db:
+ if query.lower() in item["name"].lower():
+ yield item
+ return
+
+
+class Bioicons(RemoteSource):
+ name = "Bioicons"
+ icon = "sources/bioicons.svg"
+ db_url = "https://bioicons.com/icons/icons.json"
+ icon_url = "https://bioicons.com/icons/"
+
+ def __init__(self, cache_dir):
+ self.session = requests.session()
+ self.cache_dir = cache_dir
+ self.session.mount(
+ "https://",
+ CacheControlAdapter(
+ cache=FileCache(cache_dir),
+ heuristic=ExpiresAfter(days=5),
+ ),
+ )
+ # check if local db is up to date with Last Modified header
+ try:
+ response = requests.head(self.db_url)
+ except Exception:
+ response = None
+
+ self._json = os.path.join(self.cache_dir, "icons.json")
+ if not os.path.isfile(self._json):
+ last_modified = 0
+ else:
+ last_modified = os.path.getmtime(self._json)
+
+ if response is not None:
+ last_update = datetime.strptime(
+ response.headers["Last-Modified"], "%a, %d %b %Y %H:%M:%S GMT"
+ ).timestamp()
+ # if icon db was modified download new database
+ if last_modified < last_update:
+ self.to_local_file(self.db_url)
+
+ def search(self, query):
+ results = []
+ if os.path.isfile(self._json):
+ with open(self._json, "r") as f:
+ db = json.load(f)
+ results = local_search(query, db)
+
+ for item in results:
+ yield {
+ "id": item["name"],
+ "name": item["name"],
+ "summary": item["category"],
+ "created": None,
+ "popularity": 0,
+ "author": item["author"],
+ "thumbnail": f"{self.icon_url}{item['license']}/{item['category']}/{item['author']}/{item['name']}.svg",
+ "file": f"{self.icon_url}{item['license']}/{item['category']}/{item['author']}/{item['name']}.svg",
+ "license": item["license"],
+ }
diff --git a/share/extensions/other/clipart/sources/bioicons.svg b/share/extensions/other/clipart/sources/bioicons.svg
new file mode 100644
index 0000000..ad9c98c
--- /dev/null
+++ b/share/extensions/other/clipart/sources/bioicons.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ id="Layer_1"
+ data-name="Layer 1"
+ viewBox="0 0 48 47.999999"
+ version="1.1"
+ sodipodi:docname="bioicons.svg"
+ width="48"
+ height="48"
+ inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
+ 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/">
+ <metadata
+ id="metadata47">
+ <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>Reactome_Imagotype_Positive</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#999999"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="0"
+ inkscape:window-width="1920"
+ inkscape:window-height="1114"
+ id="namedview45"
+ showgrid="false"
+ inkscape:zoom="3.0867372"
+ inkscape:cx="-56.046236"
+ inkscape:cy="60.095819"
+ inkscape:window-x="0"
+ inkscape:window-y="31"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="Layer_1"
+ inkscape:pagecheckerboard="0" />
+ <defs
+ id="defs4">
+ <style
+ id="style2">.cls-1{fill:#2f9ec2;}.cls-2{fill:#d1eaf2;}.cls-3{fill:#9bd1e2;}.cls-4{fill:#80c4da;}.cls-5{fill:#65b7d2;}.cls-6{fill:#4aabca;}</style>
+ <rect
+ x="-570.75629"
+ y="-57.900295"
+ width="612.50269"
+ height="205.65784"
+ id="rect1078" />
+ </defs>
+ <title
+ id="title6">Reactome_Imagotype_Positive</title>
+ <g
+ inkscape:label="Layer 1"
+ id="layer1"
+ transform="matrix(0.30270641,0,0,0.30270641,0.56456345,2.6535028)">
+ <path
+ id="rect842"
+ style="fill:#eeeeec;stroke:#2e3436;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 69.811488,1.973202 C 69.393094,1.977162 68.96226,2.034473 68.530033,2.1502919 66.224822,2.7679712 64.782878,4.8100011 65.297028,6.728827 l 12.69442,47.375154 -12.69442,47.375149 c -0.51415,1.91882 0.927797,3.96086 3.233005,4.57854 2.305207,0.61767 4.575189,-0.43007 5.089336,-2.34889 l 8.83181,-32.960558 8.831806,32.960558 c 0.51416,1.91883 2.78369,2.96658 5.0889,2.34889 2.3052,-0.61769 3.747155,-2.65971 3.23301,-4.57854 L 86.910915,54.103981 99.604895,6.728827 c 0.514135,-1.9188259 -0.92781,-3.9608558 -3.23301,-4.5785351 -2.30521,-0.6176785 -4.57475,0.4296199 -5.0889,2.3484457 L 82.451179,37.459739 73.619369,4.4987376 C 73.201625,2.9396917 71.624529,1.9560193 69.811488,1.973202 Z" />
+ <circle
+ style="fill:#8ae234;stroke:#2e3436;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="path849"
+ cx="82.450958"
+ cy="54.103909"
+ r="5.1479092" />
+ <path
+ id="rect851"
+ style="fill:#eeeeec;stroke:#2e3436;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 118.03724,70.576829 c -1.385,0 -2.5001,1.115105 -2.5001,2.500106 0,1.384998 1.1151,2.500103 2.5001,2.500103 h 2.56419 c -0.0383,0.250442 -0.0641,0.504876 -0.0641,0.766363 v 57.721029 c 0,2.77 2.22969,5.00021 4.99968,5.00021 2.77,0 5.00021,-2.23021 5.00021,-5.00021 V 76.343401 c 0,-0.261501 -0.0263,-0.515908 -0.0646,-0.766363 h 2.5647 c 1.385,0 2.49959,-1.115105 2.49959,-2.500103 0,-1.385001 -1.11459,-2.500106 -2.49959,-2.500106 z"
+ sodipodi:nodetypes="ssscssssscssss" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 125.48876,47.432896 V 101.58252"
+ id="path872"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:#8ae234;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 128.65374,38.96623 c 0,-2.84965 -3.16498,-7.408333 -3.16498,-7.408333 0,0 -3.16498,4.558683 -3.16498,7.408333 0,2.849649 3.16498,8.466666 3.16498,8.466666 0,0 3.16498,-5.617017 3.16498,-8.466666 z"
+ id="path878"
+ sodipodi:nodetypes="zczcz" />
+ <path
+ style="fill:#8ae234;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 132.47687,61.566036 c 1.42482,-2.46787 0.96321,-7.998295 0.96321,-7.998295 0,0 -5.02029,2.365446 -6.44511,4.833315 -1.42483,2.467867 -1.49238,8.914838 -1.49238,8.914838 0,0 5.54946,-3.281989 6.97428,-5.749858 z"
+ id="path880"
+ sodipodi:nodetypes="zczcz" />
+ <path
+ style="fill:#8ae234;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 118.5972,53.439548 c -1.42482,-2.46787 -0.96321,-7.998295 -0.96321,-7.998295 0,0 5.02029,2.365446 6.44511,4.833315 1.42483,2.467867 1.49238,8.914838 1.49238,8.914838 0,0 -5.54946,-3.281989 -6.97428,-5.749858 z"
+ id="path882"
+ sodipodi:nodetypes="zczcz" />
+ <path
+ style="fill:#ffffff;stroke:#2e3436;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 121.55128,98.816017 c -0.994,0.04983 -0.66257,1.055258 -0.70431,1.756043 0.0229,16.9791 0.0456,17.55403 0.0682,34.53313 0.66642,2.07961 2.68396,3.80356 4.94289,3.57631 2.02055,-0.10205 3.71707,-1.70899 4.27808,-3.57631 0.0232,-17.43934 0.0466,-18.47451 0.07,-35.913849 -1.27252,-0.175821 -2.50492,-0.218643 -3.66668,-1.195466 -0.5782,-0.729525 -1.15666,1.394072 -1.76875,1.670237 -1.15754,0.245224 -2.14214,-0.71211 -3.2195,-0.850095 z"
+ id="path868"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="rect956"
+ style="fill:#73d216;stroke:#2e3436;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 24.200478,120.03722 h 26.554176 v 4.29531 H 24.200478 Z" />
+ <path
+ id="rect958"
+ style="fill:#73d216;stroke:#2e3436;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 28.698401,111.27657 h 17.558331 v 4.29531 H 28.698401 Z" />
+ <path
+ id="rect962"
+ style="fill:#73d216;stroke:#2e3436;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 25.787981,93.755244 h 23.37917 v 4.295311 h -23.37917 z" />
+ <path
+ id="rect964"
+ style="fill:#73d216;stroke:#2e3436;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 24.200478,84.994586 h 26.554176 v 4.295307 H 24.200478 Z" />
+ <path
+ id="rect966"
+ style="fill:#73d216;stroke:#2e3436;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 24.200478,76.233927 h 26.554176 v 4.295307 H 24.200478 Z" />
+ <path
+ id="rect968"
+ style="fill:#73d216;stroke:#2e3436;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 26.317149,67.473284 h 22.320835 v 4.295304 H 26.317149 Z" />
+ <path
+ id="rect972"
+ style="fill:#73d216;stroke:#2e3436;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 24.200478,41.191317 h 26.554176 v 4.295307 H 24.200478 Z" />
+ <path
+ id="rect974"
+ style="fill:#73d216;stroke:#2e3436;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 27.110899,49.951972 h 20.733334 v 4.295307 H 27.110899 Z" />
+ <path
+ id="path946"
+ style="fill:#ffffff;stroke:#2e3436;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 19.302491,36.717845 c -0.01356,10.880364 6.744366,17.73128 14.33098,23.635216 -2.13265,1.518568 -4.282293,2.998734 -6.315055,4.514712 -11.614162,11.071195 -10.532919,29.577079 2.673007,38.609947 1.03945,0.86937 2.109672,1.71725 3.188135,2.55839 -6.946014,6.0421 -13.412345,13.01962 -13.562845,22.76989 h 5.835092 c 0.137349,-8.89828 5.707012,-14.3685 12.025761,-19.41488 6.318749,5.04638 11.888248,10.5166 12.025598,19.41488 h 5.835092 c -0.150499,-9.75028 -6.616824,-16.72778 -13.562845,-22.76989 1.078463,-0.84114 2.148848,-1.68902 3.188298,-2.55839 13.205927,-9.032868 14.287169,-27.538752 2.673006,-38.609947 -2.032741,-1.515963 -4.182426,-2.99616 -6.315054,-4.514712 7.586616,-5.903936 14.344543,-12.754852 14.33098,-23.635216 h -5.835093 c 0.0119,9.550247 -5.640419,15.623753 -12.339982,20.802822 -6.6996,-5.179079 -12.351881,-11.252534 -12.339983,-20.802822 z m 18.175075,26.530296 c 1.117115,0.823272 2.231679,1.638775 3.323755,2.453215 11.614131,11.071194 11.199755,26.576173 -2.006137,35.609044 -0.434386,0.36331 -0.875775,0.72993 -1.317618,1.09734 -0.44187,-0.36743 -0.883207,-0.73401 -1.317617,-1.09734 C 22.954055,92.277529 22.539681,76.77255 34.15381,65.701356 c 1.092076,-0.81444 2.20664,-1.629943 3.323756,-2.453215 z" />
+ </g>
+</svg>
diff --git a/share/extensions/other/clipart/sources/inkscape-web.py b/share/extensions/other/clipart/sources/inkscape-web.py
new file mode 100644
index 0000000..5960c3e
--- /dev/null
+++ b/share/extensions/other/clipart/sources/inkscape-web.py
@@ -0,0 +1,74 @@
+#
+# Copyright 2021 Martin Owens <doctormo@gmail.com>
+# Copyright 2022 Simon Duerr <dev@simonduerr.eu>
+# 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 3 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, see <http://www.gnu.org/licenses/>
+#
+
+from import_sources import RemoteSource
+
+
+license_mapping = {
+ "PD": "cc-0",
+ "CC-0": "cc-0",
+ "CC-BY 3.0": "cc-by-3.0",
+ "CC-BY 4.0": "cc-by-4.0",
+ "CC-BY-SA 4.0": "cc-by-sa-4.0",
+ "CC-BY-NC 3.0": "cc-by-nc-3.0",
+ "CC-BY-NC-SA 3.0": "cc-by-nc-sa-3.0",
+ "CC-BY-NC-SA 4.0": "cc-by-nc-sa-4.0",
+ "CC-BY-SA 3.0": "cc-by-sa-3.0",
+ "CC-BY-ND 3.0": "cc-by-nd-3.0",
+ "ASL": "asl",
+ "nbsd": "bsd",
+ "GPLv2": "gpl-2",
+ "GPLv3": "gpl-3",
+ "AGPLv3": "agpl-3",
+ "MIT": "mit",
+}
+
+
+class InkscapeWebsite(RemoteSource):
+ name = "Inkscape Community"
+ icon = "sources/inkscape-web.svg"
+ is_default = True
+
+ base_url = "https://inkscape.org/gallery/=artwork/json/"
+
+ def search(self, query):
+ """Ask the inkscape website for some artwork"""
+ items = []
+ try:
+ response = self.session.get(self.base_url, params={"q": query})
+ items = response.json()["items"]
+ except Exception:
+ pass
+
+ for item in items:
+ if "svg" not in item["type"]:
+ continue
+ if (
+ item["license"] == "(C)"
+ ): # ignore copyrighted items because they cannot be reused
+ continue
+ yield {
+ "id": item["id"],
+ "name": item["name"],
+ "author": item["author"],
+ "license": license_mapping.get(item["license"], item["license"].lower()),
+ "summary": item["summary"],
+ "thumbnail": item["icon"] or item["links"]["file"],
+ "created": item["dates"]["created"],
+ "popularity": item["stats"]["liked"],
+ "file": item["links"]["file"],
+ }
diff --git a/share/extensions/other/clipart/sources/inkscape-web.svg b/share/extensions/other/clipart/sources/inkscape-web.svg
new file mode 100644
index 0000000..8e2ec3b
--- /dev/null
+++ b/share/extensions/other/clipart/sources/inkscape-web.svg
@@ -0,0 +1,569 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<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="48"
+ height="48"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="1.0.2 (1.0.2+r75+1)"
+ version="1.0"
+ sodipodi:docname="inkscape-web.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ style="enable-background:new"
+ inkscape:export-filename="/home/doctormo/Desktop/inkscape-web.png"
+ inkscape:export-xdpi="204.81"
+ inkscape:export-ydpi="204.81">
+ <defs
+ id="defs4">
+ <linearGradient
+ id="linearGradient5733">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop5735" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0"
+ offset="1"
+ id="stop5737" />
+ </linearGradient>
+ <clipPath
+ id="clipoutline1">
+ <path
+ id="outline1"
+ d="M 54.1,12.5 12.9,54.7 C -2.7,70.3 23,69 32.3,74.9 36.6,77.7 18.5,81.3 22.2,85 c 3.6,3.7 21.7,7.1 25.3,10.7 3.6,3.7 -7.3,7.6 -3.7,11.3 3.5,3.7 11.9,0.2 13.4,8.6 1.1,6.2 15.4,3.1 21.8,-2.2 4,-3.4 -6.9,-3.4 -3.3,-7.1 9,-9.1 17,-4.1 20.3,-12.5 1.8,-4.5 -13.6,-7.7 -9.5,-10.6 9.8,-6.9 45.8,-10.4 29.2,-27 L 73,12.5 c -5.3,-5 -14,-5 -18.9,0 z m -9.9,64.7 c 0.9,0 30.8,4 19.3,7.1 -4.4,1.2 -24.6,-7.1 -19.3,-7.1 z m 57.2,16.6 c 0,2.1 16.3,3.3 15.4,-0.5 -1.3,-6.4 -13.6,-5.9 -15.4,0.5 z m -69.5,11.1 c 3.7,3.2 9.3,-0.7 11.1,-5.2 -3.6,-4.7 -16.9,0.3 -11.1,5.2 z m 67.5,-6.7 c -4.6,4.2 0.8,8.6 5.3,5.7 1.2,-0.8 -0.1,-4.7 -5.3,-5.7 z"
+ inkscape:connector-curvature="0" />
+ </clipPath>
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient5785">
+ <stop
+ offset="0"
+ style="stop-color:#c0cdf9;stop-opacity:1"
+ id="stop5787" />
+ <stop
+ offset="1"
+ style="stop-color:#07092d;stop-opacity:0.28804347"
+ id="stop5789" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10981-3-9">
+ <stop
+ offset="0"
+ style="stop-color:#729fcf;stop-opacity:1"
+ id="stop10983-2-0" />
+ <stop
+ offset="1"
+ style="stop-color:#729fcf;stop-opacity:0"
+ id="stop10985-3-7" />
+ </linearGradient>
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient5785"
+ id="linearGradient20622"
+ y2="40"
+ x2="60"
+ y1="20"
+ x1="82.118591" />
+ <filter
+ style="color-interpolation-filters:sRGB"
+ id="filter6017-3-0-8">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.80546496"
+ id="feGaussianBlur6019-9-8-2" />
+ </filter>
+ <filter
+ style="color-interpolation-filters:sRGB"
+ id="filter6031-0-9-2">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="3.4903482"
+ id="feGaussianBlur6033-8-8-3" />
+ </filter>
+ <clipPath
+ id="clipPath9086-1-0-9">
+ <use
+ xlink:href="#outline1"
+ height="300"
+ width="400"
+ y="0"
+ x="0"
+ style="opacity:0.25;fill:#ffffff;fill-opacity:1"
+ id="use9088-0-7-3"
+ transform="translate(1.0095461e-6)" />
+ </clipPath>
+ <filter
+ style="color-interpolation-filters:sRGB"
+ id="filter8490-0-2-5">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="2.4163949"
+ id="feGaussianBlur8492-5-5-9" />
+ </filter>
+ <linearGradient
+ gradientTransform="matrix(1.7576296,2.8325319e-8,-2.837214e-8,1.754729,134.14696,311.50758)"
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient5733"
+ id="shinySpecular-0-8-9"
+ y2="60"
+ x2="58"
+ y1="35"
+ x1="33" />
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient5733"
+ id="IcecapTip-0-7-8"
+ y2="50"
+ x2="90"
+ y1="20"
+ x1="60"
+ gradientTransform="matrix(1.7416344,2.8067547e-8,-2.8113942e-8,1.7387602,134.82458,312.17386)" />
+ <radialGradient
+ gradientTransform="matrix(1.4483002,2.3340279e-8,-1.5648879e-8,0.9678347,44.763324,267.71859)"
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient5733"
+ id="radialGradient9177-1-8-3"
+ fy="250.89737"
+ fx="116.31038"
+ r="30.599579"
+ cy="250.89737"
+ cx="116.31038" />
+ <radialGradient
+ gradientTransform="matrix(2.0032532,0,0,1.340898,-132.8752,-95.166065)"
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient5733"
+ id="radialGradient8574-0-5-5"
+ fy="251.99396"
+ fx="132.44434"
+ r="30.599579"
+ cy="251.99396"
+ cx="132.44434" />
+ <filter
+ style="color-interpolation-filters:sRGB"
+ id="filter8732-3-6-1"
+ x="-0.078079157"
+ width="1.1561583"
+ y="-0.11422065"
+ height="1.2284414">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.9579068"
+ id="feGaussianBlur8734-5-7-4" />
+ </filter>
+ <radialGradient
+ gradientTransform="matrix(0.92245387,1.4865931e-8,0,0.38988347,114.40869,377.54902)"
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient5733"
+ id="radialGradient8744-9-0-2"
+ fy="168.5"
+ fx="210.25"
+ r="34.25"
+ cy="168.5"
+ cx="210.25" />
+ <radialGradient
+ gradientTransform="matrix(1,0,0,0.4233577,0,97.164234)"
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient5733"
+ id="radialGradient8768-6-9-4"
+ fy="182.08189"
+ fx="217.5"
+ r="34.25"
+ cy="182.08189"
+ cx="217.5" />
+ <filter
+ style="color-interpolation-filters:sRGB"
+ id="filter8764-9-5-2"
+ x="-0.074262142"
+ width="1.1485243"
+ y="-0.1754123"
+ height="1.3508246">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="2.1195652"
+ id="feGaussianBlur8766-2-0-5" />
+ </filter>
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient5733"
+ id="linearGradient8912-9-6-6"
+ y2="201.5"
+ x2="231.75"
+ y1="195.1875"
+ x1="231.625"
+ gradientTransform="matrix(0.92245387,1.4865931e-8,-1.4890504e-8,0.92093156,113.25563,286.45578)" />
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient5733"
+ id="linearGradient8910-3-3-0"
+ y2="200.07138"
+ x2="231.37646"
+ y1="195.62132"
+ x1="231.37646" />
+ <filter
+ style="color-interpolation-filters:sRGB"
+ id="filter8906-3-7-0"
+ x="-0.085441329"
+ width="1.1708827"
+ y="-0.27823201"
+ height="1.556464">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.56515877"
+ id="feGaussianBlur8908-7-7-3" />
+ </filter>
+ <radialGradient
+ gradientTransform="matrix(1,0,0,0.1477455,0,174.56924)"
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient5733"
+ id="radialGradient8922-9-9-1"
+ fy="204.83229"
+ fx="228.21875"
+ r="14.09375"
+ cy="204.83229"
+ cx="228.21875" />
+ <filter
+ style="color-interpolation-filters:sRGB"
+ id="filter8980-1-3-2"
+ x="-0.069862768"
+ width="1.1397254"
+ y="-0.47285891"
+ height="1.9457178">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.82052366"
+ id="feGaussianBlur8982-9-3-6" />
+ </filter>
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient5733"
+ id="linearGradient8990-4-2-0"
+ y2="201.5"
+ x2="231.75"
+ y1="195.1875"
+ x1="231.625"
+ gradientTransform="matrix(0.35573162,-0.18006687,0.41715068,0.82138546,144.84733,364.83492)" />
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient5733"
+ id="linearGradient8992-2-5-2"
+ y2="200.07138"
+ x2="231.37646"
+ y1="195.62132"
+ x1="231.37646" />
+ <radialGradient
+ gradientTransform="matrix(1,0,0,0.1477455,0,174.56924)"
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient5733"
+ id="radialGradient8994-0-1-1"
+ fy="204.83229"
+ fx="228.21875"
+ r="14.09375"
+ cy="204.83229"
+ cx="228.21875" />
+ <radialGradient
+ gradientTransform="matrix(0.92245387,1.4865931e-8,0,0.37489687,114.40869,394.67458)"
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient5733"
+ id="radialGradient9004-6-2-3"
+ fy="187.86935"
+ fx="89.875"
+ r="22.75"
+ cy="187.86935"
+ cx="89.875" />
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient5733"
+ id="linearGradient9023-6-3-6"
+ y2="201.5"
+ x2="231.75"
+ y1="195.1875"
+ x1="231.625" />
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient5733"
+ id="linearGradient9025-1-0-8"
+ y2="200.07138"
+ x2="231.37646"
+ y1="195.62132"
+ x1="231.37646" />
+ <radialGradient
+ gradientTransform="matrix(1.1850746,-0.3283582,0.1228557,0.4433973,-45.068314,152.92161)"
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient5733"
+ id="radialGradient9046-1-8-3"
+ fy="230.83626"
+ fx="90.28125"
+ r="10.46875"
+ cy="230.83626"
+ cx="90.28125" />
+ <filter
+ style="color-interpolation-filters:sRGB"
+ id="filter9068-2-5-3"
+ x="-0.076179281"
+ width="1.1523587"
+ y="-0.1655701"
+ height="1.3311402">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.66458488"
+ id="feGaussianBlur9070-7-1-7" />
+ </filter>
+ <radialGradient
+ gradientTransform="matrix(1.7221535,0,0,1.6949765,-49.39526,-14.078057)"
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient5733"
+ id="radialGradient11553-3-7-6"
+ fy="21.225746"
+ fx="68.39994"
+ r="54.783398"
+ cy="21.225746"
+ cx="68.39994" />
+ <filter
+ style="color-interpolation-filters:sRGB"
+ id="filter9298-4-7-0">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="0.32610678"
+ id="feGaussianBlur9300-4-6-8" />
+ </filter>
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient5733"
+ id="linearGradient5905-4-8-5"
+ y2="223.5"
+ x2="153.5"
+ y1="208.16444"
+ x1="95.5" />
+ <filter
+ style="color-interpolation-filters:sRGB"
+ id="filter5983-8-2-7"
+ x="-0.082508981"
+ width="1.165018"
+ y="-0.12233575"
+ height="1.2446715">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="3.6868363"
+ id="feGaussianBlur5985-3-9-7" />
+ </filter>
+ <radialGradient
+ gradientTransform="matrix(1.3515234,0,0,1.7175707,-63.705646,-153.95568)"
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient5733"
+ id="radialGradient5811-3-3-7"
+ fy="214.55121"
+ fx="181.22731"
+ r="22.466398"
+ cy="214.55121"
+ cx="181.22731" />
+ <filter
+ style="color-interpolation-filters:sRGB"
+ id="filter5845-5-0-8">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.2409356"
+ id="feGaussianBlur5847-5-8-6" />
+ </filter>
+ <linearGradient
+ gradientTransform="matrix(0.85826228,1.3831443e-8,-1.3854306e-8,0.8568459,124.3741,295.26873)"
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient5733"
+ id="linearGradient5822-7-2-3"
+ y2="187.65974"
+ x2="82.754066"
+ y1="180.47572"
+ x1="73.712105" />
+ <linearGradient
+ gradientTransform="translate(-130.16572,-83.352786)"
+ gradientUnits="userSpaceOnUse"
+ xlink:href="#linearGradient10981-3-9"
+ id="linearGradient1539-7-2"
+ y2="144.5"
+ x2="153.70045"
+ y1="217.5"
+ x1="180.81293" />
+ <filter
+ style="color-interpolation-filters:sRGB"
+ id="filter10997-7-2-1-4">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="2.7696726"
+ id="feGaussianBlur10999-0-7-7-6" />
+ </filter>
+ <linearGradient
+ gradientTransform="translate(-7.5,-7.5)"
+ gradientUnits="userSpaceOnUse"
+ y2="17"
+ x2="13.5"
+ y1="10"
+ x1="13.5"
+ id="Glass">
+ <stop
+ id="stop7"
+ offset="0"
+ style="stop-color:#f8f8f8" />
+ <stop
+ id="stop9"
+ offset="1"
+ style="stop-color:#c0c0c0" />
+ </linearGradient>
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="29"
+ x2="15"
+ y1="1"
+ x1="15"
+ id="Background">
+ <stop
+ id="stop12"
+ offset="0"
+ style="stop-color:#f8f8f8" />
+ <stop
+ id="stop14"
+ offset="1"
+ style="stop-color:#b4b4b4" />
+ </linearGradient>
+ </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="1.7358067"
+ inkscape:cx="80.195395"
+ inkscape:cy="115.40677"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer7"
+ showgrid="false"
+ inkscape:window-width="1534"
+ inkscape:window-height="843"
+ inkscape:window-x="66"
+ inkscape:window-y="20"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:window-maximized="1"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:document-rotation="0" />
+ <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" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:groupmode="layer"
+ id="layer6"
+ inkscape:label="bgr"
+ style="display:inline"
+ transform="translate(-127.7556,-275.61689)" />
+ <g
+ inkscape:label="logo"
+ inkscape:groupmode="layer"
+ id="layer1"
+ style="display:inline"
+ transform="translate(-127.7556,-275.61689)" />
+ <g
+ inkscape:groupmode="layer"
+ id="layer5"
+ inkscape:label="draw"
+ style="display:inline"
+ transform="translate(-127.7556,-275.61689)" />
+ <g
+ inkscape:groupmode="layer"
+ id="layer7"
+ inkscape:label="draw2"
+ style="display:inline"
+ transform="translate(-127.7556,-275.61689)">
+ <g
+ id="g921"
+ transform="matrix(0.17823275,0,0,0.17823275,104.98537,226.49293)">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 238.44971,284.60355 -98.89637,101.12959 c -37.44621,37.38441 24.244,34.26903 46.56769,48.40801 10.3217,6.71004 -33.12548,15.33717 -24.24402,24.20403 8.64144,8.86679 52.08864,17.01469 60.73007,25.64186 8.64146,8.86681 -17.5229,18.21291 -8.88148,27.0797 8.4014,8.86686 28.56472,0.4793 32.16532,20.60936 2.64044,14.85791 36.96613,7.42895 52.32868,-5.27214 9.60158,-8.14789 -16.56273,-8.14789 -7.92132,-17.01471 21.60357,-21.80758 40.80677,-9.82539 48.72807,-29.95546 4.32072,-10.78394 -32.64541,-18.45254 -22.80377,-25.40222 23.5239,-16.53538 109.9382,-24.92292 70.09162,-64.70377 L 283.81721,284.60355 c -12.7221,-11.98221 -33.60555,-11.98221 -45.3675,0 z m 113.53881,194.83024 c 0,5.03253 39.12645,7.90825 36.96611,-1.19818 -3.12052,-15.33723 -32.64542,-14.13901 -36.96611,1.19818 z m -166.82764,26.60046 c 8.88146,7.66861 22.32369,-1.67753 26.64441,-12.46147 -8.64145,-11.26326 -40.5667,0.71892 -26.64441,12.46147 z m 162.02683,-16.05612 c -11.04182,10.06502 1.92032,20.60934 12.72209,13.65967 2.88049,-1.91713 -0.24002,-11.26326 -12.72209,-13.65967 z"
+ id="use7631"
+ style="fill:#000000;fill-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 277.81621,291.79286 39.1265,39.78084 c 3.6006,3.59466 3.6006,11.02361 1.44023,13.1804 l -19.4432,-15.81648 -3.84067,23.24545 -16.08266,-8.62719 -26.16431,16.53541 -8.64144,-34.74832 -13.92232,30.1951 -34.80577,-0.23966 c -6.7211,0 -5.76093,-6.94967 1.20022,-13.89935 13.68227,-15.09753 40.32669,-40.73938 48.72806,-49.60621 8.64144,-8.8668 23.76395,-8.62716 32.40536,1e-5 z"
+ id="icecap"
+ style="fill:#ffffff;fill-opacity:1" />
+ <g
+ id="g23586"
+ transform="matrix(1.1690028,0,0,1.1690028,-60.950459,-86.38167)">
+ <path
+ id="path4157"
+ d="m 367.93577,513.86204 c 0.0192,0.0297 0.0537,0.047 0.0753,0.0753 0.0267,0.0326 0.0407,0.0755 0.0674,0.1092 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;display:inline;fill:#808080;fill-opacity:1;stroke:none;stroke-width:1.64551"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path4344"
+ d="m 302.92276,513.88022 -0.14321,0.18447 c 0.0269,-0.0326 0.0407,-0.0755 0.0674,-0.1092 0.0191,-0.0297 0.0537,-0.047 0.0753,-0.0753 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:15px;line-height:125%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;display:inline;fill:#808080;fill-opacity:1;stroke:none;stroke-width:1.64551"
+ inkscape:connector-curvature="0" />
+ <ellipse
+ cy="479.36874"
+ cx="335.61429"
+ id="path2878"
+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:6.72579;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ rx="52.824123"
+ ry="53.017166" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4176-0"
+ d="m 310.87941,431.97304 4.5007,4.97442 10.6595,-3.79006 3.55317,6.63262 -13.02829,8.05382 -9.00132,11.13325 -5.21134,-3.07939 -5.44821,2.8425 3.07945,5.21134 3.55316,-1.65813 6.15879,9.23823 5.21132,-3.0794 12.55454,5.92189 11.60702,10.89641 -4.97445,10.89638 -11.607,16.1077 1.89502,8.76451 -6.86944,-4.2638 -3.79007,-23.6878 -6.39572,-8.76451 -0.23677,-10.6595 -9.94892,-7.34322 -7.58005,-2.13187 -1.42126,-5.92194 8.29071,-15.39707 z"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6.58333;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"
+ id="path4178"
+ d="m 335.27788,427.47235 -0.23676,7.34322 6.39568,0.94751 7.34322,-7.10633 z"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6.58333;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"
+ id="path4180"
+ d="m 359.4394,433.39429 -3.07943,4.97446 4.26382,3.79004 -4.26382,3.55315 1.65816,4.2638 9.47511,-4.50069 5.92196,4.50069 1.895,-5.92196 -11.84387,-9.00135 z"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6.58333;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"
+ id="path4182"
+ d="m 380.52153,453.52892 -9.23823,1.65811 -3.55317,-3.79004 -10.8964,0.71065 -6.63258,10.42262 4.50068,11.13326 14.68643,4.50066 2.84252,17.29214 3.55319,9.00135 8.29073,-4.73758 6.15883,-17.29209 -3.55317,-16.8183 z"
+ style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6.58333;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>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="zobrati"
+ style="display:inline;opacity:1"
+ transform="translate(-127.7556,-275.61689)" />
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="texts"
+ style="display:inline"
+ transform="translate(-127.7556,-275.61689)" />
+ <style
+ id="style26"
+ type="text/css" />
+</svg>
diff --git a/share/extensions/other/clipart/sources/ocal.py b/share/extensions/other/clipart/sources/ocal.py
new file mode 100644
index 0000000..2fe06db
--- /dev/null
+++ b/share/extensions/other/clipart/sources/ocal.py
@@ -0,0 +1,97 @@
+#
+# Copyright 2021 Martin Owens <doctormo@gmail.com>
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>
+#
+
+import sys
+import json
+import logging
+
+from import_sources import RemoteSource, RemoteFile
+from urllib.parse import urljoin, parse_qs
+
+try:
+ from bs4 import BeautifulSoup
+except ImportError:
+ BeautifulSoup = None
+
+
+class OpenClipartFile(RemoteFile):
+ def get_file(self):
+ """Extract search result from html"""
+ response = self.remote.session.get(self.info["file"])
+ soup = BeautifulSoup(response.text, features="lxml")
+ for script in soup.find_all("script"):
+ content = script.contents
+ if content and "image" in content[0]:
+ try:
+ data = json.loads(content[0])
+ return self.remote.to_local_file(data["image"]["url"])
+ except Exception:
+ continue
+ logging.error("Couldn't load svg from %s", self.info["file"])
+
+
+class OpenClipart(RemoteSource):
+ name = "Open Clipart Library"
+ icon = "sources/ocal.svg"
+ base_url = "https://openclipart.org/search/"
+ is_enabled = BeautifulSoup is not None
+ file_cls = OpenClipartFile
+
+ def html_search(self, response):
+ """Extract search results from html"""
+ soup = BeautifulSoup(response.text, features="lxml")
+ for div in soup.find_all("div", {"class": "artwork"}):
+ if div.a and div.a.img:
+ link = urljoin(self.base_url, div.a.get("href"))
+ img = urljoin(self.base_url, div.a.img.get("src"))
+
+ yield {
+ "file": link, # Not the actual file yet (see above)
+ "name": div.a.img.get("alt"),
+ "thumbnail": img,
+ "author": "OpenClipart",
+ "license": "cc-0",
+ }
+
+ for page in soup.find_all("a", {"class": "page-link", "aria-label": "Next"}):
+ if "=" in page.get("href", ""):
+ yield lambda: self._search(**parse_qs(page.get("href").split("?")[-1]))
+
+ def search(self, query):
+ """HTML searching for now"""
+ return self._search(query=query)
+
+ def _search(self, **params):
+ try:
+ response = self.session.get(self.base_url, params=params)
+ except Exception:
+ return []
+
+ items = []
+ next_page = None
+ for item in self.html_search(response):
+ if callable(item):
+ next_page = item
+ else:
+ items.append(item)
+ # Often ocal will have empty pages, weirdly.
+ if not items and next_page:
+ return next_page()
+ # None empty page, return all
+ if next_page:
+ items.append(next_page)
+ return items
diff --git a/share/extensions/other/clipart/sources/ocal.svg b/share/extensions/other/clipart/sources/ocal.svg
new file mode 100644
index 0000000..44eba39
--- /dev/null
+++ b/share/extensions/other/clipart/sources/ocal.svg
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<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="Layer_1"
+ data-name="Layer 1"
+ viewBox="0 0 48 47.999999"
+ version="1.1"
+ sodipodi:docname="ocal.svg"
+ width="48"
+ height="48"
+ inkscape:version="1.0.2 (1.0.2+r75+1)">
+ <metadata
+ id="metadata47">
+ <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>Reactome_Imagotype_Positive</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#999999"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="0"
+ inkscape:window-width="1534"
+ inkscape:window-height="843"
+ id="namedview45"
+ showgrid="false"
+ inkscape:zoom="2.1826528"
+ inkscape:cx="124.13182"
+ inkscape:cy="104.77682"
+ inkscape:window-x="66"
+ inkscape:window-y="20"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="Layer_1"
+ inkscape:document-rotation="0" />
+ <defs
+ id="defs4">
+ <style
+ id="style2">.cls-1{fill:#2f9ec2;}.cls-2{fill:#d1eaf2;}.cls-3{fill:#9bd1e2;}.cls-4{fill:#80c4da;}.cls-5{fill:#65b7d2;}.cls-6{fill:#4aabca;}</style>
+ </defs>
+ <title
+ id="title6">Reactome_Imagotype_Positive</title>
+ <g
+ id="g1060"
+ transform="matrix(0.06580048,0,0,0.06580048,-0.35339993,6.982498)">
+ <path
+ d="m 405.8243,48.494855 c -9.71472,-2.624519 -19.68464,3.088798 -22.30916,12.803515 l -85.35676,315.62604 c -2.62453,9.71473 3.08879,19.49065 12.8035,22.11516 l 315.62603,85.35678 c 9.71464,2.62451 19.68462,-3.0888 22.30914,-12.80352 l 85.3567,-315.62604 c 1.23722,-4.57954 0.461,-9.10928 -1.55194,-12.99751 v -0.194 l -0.19399,-0.38798 v -0.19399 c -0.0451,-0.0784 -0.14774,-0.11627 -0.19399,-0.194 l -14.54945,-30.06886 -65.95743,2.90989 z"
+ id="rect6080"
+ style="fill:#000000;fill-opacity:0.2;fill-rule:evenodd;stroke:none" />
+ <rect
+ width="363.28452"
+ height="363.28452"
+ rx="2.9260478"
+ ry="2.9260478"
+ x="363.42282"
+ y="-78.837021"
+ transform="rotate(15.117951)"
+ id="rect911"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#ffffff;stroke-width:7.75971;stroke-miterlimit:4;stroke-opacity:1" />
+ <rect
+ width="288.49521"
+ height="288.49521"
+ rx="2.3236644"
+ ry="2.3236644"
+ x="398.72931"
+ y="-39.355053"
+ transform="rotate(15.117951)"
+ id="rect912"
+ style="fill:#f3e533;fill-opacity:1;fill-rule:evenodd;stroke-width:0.794131pt" />
+ <path
+ d="m 552.48969,32.227283 -66.35244,21.339192 0.58197,0.193993 H 235.30476 c -10.06292,0 -18.04132,7.978343 -18.04132,18.041317 V 398.87339 c 0,10.06304 7.97834,18.04132 18.04132,18.04132 h 327.0716 c 10.06304,0 18.04132,-7.97834 18.04132,-18.04132 V 71.801785 c 0,-5.188823 -2.15962,-9.693549 -5.62579,-12.997509 z"
+ id="rect6079"
+ style="fill:#000000;fill-opacity:0.2;fill-rule:evenodd;stroke:none" />
+ <rect
+ width="363.28418"
+ height="363.28418"
+ rx="2.9260466"
+ ry="2.9260466"
+ x="192.47523"
+ y="30.531385"
+ id="rect913"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#ffffff;stroke-width:7.75971;stroke-miterlimit:4;stroke-opacity:1" />
+ <rect
+ width="288.49512"
+ height="288.49512"
+ rx="2.3236635"
+ ry="2.3236635"
+ x="227.78207"
+ y="70.013809"
+ id="rect914"
+ style="fill:#ff7f00;fill-rule:evenodd;stroke-width:0.794131pt" />
+ <path
+ d="m 348.20848,28.541423 -57.03385,38.02256 13.96748,1.551942 -249.474556,89.042615 c -9.479318,3.37716 -14.434728,13.60583 -11.05758,23.08513 l 94.280426,264.79998 -6.59575,-0.19399 -4.26783,40.54445 35.50064,13.1915 h 0.388 c 4.13635,1.85929 8.97108,2.41781 13.57948,0.77598 L 485.55528,389.56176 C 495.03452,386.1846 499.796,375.762 496.41886,366.28264 L 386.81301,58.416291 c -1.55516,-4.365114 -4.78917,-7.440813 -8.53567,-9.505639 z"
+ id="rect6078"
+ style="fill:#000000;fill-opacity:0.2;fill-rule:evenodd;stroke:none" />
+ <rect
+ width="363.28326"
+ height="363.28326"
+ rx="2.9260383"
+ ry="2.9260383"
+ x="-41.716114"
+ y="142.20343"
+ transform="rotate(-19.609274)"
+ id="rect915"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#ffffff;stroke-width:7.7597;stroke-miterlimit:4;stroke-opacity:1" />
+ <rect
+ width="288.49469"
+ height="288.49469"
+ rx="2.3236592"
+ ry="2.3236592"
+ x="-6.4090877"
+ y="181.68738"
+ transform="rotate(-19.609274)"
+ id="rect916"
+ style="fill:#bf0000;fill-rule:evenodd;stroke-width:0.794131pt" />
+ </g>
+</svg>
diff --git a/share/extensions/other/clipart/sources/reactome.py b/share/extensions/other/clipart/sources/reactome.py
new file mode 100644
index 0000000..1a1c8b3
--- /dev/null
+++ b/share/extensions/other/clipart/sources/reactome.py
@@ -0,0 +1,64 @@
+#
+# Copyright 2021 Martin Owens <doctormo@gmail.com>
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>
+#
+"""
+Access Reactome Content Services.
+"""
+
+import re
+
+from import_sources import RemoteSource
+
+TAG_REX = re.compile(r'<[^<]+?>')
+
+class Reactome(RemoteSource):
+ name = 'Reactome (Bio)'
+ icon = 'sources/reactome.svg'
+ search_url = "https://reactome.org/ContentService/search/query"
+ file_url = "https://reactome.org/icon/{stId}.svg"
+ icon_url = "https://reactome.org/icon/{stId}.png"
+ all_licence = "cc-by-sa-4.0"
+
+ def search(self, query):
+ params = {
+ "query": query,
+ "types": "Icon",
+ "cluster": "true",
+ "Start row": 0,
+ "rows": 100,
+ }
+ response = {}
+ try:
+ response = self.session.get(self.search_url, params=params).json()
+ except Exception:
+ pass
+
+ if 'messages' in response and 'No entries' in response['messages'][0]:
+ return
+ for cats in response.get('results', []):
+ for entry in cats['entries']:
+ yield {
+ 'id': entry['dbId'],
+ 'name': TAG_REX.sub('', entry['name']),
+ 'author': 'Reactome/'+entry.get('iconDesignerName', "Unknown"),
+ 'summary': TAG_REX.sub('', entry.get('summation', '')),
+ 'created': None, # No data
+ 'popularity': 0, # No data
+ 'thumbnail': self.icon_url.format(**entry),
+ 'file': self.file_url.format(**entry),
+ 'license': self.all_licence,
+ }
+
diff --git a/share/extensions/other/clipart/sources/reactome.svg b/share/extensions/other/clipart/sources/reactome.svg
new file mode 100644
index 0000000..3c6562c
--- /dev/null
+++ b/share/extensions/other/clipart/sources/reactome.svg
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<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="Layer_1"
+ data-name="Layer 1"
+ viewBox="0 0 48 47.999999"
+ version="1.1"
+ sodipodi:docname="reactome.svg"
+ width="48"
+ height="48"
+ inkscape:version="1.0.2 (1.0.2+r75+1)">
+ <metadata
+ id="metadata47">
+ <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>Reactome_Imagotype_Positive</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#999999"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="0"
+ inkscape:window-width="1534"
+ inkscape:window-height="843"
+ id="namedview45"
+ showgrid="false"
+ inkscape:zoom="2.1826528"
+ inkscape:cx="124.13182"
+ inkscape:cy="104.77682"
+ inkscape:window-x="66"
+ inkscape:window-y="20"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="Layer_1" />
+ <defs
+ id="defs4">
+ <style
+ id="style2">.cls-1{fill:#2f9ec2;}.cls-2{fill:#d1eaf2;}.cls-3{fill:#9bd1e2;}.cls-4{fill:#80c4da;}.cls-5{fill:#65b7d2;}.cls-6{fill:#4aabca;}</style>
+ </defs>
+ <title
+ id="title6">Reactome_Imagotype_Positive</title>
+ <g
+ id="g884"
+ transform="translate(-9.6921658,-91.760459)">
+ <polygon
+ class="cls-2"
+ points="6.697,15.467 20.092,7.733 20.092,0 0,11.6 0,34.801 6.697,30.934 "
+ id="polygon24"
+ transform="translate(14.104496,92.732857)" />
+ <polygon
+ class="cls-3"
+ points="6.697,38.667 13.395,34.801 13.395,27.067 6.697,30.934 "
+ id="polygon26"
+ transform="translate(14.104496,92.732857)" />
+ <polygon
+ class="cls-3"
+ points="26.79,3.867 20.092,7.733 20.092,15.467 26.79,11.6 "
+ id="polygon28"
+ transform="translate(14.104496,92.732857)" />
+ <polygon
+ class="cls-4"
+ points="13.395,27.067 13.395,19.334 20.092,15.467 20.092,7.733 6.697,15.467 6.697,30.934 "
+ id="polygon30"
+ transform="translate(14.104496,92.732857)" />
+ <polygon
+ class="cls-5"
+ points="26.79,27.067 26.79,34.801 33.487,30.934 33.487,23.2 "
+ id="polygon32"
+ transform="translate(14.104496,92.732857)" />
+ <polygon
+ class="cls-5"
+ points="33.487,7.733 26.79,11.6 26.79,19.334 33.487,15.467 "
+ id="polygon34"
+ transform="translate(14.104496,92.732857)" />
+ <polygon
+ class="cls-5"
+ points="13.395,42.534 20.092,38.667 20.092,30.934 13.395,34.801 "
+ id="polygon36"
+ transform="translate(14.104496,92.732857)" />
+ <polygon
+ class="cls-6"
+ points="13.395,27.067 13.395,34.801 20.092,30.934 20.092,23.2 26.79,19.334 26.79,11.6 20.092,15.467 20.092,23.2 "
+ id="polygon38"
+ transform="translate(14.104496,92.732857)" />
+ <polygon
+ class="cls-1"
+ points="13.395,27.067 20.092,23.2 20.092,15.467 13.395,19.334 "
+ id="polygon40"
+ transform="translate(14.104496,92.732857)" />
+ <polygon
+ class="cls-1"
+ points="20.092,46.401 26.79,42.534 26.79,34.801 26.79,27.067 26.79,27.067 26.79,27.067 33.487,23.2 40.184,19.334 40.184,11.6 33.487,15.467 26.79,19.334 20.092,23.2 20.092,30.934 20.092,38.667 "
+ id="polygon42"
+ transform="translate(14.104496,92.732857)" />
+ </g>
+</svg>
diff --git a/share/extensions/other/clipart/sources/wikimedia.py b/share/extensions/other/clipart/sources/wikimedia.py
new file mode 100644
index 0000000..f260bc8
--- /dev/null
+++ b/share/extensions/other/clipart/sources/wikimedia.py
@@ -0,0 +1,76 @@
+#
+# Copyright 2021 Martin Owens <doctormo@gmail.com>
+# Copyright 2022 Simon Duerr <dev@simonduerr.eu>
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>
+#
+
+import hashlib
+from import_sources import RemoteSource
+
+
+class Wikimedia(RemoteSource):
+ name = "Wikimedia"
+ icon = "sources/wikimedia.svg"
+ base_url = "https://commons.wikimedia.org/w/api.php"
+
+ def search(self, query):
+ params = {
+ "action": "query",
+ "format": "json",
+ "uselang": "en",
+ "generator": "search",
+ "gsrsearch": "filetype:bitmap|drawing filemime:svg " + query,
+ "gsrlimit": 40,
+ "gsroffset": 0,
+ "gsrinfo": "totalhits|suggestion",
+ "gsrprop": "size|wordcount",
+ "gsrnamespace": 6,
+ "prop": "info|imageinfo|entityterms",
+ "inprop": "url",
+ "iiprop": "url|size|mime|user|extmetadata",
+ "iiurlheight": 180,
+ "wbetterms": "label",
+ }
+ pages = []
+ try:
+ response = self.session.get(self.base_url, params=params).json()
+ if "error" in response:
+ raise IOError(response["error"]["info"])
+ pages = response["query"]["pages"].values()
+ except:
+ pass
+
+ for item in pages:
+ img = item["imageinfo"][0]
+ # get standard licenses
+ # for non standard licenses we have to get the ShortName and provide the url to the resource
+ try:
+ license = img["extmetadata"]["License"]["value"]
+ if license in ["cc0", "pd"]:
+ license = "cc-0"
+ except KeyError:
+ license = img["extmetadata"]["LicenseShortName"]["value"]
+ yield {
+ "id": item.get("pageid", None),
+ "name": item["title"].split(":", 1)[-1],
+ "author": img["user"],
+ "license": license,
+ "summary": "", # No data
+ "thumbnail": img["thumburl"],
+ "created": item["touched"],
+ "descriptionurl": item["canonicalurl"],
+ "popularity": 0, # No data
+ "file": img["url"],
+ }
diff --git a/share/extensions/other/clipart/sources/wikimedia.svg b/share/extensions/other/clipart/sources/wikimedia.svg
new file mode 100644
index 0000000..23387ab
--- /dev/null
+++ b/share/extensions/other/clipart/sources/wikimedia.svg
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<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="Layer_1"
+ data-name="Layer 1"
+ viewBox="0 0 48 47.999999"
+ version="1.1"
+ sodipodi:docname="wikimedia.svg"
+ width="48"
+ height="48"
+ inkscape:version="1.0.2 (1.0.2+r75+1)">
+ <metadata
+ id="metadata47">
+ <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>Reactome_Imagotype_Positive</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#999999"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="0"
+ inkscape:window-width="1534"
+ inkscape:window-height="843"
+ id="namedview45"
+ showgrid="false"
+ inkscape:zoom="2.1826528"
+ inkscape:cx="124.13182"
+ inkscape:cy="104.77682"
+ inkscape:window-x="66"
+ inkscape:window-y="20"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="Layer_1"
+ inkscape:document-rotation="0" />
+ <defs
+ id="defs4">
+ <style
+ id="style2">.cls-1{fill:#2f9ec2;}.cls-2{fill:#d1eaf2;}.cls-3{fill:#9bd1e2;}.cls-4{fill:#80c4da;}.cls-5{fill:#65b7d2;}.cls-6{fill:#4aabca;}</style>
+ <clipPath
+ id="a">
+ <path
+ d="M47.5-87.5v425h-95v-425l-552-552v1250h1199v-1250z"
+ id="path1135" />
+ </clipPath>
+ </defs>
+ <title
+ id="title6">Reactome_Imagotype_Positive</title>
+ <g
+ id="g1160"
+ transform="matrix(0.04316547,0,0,0.04316547,23.654678,24.345325)">
+ <g
+ clip-path="url(#a)"
+ id="g1144">
+ <circle
+ r="336.5"
+ fill="#339966"
+ id="circle1140"
+ cx="0"
+ cy="0" />
+ <circle
+ r="480.25"
+ fill="none"
+ stroke="#006699"
+ stroke-width="135.5"
+ id="circle1142"
+ cx="0"
+ cy="0" />
+ </g>
+ <circle
+ cy="-379.5"
+ r="184.5"
+ fill="#990000"
+ id="circle1146"
+ cx="0" />
+ </g>
+</svg>
diff --git a/share/extensions/other/gcodetools/.darglint b/share/extensions/other/gcodetools/.darglint
new file mode 100644
index 0000000..4447949
--- /dev/null
+++ b/share/extensions/other/gcodetools/.darglint
@@ -0,0 +1,3 @@
+[darglint]
+docstring_style=google
+strictness=short \ No newline at end of file
diff --git a/share/extensions/other/gcodetools/.pylintrc b/share/extensions/other/gcodetools/.pylintrc
new file mode 100644
index 0000000..a3903f9
--- /dev/null
+++ b/share/extensions/other/gcodetools/.pylintrc
@@ -0,0 +1,374 @@
+[MASTER]
+
+# Specify a configuration file.
+#rcfile=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+init-hook='import sys; sys.path.append("pythonenv/lib/python3.6/site-packages"); sys.path.append("../pythonenv/lib/python3.6/site-packages"); sys.path.append("../../pythonenv/lib/python3.6/site-packages"); sys.path.append("../../../pythonenv/lib/python3.6/site-packages");'
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=CVS
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# Use multiple processes to speed up Pylint.
+jobs=1
+
+# Allow loading of arbitrary C extensions. Extensions are imported into the
+# active Python interpreter and may run arbitrary code.
+unsafe-load-any-extension=no
+
+# A comma-separated list of package or module names from where C extensions may
+# be loaded. Extensions are loading into the active Python interpreter and may
+# run arbitrary code
+extension-pkg-whitelist=lxml,numpy
+
+# Allow optimization of some AST trees. This will activate a peephole AST
+# optimizer, which will apply various small optimizations. For instance, it can
+# be used to obtain the result of joining multiple strings with the addition
+# operator. Joining a lot of strings can lead to a maximum recursion error in
+# Pylint and this flag can prevent that. It has one side effect, the resulting
+# AST will be different than the one from reality.
+optimize-ast=no
+
+
+[MESSAGES CONTROL]
+
+# Only show warnings with the listed confidence levels. Leave empty to show
+# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
+confidence=
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time. See also the "--disable" option for examples.
+#enable=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifiers separated by comma (,) or put this
+# option multiple times (only on the command line, not in the configuration
+# file where it should appear only once).You can also use "--disable=all" to
+# disable everything first and then reenable specific checks. For example, if
+# you want to run only the similarities checker, you can use "--disable=all
+# --enable=similarities". If you want to run only the classes checker, but have
+# no Warning level messages displayed, use"--disable=all --enable=classes
+# --disable=W"
+disable=old-octal-literal,oct-method,print-statement,unpacking-in-except,parameter-unpacking,backtick,old-raise-syntax,old-ne-operator,long-suffix,dict-view-method,dict-iter-method,metaclass-assignment,next-method-called,raising-string,indexing-exception,raw_input-builtin,long-builtin,file-builtin,execfile-builtin,coerce-builtin,cmp-builtin,buffer-builtin,basestring-builtin,apply-builtin,filter-builtin-not-iterating,using-cmp-argument,useless-suppression,range-builtin-not-iterating,suppressed-message,no-absolute-import,old-division,cmp-method,reload-builtin,zip-builtin-not-iterating,intern-builtin,unichr-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,input-builtin,round-builtin,hex-method,nonzero-method,map-builtin-not-iterating,superfluous-parens,missing-super-argument,model-missing-unicode
+
+
+[REPORTS]
+
+# Set the output format. Available formats are text, parseable, colorized, msvs
+# (visual studio) and html. You can also give a reporter class, eg
+# mypackage.mymodule.MyReporterClass.
+output-format=text
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# Tells whether to display a full report or only the messages
+reports=yes
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note). You have access to the variables errors warning, statement which
+# respectively contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Template used to display messages. This is a python new-style format string
+# used to format the message information. See doc for all details
+#msg-template=
+
+
+[SIMILARITIES]
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+# Ignore imports when computing similarities.
+ignore-imports=no
+
+
+[FORMAT]
+
+# Maximum number of characters on a single line.
+max-line-length=100
+
+# Regexp for a line that is allowed to be longer than the limit.
+ignore-long-lines=^\s*(# )?<?https?://\S+>?$
+
+# Allow the body of an if to be on the same line as the test if there is no
+# else.
+single-line-if-stmt=no
+
+# List of optional constructs for which whitespace checking is disabled. `dict-
+# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
+# `trailing-comma` allows a space between comma and closing bracket: (a, ).
+# `empty-line` allows space-only lines.
+no-space-check=trailing-comma,dict-separator
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string=' '
+
+# Number of spaces of indent required inside a hanging or continued line.
+indent-after-paren=4
+
+# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
+expected-line-ending-format=
+
+
+[BASIC]
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=map,filter,input
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,x,y,z,ex,Run,_,__,js,rx,x1,y1,x2,y2
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# Colon-delimited sets of names that determine each other's naming style when
+# the name regexes allow several styles.
+name-group=
+
+# Include a hint for the correct naming format with invalid-name
+include-naming-hint=no
+
+# Regular expression matching correct function names
+function-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Naming hint for function names
+function-name-hint=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression matching correct variable names
+variable-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Naming hint for variable names
+variable-name-hint=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression matching correct constant names
+const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
+
+# Naming hint for constant names
+const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
+
+# Regular expression matching correct attribute names
+attr-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Naming hint for attribute names
+attr-name-hint=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression matching correct argument names
+argument-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Naming hint for argument names
+argument-name-hint=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression matching correct class attribute names
+class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
+
+# Naming hint for class attribute names
+class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
+
+# Regular expression matching correct inline iteration names
+inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
+
+# Naming hint for inline iteration names
+inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
+
+# Regular expression matching correct class names
+class-rgx=[A-Z_][a-zA-Z0-9]+$
+
+# Naming hint for class names
+class-name-hint=[A-Z_][a-zA-Z0-9]+$
+
+# Regular expression matching correct module names
+module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Naming hint for module names
+module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression matching correct method names
+method-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Naming hint for method names
+method-name-hint=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match function or class names that do
+# not require a docstring.
+no-docstring-rgx=^_
+
+# Minimum line length for functions/classes that require docstrings, shorter
+# ones are exempt.
+docstring-min-length=-1
+
+
+[ELIF]
+
+# Maximum number of nested blocks for function / method body
+max-nested-blocks=5
+
+
+[TYPECHECK]
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# List of module names for which member attributes should not be checked
+# (useful for modules/projects where namespaces are manipulated during runtime
+# and thus existing member attributes cannot be deduced by static analysis. It
+# supports qualified module names, as well as Unix pattern matching.
+ignored-modules=
+
+# List of classes names for which member attributes should not be checked
+# (useful for classes with attributes dynamically set). This supports can work
+# with qualified names.
+ignored-classes=SQLObject,WSGIRequest
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E1101 when accessed. Python regular
+# expressions are accepted.
+generated-members=objects,DoesNotExist,id,pk,_meta,base_fields,context
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,XXX,TODO
+
+
+[LOGGING]
+
+# Logging modules to check that the string format arguments are in logging
+# function parameter format
+logging-modules=logging
+
+
+[VARIABLES]
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# A regular expression matching the name of dummy variables (i.e. expectedly
+# not used).
+dummy-variables-rgx=_$|dummy
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+# List of strings which can identify a callback function by name. A callback
+# name must start or end with one of those strings.
+callbacks=cb_,_cb
+
+
+[SPELLING]
+
+# Spelling dictionary name. Available dictionaries: none. To make it working
+# install python-enchant package.
+spelling-dict=
+
+# List of comma separated words that should not be checked.
+spelling-ignore-words=
+
+# A path to a file that contains private dictionary; one word per line.
+spelling-private-dict-file=
+
+# Tells whether to store unknown words to indicated private dictionary in
+# --spelling-private-dict-file option instead of raising a message.
+spelling-store-unknown-words=no
+
+
+[CLASSES]
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+# List of valid names for the first argument in a metaclass class method.
+valid-metaclass-classmethod-first-arg=mcs
+
+# List of member names, which should be excluded from the protected access
+# warning.
+exclude-protected=_asdict,_fields,_replace,_source,_make
+
+
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,TERMIOS,Bastion,rexec
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled)
+import-graph=
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled)
+int-import-graph=
+
+
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=5
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore
+ignored-argument-names=_.*
+
+# Maximum number of locals for function / method body
+max-locals=15
+
+# Maximum number of return / yield for function / method body
+max-returns=6
+
+# Maximum number of branch for function / method body
+max-branches=12
+
+# Maximum number of statements in function / method body
+max-statements=50
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=2
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+# Maximum number of boolean expressions in a if statement
+max-bool-expr=5
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when being caught. Defaults to
+# "Exception"
+overgeneral-exceptions=Exception
diff --git a/share/extensions/other/gcodetools/LICENSE.txt b/share/extensions/other/gcodetools/LICENSE.txt
new file mode 100644
index 0000000..b83f24b
--- /dev/null
+++ b/share/extensions/other/gcodetools/LICENSE.txt
@@ -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) <year> <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) 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
+
+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.
diff --git a/share/extensions/other/gcodetools/MANIFEST.in b/share/extensions/other/gcodetools/MANIFEST.in
new file mode 100644
index 0000000..2f29cde
--- /dev/null
+++ b/share/extensions/other/gcodetools/MANIFEST.in
@@ -0,0 +1,2 @@
+include *.py
+include *.inx
diff --git a/share/extensions/other/gcodetools/README.md b/share/extensions/other/gcodetools/README.md
new file mode 100644
index 0000000..faf25c9
--- /dev/null
+++ b/share/extensions/other/gcodetools/README.md
@@ -0,0 +1,45 @@
+# Gcodetools
+
+This folder contains gcodetools extension. They require the Inkscape extensions API inkex, see https://gitlab.com/inkscape/extensions.
+
+## Installation
+
+These scripts should be installed with an Inkscape package already (if you have
+installed Inkscape). For packagers or people testing newer releases, you can
+install the *.inx and *.py files into /usr/share/inkscape/extensions or
+~/.config/inkscape/extensions .
+
+## Testing
+
+These extensions are designed to have good test coverage for python 3.6 and above.
+
+You must install the program `pytest` in order to run these tests. You may run all tests by omitting any other parameters or select tests by adding the test filename that you want to run.
+
+ pytest
+ pytest tests/test_gcodetools.py
+
+See TESTING.md for further details.
+
+## Extension description
+
+Each *.inx file describes an extension, listing its name, purpose,
+prerequisites, location within the menu, etc. These files are read by
+Inkscape on launch. Other files are the scripts themselves (Perl,
+Python, and Ruby are supported, as well as shell scripts).
+
+## Development
+
+Development of both the core inkex modules, tests and each of the extensions
+contained within the core inkscape extensions repository should follow these
+basic rules of quality assurance:
+
+ * Use python3.6 or later, no python2 code would be used here.
+ * Use pylint to ensure code is written consistantly
+ * Have tests so that each line of an extension is covered in the coverage report
+ * Not cross streams between extensions, so your extension should import from
+ a module and not from another extension.
+ * Use translations on text for display to users using get text.
+ * Should not require external programs to work (with some exceptions)
+
+Also join the community on chat.inkscape.org channel #inkscape_extensions with any
+doubts or problems. \ No newline at end of file
diff --git a/share/extensions/other/gcodetools/TESTING.md b/share/extensions/other/gcodetools/TESTING.md
new file mode 100644
index 0000000..07158a6
--- /dev/null
+++ b/share/extensions/other/gcodetools/TESTING.md
@@ -0,0 +1,104 @@
+# Why Test Extensions
+
+Previously, Inkscape extensions were not tested for quality or correctness. But since 1.0, the extensions repository is far more strict about requiring tests and requiring tests to pass before changes can be merged in.
+
+You may find yourself being frustrated by the tests, especially if at first it doesn't make sense why they are failing. But these tests are important and I ask that everyone be as kind as they can to make sure the quality of the repository is maintained.
+
+# Running Tests
+
+You must install the program `pytest` in order to run these tests. Both Pytest and Pytest-Coverage are required to run tests.
+
+Usually the best way to install it is:
+
+```shell
+$ pip3 install pytest pytest-cov
+```
+
+You may run all tests by omitting any other parameters or select tests by adding the test filename that you want to run.
+
+```shell
+$ pytest
+$ pytest tests/test_my_extension.py
+```
+
+You can also run tests until the first time they fail, and ask pytest to run the previously failed tests first. This can cut down how long pytest takes to run before hitting a failure.
+
+```shell
+$ pytest -x --ff
+```
+
+More info here: https://docs.pytest.org/en/latest/getting-started.html
+
+# Test Files
+
+Each extension should have its own test file in the tests directory. This test may be a series of function tests or "comparison" tests. The comparison tests will fail whenever the output of an extension changes, so often they will need to be updated to reflect your changes.
+
+Usually the test file will be named `tests/test_{name_of_extension}.py` using the same name as the extension file itself. For tests covering inkex and other modules you may find test files have the format `tests/test_{package}_{module}.py` or similar.
+
+Each test can be run independently as shown in the previous section.
+
+# Test Data
+
+As well as python test files, each test will normally depend on additional data. From source svg files, to output comparison tests and other such things.
+
+This data is always held in `tests/data`, when writing tests, please make sure your data goes into the right directory. If you are updating the comparison test, usually you just need to rename the `export` file generated and remove the `.export` suffix to enable it.
+
+See tests/data/README.md for further information.
+
+# Writing or Updating tests
+
+You need to read the documentation available inside the tester module to learn how to write tests, or what the test code means. From a python3 terminal type:
+
+```python
+from inkex import tester
+help(tester)
+```
+
+# Coverage
+
+Coverage reports tell us how much of an extension is being exercised when tests are run.
+
+The latest coverage report for master branch can be found at
+https://inkscape.gitlab.io/extensions/coverage/.
+
+To run a complete coverage report, you can specify the `--cov=.` option like so:
+
+```shell
+$ pytest --cov=. --cov-report term
+```
+
+For a single extension coverage report, you can limit it further with:
+
+```shell
+$ pytest --cov=my_extension.py --cov-report term
+```
+
+## Testing Options
+
+Tests can be run with these options that are provided as environment variables:
+
+ FAIL_ON_DEPRECATION=1 - Will instantly fail any use of deprecated APIs
+ EXPORT_COMPARE=1 - Generate output files from comparisons. This is useful for manually checking the output as well as updating the comparison data.
+ NO_MOCK_COMMANDS=1 - Instead of using the mock data, actually call commands. This will also generate the msg files similar to export compare.
+ INKSCAPE_COMMAND=/other/inkscape - Use a different Inkscape (for example development version) while running commands. Works outside of tests too.
+ XML_DIFF=1 - Attempt to output an XML diff file, this can be useful for debugging to see differences in context.
+ DEBUG_KEY=1 - Export mock file keys for debugging. This is a highly specialised option for debugging key generation.
+
+For example:
+
+```shell
+$ EXPORT_COMPARE=1 pytest
+```
+
+or
+
+```shell
+export EXPORT_COMPARE=1
+pytest
+```
+
+# Testing custom extensions
+
+The same testing framework can be used in your own extension repositories by requiring the inkex module and using the inkex.tester module set. It should be available with Inkscape or can be installed via pypi.
+
+This is a great way of ensuring you have access to the same tools Inkscape uses to test, and makes it easier for your external extension to make its way to the core repository without resistance.
diff --git a/share/extensions/other/gcodetools/gcodetools.py b/share/extensions/other/gcodetools/gcodetools.py
new file mode 100755
index 0000000..ef8bdd2
--- /dev/null
+++ b/share/extensions/other/gcodetools/gcodetools.py
@@ -0,0 +1,5930 @@
+#!/usr/bin/env python
+# coding=utf-8
+#
+# Copyright (C) 2005 Aaron Spike, aaron@ekips.org (super paths et al)
+# 2007 hugomatic... (gcode.py)
+# 2009 Nick Drobchenko, nick@cnc-club.ru (main developer)
+# 2011 Chris Lusby Taylor, clusbytaylor@enterprise.net (engraving functions)
+#
+# 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.
+#
+"""
+Comments starting "#LT" or "#CLT" are by Chris Lusby Taylor who rewrote the engraving function in 2011.
+History of CLT changes to engraving and other functions it uses:
+9 May 2011 Changed test of tool diameter to square it
+10 May Note that there are many unused functions, including:
+ bound_to_bound_distance, csp_curvature_radius_at_t,
+ csp_special_points, csplength, rebuild_csp, csp_slope,
+ csp_simple_bound_to_point_distance, csp_bound_to_point_distance,
+ bez_at_t, bez_to_point_distance, bez_normalized_slope, matrix_mul, transpose
+ Fixed csp_point_inside_bound() to work if x outside bounds
+20 May Now encoding the bisectors of angles.
+23 May Using r/cos(a) instead of normalised normals for bisectors of angles.
+23 May Note that Z values generated for engraving are in pixels, not mm.
+ Removed the biarc curves - straight lines are better.
+24 May Changed Bezier slope calculation to be less sensitive to tiny differences in points.
+ Added use of self.options.engraving_newton_iterations to control accuracy
+25 May Big restructure and new recursive function.
+ Changed the way I treat corners - I now find if the centre of a proposed circle is
+ within the area bounded by the line being tested and the two angle bisectors at
+ its ends. See get_radius_to_line().
+29 May Eliminating redundant points. If A,B,C colinear, drop B
+30 May Eliminating redundant lines in divided Beziers. Changed subdivision of lines
+ 7Jun Try to show engraving in 3D
+ 8 Jun Displaying in stereo 3D.
+ Fixed a bug in bisect - it could go wrong due to rounding errors if
+ 1+x1.x2+y1.y2<0 which should never happen. BTW, I spotted a non-normalised normal
+ returned by csp_normalized_normal. Need to check for that.
+ 9 Jun Corrected spelling of 'definition' but still match previous 'defention' and 'defenition' if found in file
+ Changed get_tool to find 1.6.04 tools or new tools with corrected spelling
+10 Jun Put 3D into a separate layer called 3D, created unless it already exists
+ Changed csp_normalized_slope to reject lines shorter than 1e-9.
+10 Jun Changed all dimensions seen by user to be mm/inch, not pixels. This includes
+ tool diameter, maximum engraving distance, tool shape and all Z values.
+12 Jun ver 208 Now scales correctly if orientation points moved or stretched.
+12 Jun ver 209. Now detect if engraving toolshape not a function of radius
+ Graphics now indicate Gcode toolpath, limited by min(tool diameter/2,max-dist)
+24 Jan 2017 Removed hard-coded scale values from orientation point calculation
+TODO Change line division to be recursive, depending on what line is touched. See line_divide
+"""
+
+__version__ = '1.7'
+
+import cmath
+import copy
+import math
+import os
+import re
+import sys
+import time
+from functools import partial
+
+import numpy
+
+import inkex
+from inkex.bezier import bezierlength, bezierparameterize, beziertatlength
+from inkex import Transform, PathElement, TextElement, Tspan, Group, Layer, Marker, CubicSuperPath, Style
+
+if sys.version_info[0] > 2:
+ xrange = range
+ unicode = str
+
+def ireplace(self, old, new, count=0):
+ pattern = re.compile(re.escape(old), re.I)
+ return re.sub(pattern, new, self, count)
+
+
+################################################################################
+#
+# Styles and additional parameters
+#
+################################################################################
+
+TAU = math.pi * 2
+STRAIGHT_TOLERANCE = 0.0001
+STRAIGHT_DISTANCE_TOLERANCE = 0.0001
+ENGRAVING_TOLERANCE = 0.0001
+LOFT_LENGTHS_TOLERANCE = 0.0000001
+
+EMC_TOLERANCE_EQUAL = 0.00001
+
+options = {}
+defaults = {
+ 'header': """%
+(Header)
+(Generated by gcodetools from Inkscape.)
+(Using default header. To add your own header create file "header" in the output dir.)
+M3
+(Header end.)
+""",
+ 'footer': """
+(Footer)
+M5
+G00 X0.0000 Y0.0000
+M2
+(Using default footer. To add your own footer create file "footer" in the output dir.)
+(end)
+%"""
+}
+
+INTERSECTION_RECURSION_DEPTH = 10
+INTERSECTION_TOLERANCE = 0.00001
+
+def marker_style(stroke, marker='DrawCurveMarker', width=1):
+ """Set a marker style with some basic defaults"""
+ return Style(stroke=stroke, fill='none', stroke_width=width,
+ marker_end='url(#{})'.format(marker))
+
+MARKER_STYLE = {
+ "in_out_path_style": marker_style('#0072a7', 'InOutPathMarker'),
+ "loft_style": {
+ 'main curve': marker_style('#88f', 'Arrow2Mend'),
+ },
+ "biarc_style": {
+ 'biarc0': marker_style('#88f'),
+ 'biarc1': marker_style('#8f8'),
+ 'line': marker_style('#f88'),
+ 'area': marker_style('#777', width=0.1),
+ },
+ "biarc_style_dark": {
+ 'biarc0': marker_style('#33a'),
+ 'biarc1': marker_style('#3a3'),
+ 'line': marker_style('#a33'),
+ 'area': marker_style('#222', width=0.3),
+ },
+ "biarc_style_dark_area": {
+ 'biarc0': marker_style('#33a', width=0.1),
+ 'biarc1': marker_style('#3a3', width=0.1),
+ 'line': marker_style('#a33', width=0.1),
+ 'area': marker_style('#222', width=0.3),
+ },
+ "biarc_style_i": {
+ 'biarc0': marker_style('#880'),
+ 'biarc1': marker_style('#808'),
+ 'line': marker_style('#088'),
+ 'area': marker_style('#999', width=0.3),
+ },
+ "biarc_style_dark_i": {
+ 'biarc0': marker_style('#dd5'),
+ 'biarc1': marker_style('#d5d'),
+ 'line': marker_style('#5dd'),
+ 'area': marker_style('#aaa', width=0.3),
+ },
+ "biarc_style_lathe_feed": {
+ 'biarc0': marker_style('#07f', width=0.4),
+ 'biarc1': marker_style('#0f7', width=0.4),
+ 'line': marker_style('#f44', width=0.4),
+ 'area': marker_style('#aaa', width=0.3),
+ },
+ "biarc_style_lathe_passing feed": {
+ 'biarc0': marker_style('#07f', width=0.4),
+ 'biarc1': marker_style('#0f7', width=0.4),
+ 'line': marker_style('#f44', width=0.4),
+ 'area': marker_style('#aaa', width=0.3),
+ },
+ "biarc_style_lathe_fine feed": {
+ 'biarc0': marker_style('#7f0', width=0.4),
+ 'biarc1': marker_style('#f70', width=0.4),
+ 'line': marker_style('#744', width=0.4),
+ 'area': marker_style('#aaa', width=0.3),
+ },
+ "area artefact": Style(stroke='#ff0000', fill='#ffff00', stroke_width=1),
+ "area artefact arrow": Style(stroke='#ff0000', fill='#ffff00', stroke_width=1),
+ "dxf_points": Style(stroke="#ff0000", fill="#ff0000"),
+}
+
+
+################################################################################
+# Gcode additional functions
+################################################################################
+
+def gcode_comment_str(s, replace_new_line=False):
+ if replace_new_line:
+ s = re.sub(r"[\n\r]+", ".", s)
+ res = ""
+ if s[-1] == "\n":
+ s = s[:-1]
+ for a in s.split("\n"):
+ if a != "":
+ res += "(" + re.sub(r"[\(\)\\\n\r]", ".", a) + ")\n"
+ else:
+ res += "\n"
+ return res
+
+
+################################################################################
+# Cubic Super Path additional functions
+################################################################################
+
+
+def csp_from_polyline(line):
+ return [[[point[:] for _ in range(3)] for point in subline] for subline in line]
+
+
+def csp_remove_zero_segments(csp, tolerance=1e-7):
+ res = []
+ for subpath in csp:
+ if len(subpath) > 0:
+ res.append([subpath[0]])
+ for sp1, sp2 in zip(subpath, subpath[1:]):
+ if point_to_point_d2(sp1[1], sp2[1]) <= tolerance and point_to_point_d2(sp1[2], sp2[1]) <= tolerance and point_to_point_d2(sp1[1], sp2[0]) <= tolerance:
+ res[-1][-1][2] = sp2[2]
+ else:
+ res[-1].append(sp2)
+ return res
+
+
+def point_inside_csp(p, csp, on_the_path=True):
+ # we'll do the raytracing and see how many intersections are there on the ray's way.
+ # if number of intersections is even then point is outside.
+ # ray will be x=p.x and y=>p.y
+ # you can assign any value to on_the_path, by default if point is on the path
+ # function will return thai it's inside the path.
+ x, y = p
+ ray_intersections_count = 0
+ for subpath in csp:
+
+ for i in range(1, len(subpath)):
+ sp1 = subpath[i - 1]
+ sp2 = subpath[i]
+ ax, ay, bx, by, cx, cy, dx, dy = csp_parameterize(sp1, sp2)
+ if ax == 0 and bx == 0 and cx == 0 and dx == x:
+ # we've got a special case here
+ b = csp_true_bounds([[sp1, sp2]])
+ if b[1][1] <= y <= b[3][1]:
+ # points is on the path
+ return on_the_path
+ else:
+ # we can skip this segment because it won't influence the answer.
+ pass
+ else:
+ for t in csp_line_intersection([x, y], [x, y + 5], sp1, sp2):
+ if t == 0 or t == 1:
+ # we've got another special case here
+ x1, y1 = csp_at_t(sp1, sp2, t)
+ if y1 == y:
+ # the point is on the path
+ return on_the_path
+ # if t == 0 we should have considered this case previously.
+ if t == 1:
+ # we have to check the next segment if it is on the same side of the ray
+ st_d = csp_normalized_slope(sp1, sp2, 1)[0]
+ if st_d == 0:
+ st_d = csp_normalized_slope(sp1, sp2, 0.99)[0]
+
+ for j in range(1, len(subpath) + 1):
+ if (i + j) % len(subpath) == 0:
+ continue # skip the closing segment
+ sp11 = subpath[(i - 1 + j) % len(subpath)]
+ sp22 = subpath[(i + j) % len(subpath)]
+ ax1, ay1, bx1, by1, cx1, cy1, dx1, dy1 = csp_parameterize(sp1, sp2)
+ if ax1 == 0 and bx1 == 0 and cx1 == 0 and dx1 == x:
+ continue # this segment parallel to the ray, so skip it
+ en_d = csp_normalized_slope(sp11, sp22, 0)[0]
+ if en_d == 0:
+ en_d = csp_normalized_slope(sp11, sp22, 0.01)[0]
+ if st_d * en_d <= 0:
+ ray_intersections_count += 1
+ break
+ else:
+ x1, y1 = csp_at_t(sp1, sp2, t)
+ if y1 == y:
+ # the point is on the path
+ return on_the_path
+ else:
+ if y1 > y and 3 * ax * t ** 2 + 2 * bx * t + cx != 0: # if it's 0 the path only touches the ray
+ ray_intersections_count += 1
+ return ray_intersections_count % 2 == 1
+
+
+def csp_close_all_subpaths(csp, tolerance=0.000001):
+ for i in range(len(csp)):
+ if point_to_point_d2(csp[i][0][1], csp[i][-1][1]) > tolerance ** 2:
+ csp[i][-1][2] = csp[i][-1][1][:]
+ csp[i] += [[csp[i][0][1][:] for _ in range(3)]]
+ else:
+ if csp[i][0][1] != csp[i][-1][1]:
+ csp[i][-1][1] = csp[i][0][1][:]
+ return csp
+
+
+def csp_simple_bound(csp):
+ minx = None
+ miny = None
+ maxx = None
+ maxy = None
+
+ for subpath in csp:
+ for sp in subpath:
+ for p in sp:
+ minx = min(minx, p[0]) if minx is not None else p[0]
+ miny = min(miny, p[1]) if miny is not None else p[1]
+ maxx = max(maxx, p[0]) if maxx is not None else p[0]
+ maxy = max(maxy, p[1]) if maxy is not None else p[1]
+ return minx, miny, maxx, maxy
+
+
+def csp_segment_to_bez(sp1, sp2):
+ return sp1[1:] + sp2[:2]
+
+
+def csp_to_point_distance(csp, p, dist_bounds=(0, 1e100)):
+ min_dist = [1e100, 0, 0, 0]
+ for j in range(len(csp)):
+ for i in range(1, len(csp[j])):
+ d = csp_seg_to_point_distance(csp[j][i - 1], csp[j][i], p, sample_points=5)
+ if d[0] < dist_bounds[0]:
+ return [d[0], j, i, d[1]]
+ else:
+ if d[0] < min_dist[0]:
+ min_dist = [d[0], j, i, d[1]]
+ return min_dist
+
+
+def csp_seg_to_point_distance(sp1, sp2, p, sample_points=5):
+ ax, ay, bx, by, cx, cy, dx, dy = csp_parameterize(sp1, sp2)
+ dx = dx - p[0]
+ dy = dy - p[1]
+ if sample_points < 2:
+ sample_points = 2
+ d = min([(p[0] - sp1[1][0]) ** 2 + (p[1] - sp1[1][1]) ** 2, 0.], [(p[0] - sp2[1][0]) ** 2 + (p[1] - sp2[1][1]) ** 2, 1.])
+ for k in range(sample_points):
+ t = float(k) / (sample_points - 1)
+ i = 0
+ while i == 0 or abs(f) > 0.000001 and i < 20:
+ t2 = t ** 2
+ t3 = t ** 3
+ f = (ax * t3 + bx * t2 + cx * t + dx) * (3 * ax * t2 + 2 * bx * t + cx) + (ay * t3 + by * t2 + cy * t + dy) * (3 * ay * t2 + 2 * by * t + cy)
+ df = (6 * ax * t + 2 * bx) * (ax * t3 + bx * t2 + cx * t + dx) + (3 * ax * t2 + 2 * bx * t + cx) ** 2 + (6 * ay * t + 2 * by) * (ay * t3 + by * t2 + cy * t + dy) + (3 * ay * t2 + 2 * by * t + cy) ** 2
+ if df != 0:
+ t = t - f / df
+ else:
+ break
+ i += 1
+ if 0 <= t <= 1:
+ p1 = csp_at_t(sp1, sp2, t)
+ d1 = (p1[0] - p[0]) ** 2 + (p1[1] - p[1]) ** 2
+ if d1 < d[0]:
+ d = [d1, t]
+ return d
+
+
+def csp_seg_to_csp_seg_distance(sp1, sp2, sp3, sp4, dist_bounds=(0, 1e100), sample_points=5, tolerance=.01):
+ # check the ending points first
+ dist = csp_seg_to_point_distance(sp1, sp2, sp3[1], sample_points)
+ dist += [0.]
+ if dist[0] <= dist_bounds[0]:
+ return dist
+ d = csp_seg_to_point_distance(sp1, sp2, sp4[1], sample_points)
+ if d[0] < dist[0]:
+ dist = d + [1.]
+ if dist[0] <= dist_bounds[0]:
+ return dist
+ d = csp_seg_to_point_distance(sp3, sp4, sp1[1], sample_points)
+ if d[0] < dist[0]:
+ dist = [d[0], 0., d[1]]
+ if dist[0] <= dist_bounds[0]:
+ return dist
+ d = csp_seg_to_point_distance(sp3, sp4, sp2[1], sample_points)
+ if d[0] < dist[0]:
+ dist = [d[0], 1., d[1]]
+ if dist[0] <= dist_bounds[0]:
+ return dist
+ sample_points -= 2
+ if sample_points < 1:
+ sample_points = 1
+ ax1, ay1, bx1, by1, cx1, cy1, dx1, dy1 = csp_parameterize(sp1, sp2)
+ ax2, ay2, bx2, by2, cx2, cy2, dx2, dy2 = csp_parameterize(sp3, sp4)
+ # try to find closes points using Newtons method
+ for k in range(sample_points):
+ for j in range(sample_points):
+ t1 = float(k + 1) / (sample_points + 1)
+ t2 = float(j) / (sample_points + 1)
+
+ t12 = t1 * t1
+ t13 = t1 * t1 * t1
+ t22 = t2 * t2
+ t23 = t2 * t2 * t2
+ i = 0
+
+ F1 = [0, 0]
+ F2 = [[0, 0], [0, 0]]
+ F = 1e100
+ x = ax1 * t13 + bx1 * t12 + cx1 * t1 + dx1 - (ax2 * t23 + bx2 * t22 + cx2 * t2 + dx2)
+ y = ay1 * t13 + by1 * t12 + cy1 * t1 + dy1 - (ay2 * t23 + by2 * t22 + cy2 * t2 + dy2)
+ while i < 2 or abs(F - Flast) > tolerance and i < 30:
+ f1x = 3 * ax1 * t12 + 2 * bx1 * t1 + cx1
+ f1y = 3 * ay1 * t12 + 2 * by1 * t1 + cy1
+ f2x = 3 * ax2 * t22 + 2 * bx2 * t2 + cx2
+ f2y = 3 * ay2 * t22 + 2 * by2 * t2 + cy2
+ F1[0] = 2 * f1x * x + 2 * f1y * y
+ F1[1] = -2 * f2x * x - 2 * f2y * y
+ F2[0][0] = 2 * (6 * ax1 * t1 + 2 * bx1) * x + 2 * f1x * f1x + 2 * (6 * ay1 * t1 + 2 * by1) * y + 2 * f1y * f1y
+ F2[0][1] = -2 * f1x * f2x - 2 * f1y * f2y
+ F2[1][0] = -2 * f2x * f1x - 2 * f2y * f1y
+ F2[1][1] = -2 * (6 * ax2 * t2 + 2 * bx2) * x + 2 * f2x * f2x - 2 * (6 * ay2 * t2 + 2 * by2) * y + 2 * f2y * f2y
+ F2 = inv_2x2(F2)
+ if F2 is not None:
+ t1 -= (F2[0][0] * F1[0] + F2[0][1] * F1[1])
+ t2 -= (F2[1][0] * F1[0] + F2[1][1] * F1[1])
+ t12 = t1 * t1
+ t13 = t1 * t1 * t1
+ t22 = t2 * t2
+ t23 = t2 * t2 * t2
+ x = ax1 * t13 + bx1 * t12 + cx1 * t1 + dx1 - (ax2 * t23 + bx2 * t22 + cx2 * t2 + dx2)
+ y = ay1 * t13 + by1 * t12 + cy1 * t1 + dy1 - (ay2 * t23 + by2 * t22 + cy2 * t2 + dy2)
+ Flast = F
+ F = x * x + y * y
+ else:
+ break
+ i += 1
+ if F < dist[0] and 0 <= t1 <= 1 and 0 <= t2 <= 1:
+ dist = [F, t1, t2]
+ if dist[0] <= dist_bounds[0]:
+ return dist
+ return dist
+
+
+def csp_to_csp_distance(csp1, csp2, dist_bounds=(0, 1e100), tolerance=.01):
+ dist = [1e100, 0, 0, 0, 0, 0, 0]
+ for i1 in range(len(csp1)):
+ for j1 in range(1, len(csp1[i1])):
+ for i2 in range(len(csp2)):
+ for j2 in range(1, len(csp2[i2])):
+ d = csp_seg_bound_to_csp_seg_bound_max_min_distance(csp1[i1][j1 - 1], csp1[i1][j1], csp2[i2][j2 - 1], csp2[i2][j2])
+ if d[0] >= dist_bounds[1]:
+ continue
+ if d[1] < dist_bounds[0]:
+ return [d[1], i1, j1, 1, i2, j2, 1]
+ d = csp_seg_to_csp_seg_distance(csp1[i1][j1 - 1], csp1[i1][j1], csp2[i2][j2 - 1], csp2[i2][j2], dist_bounds, tolerance=tolerance)
+ if d[0] < dist[0]:
+ dist = [d[0], i1, j1, d[1], i2, j2, d[2]]
+ if dist[0] <= dist_bounds[0]:
+ return dist
+ if dist[0] >= dist_bounds[1]:
+ return dist
+ return dist
+
+
+def csp_split(sp1, sp2, t=.5):
+ [x1, y1] = sp1[1]
+ [x2, y2] = sp1[2]
+ [x3, y3] = sp2[0]
+ [x4, y4] = sp2[1]
+ x12 = x1 + (x2 - x1) * t
+ y12 = y1 + (y2 - y1) * t
+ x23 = x2 + (x3 - x2) * t
+ y23 = y2 + (y3 - y2) * t
+ x34 = x3 + (x4 - x3) * t
+ y34 = y3 + (y4 - y3) * t
+ x1223 = x12 + (x23 - x12) * t
+ y1223 = y12 + (y23 - y12) * t
+ x2334 = x23 + (x34 - x23) * t
+ y2334 = y23 + (y34 - y23) * t
+ x = x1223 + (x2334 - x1223) * t
+ y = y1223 + (y2334 - y1223) * t
+ return [sp1[0], sp1[1], [x12, y12]], [[x1223, y1223], [x, y], [x2334, y2334]], [[x34, y34], sp2[1], sp2[2]]
+
+
+def csp_true_bounds(csp):
+ # Finds minx,miny,maxx,maxy of the csp and return their (x,y,i,j,t)
+ minx = [float("inf"), 0, 0, 0]
+ maxx = [float("-inf"), 0, 0, 0]
+ miny = [float("inf"), 0, 0, 0]
+ maxy = [float("-inf"), 0, 0, 0]
+ for i in range(len(csp)):
+ for j in range(1, len(csp[i])):
+ ax, ay, bx, by, cx, cy, x0, y0 = bezierparameterize((csp[i][j - 1][1], csp[i][j - 1][2], csp[i][j][0], csp[i][j][1]))
+ roots = cubic_solver(0, 3 * ax, 2 * bx, cx) + [0, 1]
+ for root in roots:
+ if type(root) is complex and abs(root.imag) < 1e-10:
+ root = root.real
+ if type(root) is not complex and 0 <= root <= 1:
+ y = ay * (root ** 3) + by * (root ** 2) + cy * root + y0
+ x = ax * (root ** 3) + bx * (root ** 2) + cx * root + x0
+ maxx = max([x, y, i, j, root], maxx)
+ minx = min([x, y, i, j, root], minx)
+
+ roots = cubic_solver(0, 3 * ay, 2 * by, cy) + [0, 1]
+ for root in roots:
+ if type(root) is complex and root.imag == 0:
+ root = root.real
+ if type(root) is not complex and 0 <= root <= 1:
+ y = ay * (root ** 3) + by * (root ** 2) + cy * root + y0
+ x = ax * (root ** 3) + bx * (root ** 2) + cx * root + x0
+ maxy = max([y, x, i, j, root], maxy)
+ miny = min([y, x, i, j, root], miny)
+ maxy[0], maxy[1] = maxy[1], maxy[0]
+ miny[0], miny[1] = miny[1], miny[0]
+
+ return minx, miny, maxx, maxy
+
+
+############################################################################
+# csp_segments_intersection(sp1,sp2,sp3,sp4)
+#
+# Returns array containing all intersections between two segments of cubic
+# super path. Results are [ta,tb], or [ta0, ta1, tb0, tb1, "Overlap"]
+# where ta, tb are values of t for the intersection point.
+############################################################################
+def csp_segments_intersection(sp1, sp2, sp3, sp4):
+ a = csp_segment_to_bez(sp1, sp2)
+ b = csp_segment_to_bez(sp3, sp4)
+
+ def polish_intersection(a, b, ta, tb, tolerance=INTERSECTION_TOLERANCE):
+ ax, ay, bx, by, cx, cy, dx, dy = bezierparameterize(a)
+ ax1, ay1, bx1, by1, cx1, cy1, dx1, dy1 = bezierparameterize(b)
+ i = 0
+ F = [.0, .0]
+ F1 = [[.0, .0], [.0, .0]]
+ while i == 0 or (abs(F[0]) ** 2 + abs(F[1]) ** 2 > tolerance and i < 10):
+ ta3 = ta ** 3
+ ta2 = ta ** 2
+ tb3 = tb ** 3
+ tb2 = tb ** 2
+ F[0] = ax * ta3 + bx * ta2 + cx * ta + dx - ax1 * tb3 - bx1 * tb2 - cx1 * tb - dx1
+ F[1] = ay * ta3 + by * ta2 + cy * ta + dy - ay1 * tb3 - by1 * tb2 - cy1 * tb - dy1
+ F1[0][0] = 3 * ax * ta2 + 2 * bx * ta + cx
+ F1[0][1] = -3 * ax1 * tb2 - 2 * bx1 * tb - cx1
+ F1[1][0] = 3 * ay * ta2 + 2 * by * ta + cy
+ F1[1][1] = -3 * ay1 * tb2 - 2 * by1 * tb - cy1
+ det = F1[0][0] * F1[1][1] - F1[0][1] * F1[1][0]
+ if det != 0:
+ F1 = [[F1[1][1] / det, -F1[0][1] / det], [-F1[1][0] / det, F1[0][0] / det]]
+ ta = ta - (F1[0][0] * F[0] + F1[0][1] * F[1])
+ tb = tb - (F1[1][0] * F[0] + F1[1][1] * F[1])
+ else:
+ break
+ i += 1
+
+ return ta, tb
+
+ def recursion(a, b, ta0, ta1, tb0, tb1, depth_a, depth_b):
+ global bezier_intersection_recursive_result
+ if a == b:
+ bezier_intersection_recursive_result += [[ta0, tb0, ta1, tb1, "Overlap"]]
+ return
+ tam = (ta0 + ta1) / 2
+ tbm = (tb0 + tb1) / 2
+ if depth_a > 0 and depth_b > 0:
+ a1, a2 = bez_split(a, 0.5)
+ b1, b2 = bez_split(b, 0.5)
+ if bez_bounds_intersect(a1, b1):
+ recursion(a1, b1, ta0, tam, tb0, tbm, depth_a - 1, depth_b - 1)
+ if bez_bounds_intersect(a2, b1):
+ recursion(a2, b1, tam, ta1, tb0, tbm, depth_a - 1, depth_b - 1)
+ if bez_bounds_intersect(a1, b2):
+ recursion(a1, b2, ta0, tam, tbm, tb1, depth_a - 1, depth_b - 1)
+ if bez_bounds_intersect(a2, b2):
+ recursion(a2, b2, tam, ta1, tbm, tb1, depth_a - 1, depth_b - 1)
+ elif depth_a > 0:
+ a1, a2 = bez_split(a, 0.5)
+ if bez_bounds_intersect(a1, b):
+ recursion(a1, b, ta0, tam, tb0, tb1, depth_a - 1, depth_b)
+ if bez_bounds_intersect(a2, b):
+ recursion(a2, b, tam, ta1, tb0, tb1, depth_a - 1, depth_b)
+ elif depth_b > 0:
+ b1, b2 = bez_split(b, 0.5)
+ if bez_bounds_intersect(a, b1):
+ recursion(a, b1, ta0, ta1, tb0, tbm, depth_a, depth_b - 1)
+ if bez_bounds_intersect(a, b2):
+ recursion(a, b2, ta0, ta1, tbm, tb1, depth_a, depth_b - 1)
+ else: # Both segments have been subdivided enough. Let's get some intersections :).
+ intersection, t1, t2 = straight_segments_intersection([a[0]] + [a[3]], [b[0]] + [b[3]])
+ if intersection:
+ if intersection == "Overlap":
+ t1 = (max(0, min(1, t1[0])) + max(0, min(1, t1[1]))) / 2
+ t2 = (max(0, min(1, t2[0])) + max(0, min(1, t2[1]))) / 2
+ bezier_intersection_recursive_result += [[ta0 + t1 * (ta1 - ta0), tb0 + t2 * (tb1 - tb0)]]
+
+ global bezier_intersection_recursive_result
+ bezier_intersection_recursive_result = []
+ recursion(a, b, 0., 1., 0., 1., INTERSECTION_RECURSION_DEPTH, INTERSECTION_RECURSION_DEPTH)
+ intersections = bezier_intersection_recursive_result
+ for i in range(len(intersections)):
+ if len(intersections[i]) < 5 or intersections[i][4] != "Overlap":
+ intersections[i] = polish_intersection(a, b, intersections[i][0], intersections[i][1])
+ return intersections
+
+
+def csp_segments_true_intersection(sp1, sp2, sp3, sp4):
+ intersections = csp_segments_intersection(sp1, sp2, sp3, sp4)
+ res = []
+ for intersection in intersections:
+ if (
+ (len(intersection) == 5 and intersection[4] == "Overlap" and (0 <= intersection[0] <= 1 or 0 <= intersection[1] <= 1) and (0 <= intersection[2] <= 1 or 0 <= intersection[3] <= 1))
+ or (0 <= intersection[0] <= 1 and 0 <= intersection[1] <= 1)
+ ):
+ res += [intersection]
+ return res
+
+
+def csp_get_t_at_curvature(sp1, sp2, c, sample_points=16):
+ # returns a list containing [t1,t2,t3,...,tn], 0<=ti<=1...
+ if sample_points < 2:
+ sample_points = 2
+ tolerance = .0000000001
+ res = []
+ ax, ay, bx, by, cx, cy, dx, dy = csp_parameterize(sp1, sp2)
+ for k in range(sample_points):
+ t = float(k) / (sample_points - 1)
+ i = 0
+ F = 1e100
+ while i < 2 or abs(F) > tolerance and i < 17:
+ try: # some numerical calculation could exceed the limits
+ t2 = t * t
+ # slopes...
+ f1x = 3 * ax * t2 + 2 * bx * t + cx
+ f1y = 3 * ay * t2 + 2 * by * t + cy
+ f2x = 6 * ax * t + 2 * bx
+ f2y = 6 * ay * t + 2 * by
+ f3x = 6 * ax
+ f3y = 6 * ay
+ d = (f1x ** 2 + f1y ** 2) ** 1.5
+ F1 = (
+ ((f1x * f3y - f3x * f1y) * d - (f1x * f2y - f2x * f1y) * 3. * (f2x * f1x + f2y * f1y) * ((f1x ** 2 + f1y ** 2) ** .5)) /
+ ((f1x ** 2 + f1y ** 2) ** 3)
+ )
+ F = (f1x * f2y - f1y * f2x) / d - c
+ t -= F / F1
+ except:
+ break
+ i += 1
+ if 0 <= t <= 1 and F <= tolerance:
+ if len(res) == 0:
+ res.append(t)
+ for i in res:
+ if abs(t - i) <= 0.001:
+ break
+ if not abs(t - i) <= 0.001:
+ res.append(t)
+ return res
+
+
+def csp_max_curvature(sp1, sp2):
+ ax, ay, bx, by, cx, cy, dx, dy = csp_parameterize(sp1, sp2)
+ tolerance = .0001
+ F = 0.
+ i = 0
+ while i < 2 or F - Flast < tolerance and i < 10:
+ t = .5
+ f1x = 3 * ax * t ** 2 + 2 * bx * t + cx
+ f1y = 3 * ay * t ** 2 + 2 * by * t + cy
+ f2x = 6 * ax * t + 2 * bx
+ f2y = 6 * ay * t + 2 * by
+ f3x = 6 * ax
+ f3y = 6 * ay
+ d = pow(f1x ** 2 + f1y ** 2, 1.5)
+ if d != 0:
+ Flast = F
+ F = (f1x * f2y - f1y * f2x) / d
+ F1 = (
+ (d * (f1x * f3y - f3x * f1y) - (f1x * f2y - f2x * f1y) * 3. * (f2x * f1x + f2y * f1y) * pow(f1x ** 2 + f1y ** 2, .5)) /
+ (f1x ** 2 + f1y ** 2) ** 3
+ )
+ i += 1
+ if F1 != 0:
+ t -= F / F1
+ else:
+ break
+ else:
+ break
+ return t
+
+
+def csp_curvature_at_t(sp1, sp2, t, depth=3):
+ ax, ay, bx, by, cx, cy, dx, dy = bezierparameterize(csp_segment_to_bez(sp1, sp2))
+
+ # curvature = (x'y''-y'x'') / (x'^2+y'^2)^1.5
+
+ f1x = 3 * ax * t ** 2 + 2 * bx * t + cx
+ f1y = 3 * ay * t ** 2 + 2 * by * t + cy
+ f2x = 6 * ax * t + 2 * bx
+ f2y = 6 * ay * t + 2 * by
+ d = (f1x ** 2 + f1y ** 2) ** 1.5
+ if d != 0:
+ return (f1x * f2y - f1y * f2x) / d
+ else:
+ t1 = f1x * f2y - f1y * f2x
+ if t1 > 0:
+ return 1e100
+ if t1 < 0:
+ return -1e100
+ # Use the Lapitals rule to solve 0/0 problem for 2 times...
+ t1 = 2 * (bx * ay - ax * by) * t + (ay * cx - ax * cy)
+ if t1 > 0:
+ return 1e100
+ if t1 < 0:
+ return -1e100
+ t1 = bx * ay - ax * by
+ if t1 > 0:
+ return 1e100
+ if t1 < 0:
+ return -1e100
+ if depth > 0:
+ # little hack ;^) hope it won't influence anything...
+ return csp_curvature_at_t(sp1, sp2, t * 1.004, depth - 1)
+ return 1e100
+
+
+def csp_subpath_ccw(subpath):
+ # Remove all zero length segments
+ s = 0
+ if (P(subpath[-1][1]) - P(subpath[0][1])).l2() > 1e-10:
+ subpath[-1][2] = subpath[-1][1]
+ subpath[0][0] = subpath[0][1]
+ subpath += [[subpath[0][1], subpath[0][1], subpath[0][1]]]
+ pl = subpath[-1][2]
+ for sp1 in subpath:
+ for p in sp1:
+ s += (p[0] - pl[0]) * (p[1] + pl[1])
+ pl = p
+ return s < 0
+
+
+def csp_at_t(sp1, sp2, t):
+ ax = sp1[1][0]
+ bx = sp1[2][0]
+ cx = sp2[0][0]
+ dx = sp2[1][0]
+
+ ay = sp1[1][1]
+ by = sp1[2][1]
+ cy = sp2[0][1]
+ dy = sp2[1][1]
+
+ x1 = ax + (bx - ax) * t
+ y1 = ay + (by - ay) * t
+
+ x2 = bx + (cx - bx) * t
+ y2 = by + (cy - by) * t
+
+ x3 = cx + (dx - cx) * t
+ y3 = cy + (dy - cy) * t
+
+ x4 = x1 + (x2 - x1) * t
+ y4 = y1 + (y2 - y1) * t
+
+ x5 = x2 + (x3 - x2) * t
+ y5 = y2 + (y3 - y2) * t
+
+ x = x4 + (x5 - x4) * t
+ y = y4 + (y5 - y4) * t
+
+ return [x, y]
+
+
+def csp_at_length(sp1, sp2, l=0.5, tolerance=0.01):
+ bez = (sp1[1][:], sp1[2][:], sp2[0][:], sp2[1][:])
+ t = beziertatlength(bez, l, tolerance)
+ return csp_at_t(sp1, sp2, t)
+
+
+def cspseglength(sp1, sp2, tolerance=0.01):
+ bez = (sp1[1][:], sp1[2][:], sp2[0][:], sp2[1][:])
+ return bezierlength(bez, tolerance)
+
+
+def csp_line_intersection(l1, l2, sp1, sp2):
+ dd = l1[0]
+ cc = l2[0] - l1[0]
+ bb = l1[1]
+ aa = l2[1] - l1[1]
+ if aa == cc == 0:
+ return []
+ if aa:
+ coef1 = cc / aa
+ coef2 = 1
+ else:
+ coef1 = 1
+ coef2 = aa / cc
+ bez = (sp1[1][:], sp1[2][:], sp2[0][:], sp2[1][:])
+ ax, ay, bx, by, cx, cy, x0, y0 = bezierparameterize(bez)
+ a = coef1 * ay - coef2 * ax
+ b = coef1 * by - coef2 * bx
+ c = coef1 * cy - coef2 * cx
+ d = coef1 * (y0 - bb) - coef2 * (x0 - dd)
+ roots = cubic_solver(a, b, c, d)
+ retval = []
+ for i in roots:
+ if type(i) is complex and abs(i.imag) < 1e-7:
+ i = i.real
+ if type(i) is not complex and -1e-10 <= i <= 1. + 1e-10:
+ retval.append(i)
+ return retval
+
+
+def csp_split_by_two_points(sp1, sp2, t1, t2):
+ if t1 > t2:
+ t1, t2 = t2, t1
+ if t1 == t2:
+ sp1, sp2, sp3 = csp_split(sp1, sp2, t1)
+ return [sp1, sp2, sp2, sp3]
+ elif t1 <= 1e-10 and t2 >= 1. - 1e-10:
+ return [sp1, sp1, sp2, sp2]
+ elif t1 <= 1e-10:
+ sp1, sp2, sp3 = csp_split(sp1, sp2, t2)
+ return [sp1, sp1, sp2, sp3]
+ elif t2 >= 1. - 1e-10:
+ sp1, sp2, sp3 = csp_split(sp1, sp2, t1)
+ return [sp1, sp2, sp3, sp3]
+ else:
+ sp1, sp2, sp3 = csp_split(sp1, sp2, t1)
+ sp2, sp3, sp4 = csp_split(sp2, sp3, (t2 - t1) / (1 - t1))
+ return [sp1, sp2, sp3, sp4]
+
+
+def csp_seg_split(sp1, sp2, points):
+ # points is float=t or list [t1, t2, ..., tn]
+ if type(points) is float:
+ points = [points]
+ points.sort()
+ res = [sp1, sp2]
+ last_t = 0
+ for t in points:
+ if 1e-10 < t < 1. - 1e-10:
+ sp3, sp4, sp5 = csp_split(res[-2], res[-1], (t - last_t) / (1 - last_t))
+ last_t = t
+ res[-2:] = [sp3, sp4, sp5]
+ return res
+
+
+def csp_subpath_split_by_points(subpath, points):
+ # points are [[i,t]...] where i-segment's number
+ points.sort()
+ points = [[1, 0.]] + points + [[len(subpath) - 1, 1.]]
+ parts = []
+ for int1, int2 in zip(points, points[1:]):
+ if int1 == int2:
+ continue
+ if int1[1] == 1.:
+ int1[0] += 1
+ int1[1] = 0.
+ if int1 == int2:
+ continue
+ if int2[1] == 0.:
+ int2[0] -= 1
+ int2[1] = 1.
+ if int1[0] == 0 and int2[0] == len(subpath) - 1: # and small(int1[1]) and small(int2[1]-1) :
+ continue
+ if int1[0] == int2[0]: # same segment
+ sp = csp_split_by_two_points(subpath[int1[0] - 1], subpath[int1[0]], int1[1], int2[1])
+ if sp[1] != sp[2]:
+ parts += [[sp[1], sp[2]]]
+ else:
+ sp5, sp1, sp2 = csp_split(subpath[int1[0] - 1], subpath[int1[0]], int1[1])
+ sp3, sp4, sp5 = csp_split(subpath[int2[0] - 1], subpath[int2[0]], int2[1])
+ if int1[0] == int2[0] - 1:
+ parts += [[sp1, [sp2[0], sp2[1], sp3[2]], sp4]]
+ else:
+ parts += [[sp1, sp2] + subpath[int1[0] + 1:int2[0] - 1] + [sp3, sp4]]
+ return parts
+
+
+def arc_from_s_r_n_l(s, r, n, l):
+ if abs(n[0] ** 2 + n[1] ** 2 - 1) > 1e-10:
+ n = normalize(n)
+ return arc_from_c_s_l([s[0] + n[0] * r, s[1] + n[1] * r], s, l)
+
+
+def arc_from_c_s_l(c, s, l):
+ r = point_to_point_d(c, s)
+ if r == 0:
+ return []
+ alpha = l / r
+ cos_ = math.cos(alpha)
+ sin_ = math.sin(alpha)
+ e = [c[0] + (s[0] - c[0]) * cos_ - (s[1] - c[1]) * sin_, c[1] + (s[0] - c[0]) * sin_ + (s[1] - c[1]) * cos_]
+ n = [c[0] - s[0], c[1] - s[1]]
+ slope = rotate_cw(n) if l > 0 else rotate_ccw(n)
+ return csp_from_arc(s, e, c, r, slope)
+
+
+def csp_from_arc(start, end, center, r, slope_st):
+ # Creates csp that approximise specified arc
+ r = abs(r)
+ alpha = (atan2(end[0] - center[0], end[1] - center[1]) - atan2(start[0] - center[0], start[1] - center[1])) % TAU
+
+ sectors = int(abs(alpha) * 2 / math.pi) + 1
+ alpha_start = atan2(start[0] - center[0], start[1] - center[1])
+ cos_ = math.cos(alpha_start)
+ sin_ = math.sin(alpha_start)
+ k = (4. * math.tan(alpha / sectors / 4.) / 3.)
+ if dot(slope_st, [- sin_ * k * r, cos_ * k * r]) < 0:
+ if alpha > 0:
+ alpha -= TAU
+ else:
+ alpha += TAU
+ if abs(alpha * r) < 0.001:
+ return []
+
+ sectors = int(abs(alpha) * 2 / math.pi) + 1
+ k = (4. * math.tan(alpha / sectors / 4.) / 3.)
+ result = []
+ for i in range(sectors + 1):
+ cos_ = math.cos(alpha_start + alpha * i / sectors)
+ sin_ = math.sin(alpha_start + alpha * i / sectors)
+ sp = [[], [center[0] + cos_ * r, center[1] + sin_ * r], []]
+ sp[0] = [sp[1][0] + sin_ * k * r, sp[1][1] - cos_ * k * r]
+ sp[2] = [sp[1][0] - sin_ * k * r, sp[1][1] + cos_ * k * r]
+ result += [sp]
+ result[0][0] = result[0][1][:]
+ result[-1][2] = result[-1][1]
+
+ return result
+
+
+def point_to_arc_distance(p, arc):
+ # Distance calculattion from point to arc
+ P0, P2, c, a = arc
+ p = P(p)
+ r = (P0 - c).mag()
+ if r > 0:
+ i = c + (p - c).unit() * r
+ alpha = ((i - c).angle() - (P0 - c).angle())
+ if a * alpha < 0:
+ if alpha > 0:
+ alpha = alpha - TAU
+ else:
+ alpha = TAU + alpha
+ if between(alpha, 0, a) or min(abs(alpha), abs(alpha - a)) < STRAIGHT_TOLERANCE:
+ return (p - i).mag(), [i.x, i.y]
+ else:
+ d1 = (p - P0).mag()
+ d2 = (p - P2).mag()
+ if d1 < d2:
+ return d1, [P0.x, P0.y]
+ else:
+ return d2, [P2.x, P2.y]
+
+
+def csp_to_arc_distance(sp1, sp2, arc1, arc2, tolerance=0.01): # arc = [start,end,center,alpha]
+ n = 10
+ i = 0
+ d = (0, [0, 0])
+ d1 = (0, [0, 0])
+ dl = 0
+ while i < 1 or (abs(d1[0] - dl[0]) > tolerance and i < 4):
+ i += 1
+ dl = d1 * 1
+ for j in range(n + 1):
+ t = float(j) / n
+ p = csp_at_t(sp1, sp2, t)
+ d = min(point_to_arc_distance(p, arc1), point_to_arc_distance(p, arc2))
+ d1 = max(d1, d)
+ n = n * 2
+ return d1[0]
+
+
+def csp_point_inside_bound(sp1, sp2, p):
+ bez = [sp1[1], sp1[2], sp2[0], sp2[1]]
+ x, y = p
+ c = 0
+ # CLT added test of x in range
+ xmin = 1e100
+ xmax = -1e100
+ for i in range(4):
+ [x0, y0] = bez[i - 1]
+ [x1, y1] = bez[i]
+ xmin = min(xmin, x0)
+ xmax = max(xmax, x0)
+ if x0 - x1 != 0 and (y - y0) * (x1 - x0) >= (x - x0) * (y1 - y0) and x > min(x0, x1) and x <= max(x0, x1):
+ c += 1
+ return xmin <= x <= xmax and c % 2 == 0
+
+
+def line_line_intersect(p1, p2, p3, p4): # Return only true intersection.
+ if (p1[0] == p2[0] and p1[1] == p2[1]) or (p3[0] == p4[0] and p3[1] == p4[1]):
+ return False
+ x = (p2[0] - p1[0]) * (p4[1] - p3[1]) - (p2[1] - p1[1]) * (p4[0] - p3[0])
+ if x == 0: # Lines are parallel
+ if (p3[0] - p1[0]) * (p2[1] - p1[1]) == (p3[1] - p1[1]) * (p2[0] - p1[0]):
+ if p3[0] != p4[0]:
+ t11 = (p1[0] - p3[0]) / (p4[0] - p3[0])
+ t12 = (p2[0] - p3[0]) / (p4[0] - p3[0])
+ t21 = (p3[0] - p1[0]) / (p2[0] - p1[0])
+ t22 = (p4[0] - p1[0]) / (p2[0] - p1[0])
+ else:
+ t11 = (p1[1] - p3[1]) / (p4[1] - p3[1])
+ t12 = (p2[1] - p3[1]) / (p4[1] - p3[1])
+ t21 = (p3[1] - p1[1]) / (p2[1] - p1[1])
+ t22 = (p4[1] - p1[1]) / (p2[1] - p1[1])
+ return "Overlap" if (0 <= t11 <= 1 or 0 <= t12 <= 1) and (0 <= t21 <= 1 or 0 <= t22 <= 1) else False
+ else:
+ return False
+ else:
+ return (
+ 0 <= ((p4[0] - p3[0]) * (p1[1] - p3[1]) - (p4[1] - p3[1]) * (p1[0] - p3[0])) / x <= 1 and
+ 0 <= ((p2[0] - p1[0]) * (p1[1] - p3[1]) - (p2[1] - p1[1]) * (p1[0] - p3[0])) / x <= 1)
+
+
+def line_line_intersection_points(p1, p2, p3, p4): # Return only points [ (x,y) ]
+ if (p1[0] == p2[0] and p1[1] == p2[1]) or (p3[0] == p4[0] and p3[1] == p4[1]):
+ return []
+ x = (p2[0] - p1[0]) * (p4[1] - p3[1]) - (p2[1] - p1[1]) * (p4[0] - p3[0])
+ if x == 0: # Lines are parallel
+ if (p3[0] - p1[0]) * (p2[1] - p1[1]) == (p3[1] - p1[1]) * (p2[0] - p1[0]):
+ if p3[0] != p4[0]:
+ t11 = (p1[0] - p3[0]) / (p4[0] - p3[0])
+ t12 = (p2[0] - p3[0]) / (p4[0] - p3[0])
+ t21 = (p3[0] - p1[0]) / (p2[0] - p1[0])
+ t22 = (p4[0] - p1[0]) / (p2[0] - p1[0])
+ else:
+ t11 = (p1[1] - p3[1]) / (p4[1] - p3[1])
+ t12 = (p2[1] - p3[1]) / (p4[1] - p3[1])
+ t21 = (p3[1] - p1[1]) / (p2[1] - p1[1])
+ t22 = (p4[1] - p1[1]) / (p2[1] - p1[1])
+ res = []
+ if (0 <= t11 <= 1 or 0 <= t12 <= 1) and (0 <= t21 <= 1 or 0 <= t22 <= 1):
+ if 0 <= t11 <= 1:
+ res += [p1]
+ if 0 <= t12 <= 1:
+ res += [p2]
+ if 0 <= t21 <= 1:
+ res += [p3]
+ if 0 <= t22 <= 1:
+ res += [p4]
+ return res
+ else:
+ return []
+ else:
+ t1 = ((p4[0] - p3[0]) * (p1[1] - p3[1]) - (p4[1] - p3[1]) * (p1[0] - p3[0])) / x
+ t2 = ((p2[0] - p1[0]) * (p1[1] - p3[1]) - (p2[1] - p1[1]) * (p1[0] - p3[0])) / x
+ if 0 <= t1 <= 1 and 0 <= t2 <= 1:
+ return [[p1[0] * (1 - t1) + p2[0] * t1, p1[1] * (1 - t1) + p2[1] * t1]]
+ else:
+ return []
+
+
+def point_to_point_d2(a, b):
+ return (a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2
+
+
+def point_to_point_d(a, b):
+ return math.sqrt((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2)
+
+
+def point_to_line_segment_distance_2(p1, p2, p3):
+ # p1 - point, p2,p3 - line segment
+ # draw_pointer(p1)
+ w0 = [p1[0] - p2[0], p1[1] - p2[1]]
+ v = [p3[0] - p2[0], p3[1] - p2[1]]
+ c1 = w0[0] * v[0] + w0[1] * v[1]
+ if c1 <= 0:
+ return w0[0] * w0[0] + w0[1] * w0[1]
+ c2 = v[0] * v[0] + v[1] * v[1]
+ if c2 <= c1:
+ return (p1[0] - p3[0]) ** 2 + (p1[1] - p3[1]) ** 2
+ return (p1[0] - p2[0] - v[0] * c1 / c2) ** 2 + (p1[1] - p2[1] - v[1] * c1 / c2)
+
+
+def line_to_line_distance_2(p1, p2, p3, p4):
+ if line_line_intersect(p1, p2, p3, p4):
+ return 0
+ return min(
+ point_to_line_segment_distance_2(p1, p3, p4),
+ point_to_line_segment_distance_2(p2, p3, p4),
+ point_to_line_segment_distance_2(p3, p1, p2),
+ point_to_line_segment_distance_2(p4, p1, p2))
+
+
+def csp_seg_bound_to_csp_seg_bound_max_min_distance(sp1, sp2, sp3, sp4):
+ bez1 = csp_segment_to_bez(sp1, sp2)
+ bez2 = csp_segment_to_bez(sp3, sp4)
+ min_dist = 1e100
+ max_dist = 0.
+ for i in range(4):
+ if csp_point_inside_bound(sp1, sp2, bez2[i]) or csp_point_inside_bound(sp3, sp4, bez1[i]):
+ min_dist = 0.
+ break
+ for i in range(4):
+ for j in range(4):
+ d = line_to_line_distance_2(bez1[i - 1], bez1[i], bez2[j - 1], bez2[j])
+ if d < min_dist:
+ min_dist = d
+ d = (bez2[j][0] - bez1[i][0]) ** 2 + (bez2[j][1] - bez1[i][1]) ** 2
+ if max_dist < d:
+ max_dist = d
+ return min_dist, max_dist
+
+
+def csp_reverse(csp):
+ for i in range(len(csp)):
+ n = []
+ for j in csp[i]:
+ n = [[j[2][:], j[1][:], j[0][:]]] + n
+ csp[i] = n[:]
+ return csp
+
+
+def csp_normalized_slope(sp1, sp2, t):
+ ax, ay, bx, by, cx, cy, dx, dy = bezierparameterize((sp1[1][:], sp1[2][:], sp2[0][:], sp2[1][:]))
+ if sp1[1] == sp2[1] == sp1[2] == sp2[0]:
+ return [1., 0.]
+ f1x = 3 * ax * t * t + 2 * bx * t + cx
+ f1y = 3 * ay * t * t + 2 * by * t + cy
+ if abs(f1x * f1x + f1y * f1y) > 1e-9: # LT changed this from 1e-20, which caused problems
+ l = math.sqrt(f1x * f1x + f1y * f1y)
+ return [f1x / l, f1y / l]
+
+ if t == 0:
+ f1x = sp2[0][0] - sp1[1][0]
+ f1y = sp2[0][1] - sp1[1][1]
+ if abs(f1x * f1x + f1y * f1y) > 1e-9: # LT changed this from 1e-20, which caused problems
+ l = math.sqrt(f1x * f1x + f1y * f1y)
+ return [f1x / l, f1y / l]
+ else:
+ f1x = sp2[1][0] - sp1[1][0]
+ f1y = sp2[1][1] - sp1[1][1]
+ if f1x * f1x + f1y * f1y != 0:
+ l = math.sqrt(f1x * f1x + f1y * f1y)
+ return [f1x / l, f1y / l]
+ elif t == 1:
+ f1x = sp2[1][0] - sp1[2][0]
+ f1y = sp2[1][1] - sp1[2][1]
+ if abs(f1x * f1x + f1y * f1y) > 1e-9:
+ l = math.sqrt(f1x * f1x + f1y * f1y)
+ return [f1x / l, f1y / l]
+ else:
+ f1x = sp2[1][0] - sp1[1][0]
+ f1y = sp2[1][1] - sp1[1][1]
+ if f1x * f1x + f1y * f1y != 0:
+ l = math.sqrt(f1x * f1x + f1y * f1y)
+ return [f1x / l, f1y / l]
+ else:
+ return [1., 0.]
+
+
+def csp_normalized_normal(sp1, sp2, t):
+ nx, ny = csp_normalized_slope(sp1, sp2, t)
+ return [-ny, nx]
+
+
+def csp_parameterize(sp1, sp2):
+ return bezierparameterize(csp_segment_to_bez(sp1, sp2))
+
+
+def csp_concat_subpaths(*s):
+ def concat(s1, s2):
+ if not s1:
+ return s2
+ if not s2:
+ return s1
+ if (s1[-1][1][0] - s2[0][1][0]) ** 2 + (s1[-1][1][1] - s2[0][1][1]) ** 2 > 0.00001:
+ return s1[:-1] + [[s1[-1][0], s1[-1][1], s1[-1][1]], [s2[0][1], s2[0][1], s2[0][2]]] + s2[1:]
+ else:
+ return s1[:-1] + [[s1[-1][0], s2[0][1], s2[0][2]]] + s2[1:]
+
+ if len(s) == 0:
+ return []
+ if len(s) == 1:
+ return s[0]
+ result = s[0]
+ for s1 in s[1:]:
+ result = concat(result, s1)
+ return result
+
+
+def csp_subpaths_end_to_start_distance2(s1, s2):
+ return (s1[-1][1][0] - s2[0][1][0]) ** 2 + (s1[-1][1][1] - s2[0][1][1]) ** 2
+
+
+def csp_clip_by_line(csp, l1, l2):
+ result = []
+ for i in range(len(csp)):
+ s = csp[i]
+ intersections = []
+ for j in range(1, len(s)):
+ intersections += [[j, int_] for int_ in csp_line_intersection(l1, l2, s[j - 1], s[j])]
+ splitted_s = csp_subpath_split_by_points(s, intersections)
+ for s in splitted_s[:]:
+ clip = False
+ for p in csp_true_bounds([s]):
+ if (l1[1] - l2[1]) * p[0] + (l2[0] - l1[0]) * p[1] + (l1[0] * l2[1] - l2[0] * l1[1]) < -0.01:
+ clip = True
+ break
+ if clip:
+ splitted_s.remove(s)
+ result += splitted_s
+ return result
+
+
+def csp_subpath_line_to(subpath, points, prepend=False):
+ # Appends subpath with line or polyline.
+ if len(points) > 0:
+ if not prepend:
+ if len(subpath) > 0:
+ subpath[-1][2] = subpath[-1][1][:]
+ if type(points[0]) == type([1, 1]):
+ for p in points:
+ subpath += [[p[:], p[:], p[:]]]
+ else:
+ subpath += [[points, points, points]]
+ else:
+ if len(subpath) > 0:
+ subpath[0][0] = subpath[0][1][:]
+ if type(points[0]) == type([1, 1]):
+ for p in points:
+ subpath = [[p[:], p[:], p[:]]] + subpath
+ else:
+ subpath = [[points, points, points]] + subpath
+ return subpath
+
+
+def csp_join_subpaths(csp):
+ result = csp[:]
+ done_smf = True
+ joined_result = []
+ while done_smf:
+ done_smf = False
+ while len(result) > 0:
+ s1 = result[-1][:]
+ del (result[-1])
+ j = 0
+ joined_smf = False
+ while j < len(joined_result):
+ if csp_subpaths_end_to_start_distance2(joined_result[j], s1) < 0.000001:
+ joined_result[j] = csp_concat_subpaths(joined_result[j], s1)
+ done_smf = True
+ joined_smf = True
+ break
+ if csp_subpaths_end_to_start_distance2(s1, joined_result[j]) < 0.000001:
+ joined_result[j] = csp_concat_subpaths(s1, joined_result[j])
+ done_smf = True
+ joined_smf = True
+ break
+ j += 1
+ if not joined_smf:
+ joined_result += [s1[:]]
+ if done_smf:
+ result = joined_result[:]
+ joined_result = []
+ return joined_result
+
+
+def triangle_cross(a, b, c):
+ return (a[0] - b[0]) * (c[1] - b[1]) - (c[0] - b[0]) * (a[1] - b[1])
+
+
+def csp_segment_convex_hull(sp1, sp2):
+ a = sp1[1][:]
+ b = sp1[2][:]
+ c = sp2[0][:]
+ d = sp2[1][:]
+
+ abc = triangle_cross(a, b, c)
+ abd = triangle_cross(a, b, d)
+ bcd = triangle_cross(b, c, d)
+ cad = triangle_cross(c, a, d)
+ if abc == 0 and abd == 0:
+ return [min(a, b, c, d), max(a, b, c, d)]
+ if abc == 0:
+ return [d, min(a, b, c), max(a, b, c)]
+ if abd == 0:
+ return [c, min(a, b, d), max(a, b, d)]
+ if bcd == 0:
+ return [a, min(b, c, d), max(b, c, d)]
+ if cad == 0:
+ return [b, min(c, a, d), max(c, a, d)]
+
+ m1 = abc * abd > 0
+ m2 = abc * bcd > 0
+ m3 = abc * cad > 0
+
+ if m1 and m2 and m3:
+ return [a, b, c]
+ if m1 and m2 and not m3:
+ return [a, b, c, d]
+ if m1 and not m2 and m3:
+ return [a, b, d, c]
+ if not m1 and m2 and m3:
+ return [a, d, b, c]
+ if m1 and not (m2 and m3):
+ return [a, b, d]
+ if not (m1 and m2) and m3:
+ return [c, a, d]
+ if not (m1 and m3) and m2:
+ return [b, c, d]
+
+ raise ValueError("csp_segment_convex_hull happened which is something that shouldn't happen!")
+
+
+################################################################################
+# Bezier additional functions
+################################################################################
+
+def bez_bounds_intersect(bez1, bez2):
+ return bounds_intersect(bez_bound(bez2), bez_bound(bez1))
+
+
+def bez_bound(bez):
+ return [
+ min(bez[0][0], bez[1][0], bez[2][0], bez[3][0]),
+ min(bez[0][1], bez[1][1], bez[2][1], bez[3][1]),
+ max(bez[0][0], bez[1][0], bez[2][0], bez[3][0]),
+ max(bez[0][1], bez[1][1], bez[2][1], bez[3][1]),
+ ]
+
+
+def bounds_intersect(a, b):
+ return not ((a[0] > b[2]) or (b[0] > a[2]) or (a[1] > b[3]) or (b[1] > a[3]))
+
+
+def tpoint(xy1, xy2, t):
+ (x1, y1) = xy1
+ (x2, y2) = xy2
+ return [x1 + t * (x2 - x1), y1 + t * (y2 - y1)]
+
+
+def bez_split(a, t=0.5):
+ a1 = tpoint(a[0], a[1], t)
+ at = tpoint(a[1], a[2], t)
+ b2 = tpoint(a[2], a[3], t)
+ a2 = tpoint(a1, at, t)
+ b1 = tpoint(b2, at, t)
+ a3 = tpoint(a2, b1, t)
+ return [a[0], a1, a2, a3], [a3, b1, b2, a[3]]
+
+
+################################################################################
+# Some vector functions
+################################################################################
+
+def normalize(xy):
+ (x, y) = xy
+ l = math.sqrt(x ** 2 + y ** 2)
+ if l == 0:
+ return [0., 0.]
+ else:
+ return [x / l, y / l]
+
+
+def cross(a, b):
+ return a[1] * b[0] - a[0] * b[1]
+
+
+def dot(a, b):
+ return a[0] * b[0] + a[1] * b[1]
+
+
+def rotate_ccw(d):
+ return [-d[1], d[0]]
+
+
+def rotate_cw(d):
+ return [d[1], -d[0]]
+
+
+def vectors_ccw(a, b):
+ return a[0] * b[1] - b[0] * a[1] < 0
+
+
+################################################################################
+# Common functions
+################################################################################
+
+def inv_2x2(a): # invert matrix 2x2
+ det = a[0][0] * a[1][1] - a[1][0] * a[0][1]
+ if det == 0:
+ return None
+ return [
+ [a[1][1] / det, -a[0][1] / det],
+ [-a[1][0] / det, a[0][0] / det]
+ ]
+
+
+def small(a):
+ global small_tolerance
+ return abs(a) < small_tolerance
+
+
+def atan2(*arg):
+ if len(arg) == 1 and (type(arg[0]) == type([0., 0.]) or type(arg[0]) == type((0., 0.))):
+ return (math.pi / 2 - math.atan2(arg[0][0], arg[0][1])) % TAU
+ elif len(arg) == 2:
+ return (math.pi / 2 - math.atan2(arg[0], arg[1])) % TAU
+ else:
+ raise ValueError("Bad argumets for atan! ({})".format(*arg))
+
+
+def draw_text(text, x, y, group=None, style=None, font_size=10, gcodetools_tag=None):
+ if style is None:
+ style = "font-family:DejaVu Sans;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:DejaVu Sans;fill:#000000;fill-opacity:1;stroke:none;"
+ style += "font-size:{:f}px;".format(font_size)
+ attributes = {'x': str(x), 'y': str(y), 'style': style}
+ if gcodetools_tag is not None:
+ attributes["gcodetools"] = str(gcodetools_tag)
+
+ if group is None:
+ group = options.doc_root
+
+ text_elem = group.add(TextElement(**attributes))
+ text_elem.set("xml:space", "preserve")
+ text = str(text).split("\n")
+ for string in text:
+ span = text_elem.add(Tspan(x=str(x), y=str(y)))
+ span.set('sodipodi:role', 'line')
+ y += font_size
+ span.text = str(string)
+
+
+def draw_csp(csp, stroke="#f00", fill="none", comment="", width=0.354, group=None, style=None):
+ if group is None:
+ group = options.doc_root
+ node = group.add(PathElement())
+
+ node.style = style if style is not None else \
+ {'fill': fill, 'fill-opacity': 1, 'stroke': stroke, 'stroke-width': width}
+
+ node.path = CubicSuperPath(csp)
+
+ if comment != '':
+ node.set('comment', comment)
+
+ return node
+
+
+def draw_pointer(x, color="#f00", figure="cross", group=None, comment="", fill=None, width=.1, size=10., text=None, font_size=None, pointer_type=None, attrib=None):
+ size = size / 2
+ if attrib is None:
+ attrib = {}
+ if pointer_type is None:
+ pointer_type = "Pointer"
+ attrib["gcodetools"] = pointer_type
+ if group is None:
+ group = options.self.svg.get_current_layer()
+ if text is not None:
+ if font_size is None:
+ font_size = 7
+ group = group.add(Group(gcodetools=pointer_type + " group"))
+ draw_text(text, x[0] + size * 2.2, x[1] - size, group=group, font_size=font_size)
+ if figure == "line":
+ s = ""
+ for i in range(1, len(x) / 2):
+ s += " {}, {} ".format(x[i * 2], x[i * 2 + 1])
+ attrib.update({"d": "M {},{} L {}".format(x[0], x[1], s), "style": "fill:none;stroke:{};stroke-width:{:f};".format(color, width), "comment": str(comment)})
+ elif figure == "arrow":
+ if fill is None:
+ fill = "#12b3ff"
+ fill_opacity = "0.8"
+ d = "m {},{} ".format(x[0], x[1]) + re.sub("([0-9\\-.e]+)", (lambda match: str(float(match.group(1)) * size * 2.)), "0.88464,-0.40404 c -0.0987,-0.0162 -0.186549,-0.0589 -0.26147,-0.1173 l 0.357342,-0.35625 c 0.04631,-0.039 0.0031,-0.13174 -0.05665,-0.12164 -0.0029,-1.4e-4 -0.0058,-1.4e-4 -0.0087,0 l -2.2e-5,2e-5 c -0.01189,0.004 -0.02257,0.0119 -0.0305,0.0217 l -0.357342,0.35625 c -0.05818,-0.0743 -0.102813,-0.16338 -0.117662,-0.26067 l -0.409636,0.88193 z")
+ attrib.update({"d": d, "style": "fill:{};stroke:none;fill-opacity:{};".format(fill, fill_opacity), "comment": str(comment)})
+ else:
+ attrib.update({"d": "m {},{} l {:f},{:f} {:f},{:f} {:f},{:f} {:f},{:f} , {:f},{:f}".format(x[0], x[1], size, size, -2 * size, -2 * size, size, size, size, -size, -2 * size, 2 * size), "style": "fill:none;stroke:{};stroke-width:{:f};".format(color, width), "comment": str(comment)})
+ group.add(PathElement(**attrib))
+
+
+def straight_segments_intersection(a, b, true_intersection=True): # (True intersection means check ta and tb are in [0,1])
+ ax = a[0][0]
+ bx = a[1][0]
+ cx = b[0][0]
+ dx = b[1][0]
+ ay = a[0][1]
+ by = a[1][1]
+ cy = b[0][1]
+ dy = b[1][1]
+ if (ax == bx and ay == by) or (cx == dx and cy == dy):
+ return False, 0, 0
+ if (bx - ax) * (dy - cy) - (by - ay) * (dx - cx) == 0: # Lines are parallel
+ ta = (ax - cx) / (dx - cx) if cx != dx else (ay - cy) / (dy - cy)
+ tb = (bx - cx) / (dx - cx) if cx != dx else (by - cy) / (dy - cy)
+ tc = (cx - ax) / (bx - ax) if ax != bx else (cy - ay) / (by - ay)
+ td = (dx - ax) / (bx - ax) if ax != bx else (dy - ay) / (by - ay)
+ return ("Overlap" if 0 <= ta <= 1 or 0 <= tb <= 1 or 0 <= tc <= 1 or 0 <= td <= 1 or not true_intersection else False), (ta, tb), (tc, td)
+ else:
+ ta = ((ay - cy) * (dx - cx) - (ax - cx) * (dy - cy)) / ((bx - ax) * (dy - cy) - (by - ay) * (dx - cx))
+ tb = (ax - cx + ta * (bx - ax)) / (dx - cx) if dx != cx else (ay - cy + ta * (by - ay)) / (dy - cy)
+ return (0 <= ta <= 1 and 0 <= tb <= 1 or not true_intersection), ta, tb
+
+
+def between(c, x, y):
+ return x - STRAIGHT_TOLERANCE <= c <= y + STRAIGHT_TOLERANCE or y - STRAIGHT_TOLERANCE <= c <= x + STRAIGHT_TOLERANCE
+
+
+def cubic_solver_real(a, b, c, d):
+ # returns only real roots of a cubic equation.
+ roots = cubic_solver(a, b, c, d)
+ res = []
+ for root in roots:
+ if type(root) is complex:
+ if -1e-10 < root.imag < 1e-10:
+ res.append(root.real)
+ else:
+ res.append(root)
+ return res
+
+
+def cubic_solver(a, b, c, d):
+ if a != 0:
+ # Monics formula see http://en.wikipedia.org/wiki/Cubic_function#Monic_formula_of_roots
+ a, b, c = (b / a, c / a, d / a)
+ m = 2 * a ** 3 - 9 * a * b + 27 * c
+ k = a ** 2 - 3 * b
+ n = m ** 2 - 4 * k ** 3
+ w1 = -.5 + .5 * cmath.sqrt(3) * 1j
+ w2 = -.5 - .5 * cmath.sqrt(3) * 1j
+ if n >= 0:
+ t = m + math.sqrt(n)
+ m1 = pow(t / 2, 1. / 3) if t >= 0 else -pow(-t / 2, 1. / 3)
+ t = m - math.sqrt(n)
+ n1 = pow(t / 2, 1. / 3) if t >= 0 else -pow(-t / 2, 1. / 3)
+ else:
+ m1 = pow(complex((m + cmath.sqrt(n)) / 2), 1. / 3)
+ n1 = pow(complex((m - cmath.sqrt(n)) / 2), 1. / 3)
+ x1 = -1. / 3 * (a + m1 + n1)
+ x2 = -1. / 3 * (a + w1 * m1 + w2 * n1)
+ x3 = -1. / 3 * (a + w2 * m1 + w1 * n1)
+ return [x1, x2, x3]
+ elif b != 0:
+ det = c ** 2 - 4 * b * d
+ if det > 0:
+ return [(-c + math.sqrt(det)) / (2 * b), (-c - math.sqrt(det)) / (2 * b)]
+ elif d == 0:
+ return [-c / (b * b)]
+ else:
+ return [(-c + cmath.sqrt(det)) / (2 * b), (-c - cmath.sqrt(det)) / (2 * b)]
+ elif c != 0:
+ return [-d / c]
+ else:
+ return []
+
+
+################################################################################
+# print_ prints any arguments into specified log file
+################################################################################
+
+def print_(*arg):
+ with open(options.log_filename, "ab") as f:
+ for s in arg:
+ s = unicode(s).encode('unicode_escape') + b" "
+ f.write(s)
+ f.write(b"\n")
+
+
+################################################################################
+# Point (x,y) operations
+################################################################################
+class P(object):
+ def __init__(self, x, y=None):
+ if not y is None:
+ self.x = float(x)
+ self.y = float(y)
+ else:
+ self.x = float(x[0])
+ self.y = float(x[1])
+
+ def __add__(self, other):
+ return P(self.x + other.x, self.y + other.y)
+
+ def __sub__(self, other):
+ return P(self.x - other.x, self.y - other.y)
+
+ def __neg__(self):
+ return P(-self.x, -self.y)
+
+ def __mul__(self, other):
+ if isinstance(other, P):
+ return self.x * other.x + self.y * other.y
+ return P(self.x * other, self.y * other)
+
+ __rmul__ = __mul__
+
+ def __div__(self, other):
+ return P(self.x / other, self.y / other)
+
+ def __truediv__(self, other):
+ return self.__div__(other)
+
+ def mag(self):
+ return math.hypot(self.x, self.y)
+
+ def unit(self):
+ h_mag = self.mag()
+ if h_mag:
+ return self / h_mag
+ return P(0, 0)
+
+ def dot(self, other):
+ return self.x * other.x + self.y * other.y
+
+ def rot(self, theta):
+ c = math.cos(theta)
+ s = math.sin(theta)
+ return P(self.x * c - self.y * s, self.x * s + self.y * c)
+
+ def angle(self):
+ return math.atan2(self.y, self.x)
+
+ def __repr__(self):
+ return '{:f},{:f}'.format(self.x, self.y)
+
+ def pr(self):
+ return "{:.2f},{:.2f}".format(self.x, self.y)
+
+ def to_list(self):
+ return [self.x, self.y]
+
+ def ccw(self):
+ return P(-self.y, self.x)
+
+ def l2(self):
+ return self.x * self.x + self.y * self.y
+
+
+class Line(object):
+ def __init__(self, st, end):
+ if st.__class__ == P:
+ st = st.to_list()
+ if end.__class__ == P:
+ end = end.to_list()
+ self.st = P(st)
+ self.end = P(end)
+ self.l = self.length()
+ if self.l != 0:
+ self.n = ((self.end - self.st) / self.l).ccw()
+ else:
+ self.n = [0, 1]
+
+ def offset(self, r):
+ self.st -= self.n * r
+ self.end -= self.n * r
+
+ def l2(self):
+ return (self.st - self.end).l2()
+
+ def length(self):
+ return (self.st - self.end).mag()
+
+ def draw(self, group, style, layer, transform, num=0, reverse_angle=1):
+ st = gcodetools.transform(self.st.to_list(), layer, True)
+ end = gcodetools.transform(self.end.to_list(), layer, True)
+
+ attr = {'style': style['line'],
+ 'd': 'M {},{} L {},{}'.format(st[0], st[1], end[0], end[1]),
+ "gcodetools": "Preview",
+ }
+ if transform:
+ attr["transform"] = transform
+ group.add(PathElement(**attr))
+
+ def intersect(self, b):
+ if b.__class__ == Line:
+ if self.l < 10e-8 or b.l < 10e-8:
+ return []
+ v1 = self.end - self.st
+ v2 = b.end - b.st
+ x = v1.x * v2.y - v2.x * v1.y
+ if x == 0:
+ # lines are parallel
+ res = []
+
+ if (self.st.x - b.st.x) * v1.y - (self.st.y - b.st.y) * v1.x == 0:
+ # lines are the same
+ if v1.x != 0:
+ if 0 <= (self.st.x - b.st.x) / v2.x <= 1:
+ res.append(self.st)
+ if 0 <= (self.end.x - b.st.x) / v2.x <= 1:
+ res.append(self.end)
+ if 0 <= (b.st.x - self.st.x) / v1.x <= 1:
+ res.append(b.st)
+ if 0 <= (b.end.x - b.st.x) / v1.x <= 1:
+ res.append(b.end)
+ else:
+ if 0 <= (self.st.y - b.st.y) / v2.y <= 1:
+ res.append(self.st)
+ if 0 <= (self.end.y - b.st.y) / v2.y <= 1:
+ res.append(self.end)
+ if 0 <= (b.st.y - self.st.y) / v1.y <= 1:
+ res.append(b.st)
+ if 0 <= (b.end.y - b.st.y) / v1.y <= 1:
+ res.append(b.end)
+ return res
+ else:
+ t1 = (-v1.x * (b.end.y - self.end.y) + v1.y * (b.end.x - self.end.x)) / x
+ t2 = (-v1.y * (self.st.x - b.st.x) + v1.x * (self.st.y - b.st.y)) / x
+
+ gcodetools.error(str((x, t1, t2)))
+ if 0 <= t1 <= 1 and 0 <= t2 <= 1:
+ return [self.st + v1 * t1]
+ else:
+ return []
+ else:
+ return []
+
+
+################################################################################
+#
+# Offset function
+#
+# This function offsets given cubic super path.
+# It's based on src/livarot/PathOutline.cpp from Inkscape's source code.
+#
+#
+################################################################################
+def csp_offset(csp, r):
+ offset_tolerance = 0.05
+ offset_subdivision_depth = 10
+ time_ = time.time()
+ time_start = time_
+ print_("Offset start at {}".format(time_))
+ print_("Offset radius {}".format(r))
+
+ def csp_offset_segment(sp1, sp2, r):
+ result = []
+ t = csp_get_t_at_curvature(sp1, sp2, 1 / r)
+ if len(t) == 0:
+ t = [0., 1.]
+ t.sort()
+ if t[0] > .00000001:
+ t = [0.] + t
+ if t[-1] < .99999999:
+ t.append(1.)
+ for st, end in zip(t, t[1:]):
+ c = csp_curvature_at_t(sp1, sp2, (st + end) / 2)
+ sp = csp_split_by_two_points(sp1, sp2, st, end)
+ if sp[1] != sp[2]:
+ if c > 1 / r and r < 0 or c < 1 / r and r > 0:
+ offset = offset_segment_recursion(sp[1], sp[2], r, offset_subdivision_depth, offset_tolerance)
+ else: # This part will be clipped for sure... TODO Optimize it...
+ offset = offset_segment_recursion(sp[1], sp[2], r, offset_subdivision_depth, offset_tolerance)
+
+ if not result:
+ result = offset[:]
+ else:
+ if csp_subpaths_end_to_start_distance2(result, offset) < 0.0001:
+ result = csp_concat_subpaths(result, offset)
+ else:
+
+ intersection = csp_get_subapths_last_first_intersection(result, offset)
+ if intersection:
+ i, t1, j, t2 = intersection
+ sp1_, sp2_, sp3_ = csp_split(result[i - 1], result[i], t1)
+ result = result[:i - 1] + [sp1_, sp2_]
+ sp1_, sp2_, sp3_ = csp_split(offset[j - 1], offset[j], t2)
+ result = csp_concat_subpaths(result, [sp2_, sp3_] + offset[j + 1:])
+ else:
+ pass # ???
+ return result
+
+ def create_offset_segment(sp1, sp2, r):
+ # See Gernot Hoffmann "Bezier Curves" p.34 -> 7.1 Bezier Offset Curves
+ p0 = P(sp1[1])
+ p1 = P(sp1[2])
+ p2 = P(sp2[0])
+ p3 = P(sp2[1])
+
+ s0 = p1 - p0
+ s1 = p2 - p1
+ s3 = p3 - p2
+
+ n0 = s0.ccw().unit() if s0.l2() != 0 else P(csp_normalized_normal(sp1, sp2, 0))
+ n3 = s3.ccw().unit() if s3.l2() != 0 else P(csp_normalized_normal(sp1, sp2, 1))
+ n1 = s1.ccw().unit() if s1.l2() != 0 else (n0.unit() + n3.unit()).unit()
+
+ q0 = p0 + r * n0
+ q3 = p3 + r * n3
+ c = csp_curvature_at_t(sp1, sp2, 0)
+ q1 = q0 + (p1 - p0) * (1 - (r * c if abs(c) < 100 else 0))
+ c = csp_curvature_at_t(sp1, sp2, 1)
+ q2 = q3 + (p2 - p3) * (1 - (r * c if abs(c) < 100 else 0))
+
+ return [[q0.to_list(), q0.to_list(), q1.to_list()], [q2.to_list(), q3.to_list(), q3.to_list()]]
+
+ def csp_get_subapths_last_first_intersection(s1, s2):
+ _break = False
+ for i in range(1, len(s1)):
+ sp11 = s1[-i - 1]
+ sp12 = s1[-i]
+ for j in range(1, len(s2)):
+ sp21 = s2[j - 1]
+ sp22 = s2[j]
+ intersection = csp_segments_true_intersection(sp11, sp12, sp21, sp22)
+ if intersection:
+ _break = True
+ break
+ if _break:
+ break
+ if _break:
+ intersection = max(intersection)
+ return [len(s1) - i, intersection[0], j, intersection[1]]
+ else:
+ return []
+
+ def csp_join_offsets(prev, next, sp1, sp2, sp1_l, sp2_l, r):
+ if len(next) > 1:
+ if (P(prev[-1][1]) - P(next[0][1])).l2() < 0.001:
+ return prev, [], next
+ intersection = csp_get_subapths_last_first_intersection(prev, next)
+ if intersection:
+ i, t1, j, t2 = intersection
+ sp1_, sp2_, sp3_ = csp_split(prev[i - 1], prev[i], t1)
+ sp3_, sp4_, sp5_ = csp_split(next[j - 1], next[j], t2)
+ return prev[:i - 1] + [sp1_, sp2_], [], [sp4_, sp5_] + next[j + 1:]
+
+ # Offsets do not intersect... will add an arc...
+ start = (P(csp_at_t(sp1_l, sp2_l, 1.)) + r * P(csp_normalized_normal(sp1_l, sp2_l, 1.))).to_list()
+ end = (P(csp_at_t(sp1, sp2, 0.)) + r * P(csp_normalized_normal(sp1, sp2, 0.))).to_list()
+ arc = csp_from_arc(start, end, sp1[1], r, csp_normalized_slope(sp1_l, sp2_l, 1.))
+ if not arc:
+ return prev, [], next
+ else:
+ # Clip prev by arc
+ if csp_subpaths_end_to_start_distance2(prev, arc) > 0.00001:
+ intersection = csp_get_subapths_last_first_intersection(prev, arc)
+ if intersection:
+ i, t1, j, t2 = intersection
+ sp1_, sp2_, sp3_ = csp_split(prev[i - 1], prev[i], t1)
+ sp3_, sp4_, sp5_ = csp_split(arc[j - 1], arc[j], t2)
+ prev = prev[:i - 1] + [sp1_, sp2_]
+ arc = [sp4_, sp5_] + arc[j + 1:]
+ # Clip next by arc
+ if not next:
+ return prev, [], arc
+ if csp_subpaths_end_to_start_distance2(arc, next) > 0.00001:
+ intersection = csp_get_subapths_last_first_intersection(arc, next)
+ if intersection:
+ i, t1, j, t2 = intersection
+ sp1_, sp2_, sp3_ = csp_split(arc[i - 1], arc[i], t1)
+ sp3_, sp4_, sp5_ = csp_split(next[j - 1], next[j], t2)
+ arc = arc[:i - 1] + [sp1_, sp2_]
+ next = [sp4_, sp5_] + next[j + 1:]
+
+ return prev, arc, next
+
+ def offset_segment_recursion(sp1, sp2, r, depth, tolerance):
+ sp1_r, sp2_r = create_offset_segment(sp1, sp2, r)
+ err = max(
+ csp_seg_to_point_distance(sp1_r, sp2_r, (P(csp_at_t(sp1, sp2, .25)) + P(csp_normalized_normal(sp1, sp2, .25)) * r).to_list())[0],
+ csp_seg_to_point_distance(sp1_r, sp2_r, (P(csp_at_t(sp1, sp2, .50)) + P(csp_normalized_normal(sp1, sp2, .50)) * r).to_list())[0],
+ csp_seg_to_point_distance(sp1_r, sp2_r, (P(csp_at_t(sp1, sp2, .75)) + P(csp_normalized_normal(sp1, sp2, .75)) * r).to_list())[0],
+ )
+
+ if err > tolerance ** 2 and depth > 0:
+ if depth > offset_subdivision_depth - 2:
+ t = csp_max_curvature(sp1, sp2)
+ t = max(.1, min(.9, t))
+ else:
+ t = .5
+ sp3, sp4, sp5 = csp_split(sp1, sp2, t)
+ r1 = offset_segment_recursion(sp3, sp4, r, depth - 1, tolerance)
+ r2 = offset_segment_recursion(sp4, sp5, r, depth - 1, tolerance)
+ return r1[:-1] + [[r1[-1][0], r1[-1][1], r2[0][2]]] + r2[1:]
+ else:
+ return [sp1_r, sp2_r]
+
+ ############################################################################
+ # Some small definitions
+ ############################################################################
+ csp_len = len(csp)
+
+ ############################################################################
+ # Prepare the path
+ ############################################################################
+ # Remove all small segments (segment length < 0.001)
+
+ for i in xrange(len(csp)):
+ for j in xrange(len(csp[i])):
+ sp = csp[i][j]
+ if (P(sp[1]) - P(sp[0])).mag() < 0.001:
+ csp[i][j][0] = sp[1]
+ if (P(sp[2]) - P(sp[0])).mag() < 0.001:
+ csp[i][j][2] = sp[1]
+ for i in xrange(len(csp)):
+ for j in xrange(1, len(csp[i])):
+ if cspseglength(csp[i][j - 1], csp[i][j]) < 0.001:
+ csp[i] = csp[i][:j] + csp[i][j + 1:]
+ if cspseglength(csp[i][-1], csp[i][0]) > 0.001:
+ csp[i][-1][2] = csp[i][-1][1]
+ csp[i] += [[csp[i][0][1], csp[i][0][1], csp[i][0][1]]]
+
+ # TODO Get rid of self intersections.
+
+ original_csp = csp[:]
+ # Clip segments which has curvature>1/r. Because their offset will be self-intersecting and very nasty.
+
+ print_("Offset prepared the path in {}".format(time.time() - time_))
+ print_("Path length = {}".format(sum([len(i) for i in csp])))
+ time_ = time.time()
+
+ ############################################################################
+ # Offset
+ ############################################################################
+ # Create offsets for all segments in the path. And join them together inside each subpath.
+ unclipped_offset = [[] for i in xrange(csp_len)]
+
+ intersection = [[] for i in xrange(csp_len)]
+ for i in xrange(csp_len):
+ subpath = csp[i]
+ subpath_offset = []
+ for sp1, sp2 in zip(subpath, subpath[1:]):
+ segment_offset = csp_offset_segment(sp1, sp2, r)
+ if not subpath_offset:
+ subpath_offset = segment_offset
+
+ prev_l = len(subpath_offset)
+ else:
+ prev, arc, next = csp_join_offsets(subpath_offset[-prev_l:], segment_offset, sp1, sp2, sp1_l, sp2_l, r)
+
+ subpath_offset = csp_concat_subpaths(subpath_offset[:-prev_l + 1], prev, arc, next)
+ prev_l = len(next)
+ sp1_l = sp1[:]
+ sp2_l = sp2[:]
+
+ # Join last and first offsets togother to close the curve
+
+ prev, arc, next = csp_join_offsets(subpath_offset[-prev_l:], subpath_offset[:2], subpath[0], subpath[1], sp1_l, sp2_l, r)
+ subpath_offset[:2] = next[:]
+ subpath_offset = csp_concat_subpaths(subpath_offset[:-prev_l + 1], prev, arc)
+
+ # Collect subpath's offset and save it to unclipped offset list.
+ unclipped_offset[i] = subpath_offset[:]
+
+ print_("Offsetted path in {}".format(time.time() - time_))
+ time_ = time.time()
+
+ ############################################################################
+ # Now to the clipping.
+ ############################################################################
+ # First of all find all intersection's between all segments of all offset subpaths, including self intersections.
+
+ # TODO define offset tolerance here
+ global small_tolerance
+ small_tolerance = 0.01
+ summ = 0
+ summ1 = 0
+ for subpath_i in xrange(csp_len):
+ for subpath_j in xrange(subpath_i, csp_len):
+ subpath = unclipped_offset[subpath_i]
+ subpath1 = unclipped_offset[subpath_j]
+ for i in xrange(1, len(subpath)):
+ # If subpath_i==subpath_j we are looking for self intersections, so
+ # we'll need search intersections only for xrange(i,len(subpath1))
+ for j in (xrange(i, len(subpath1)) if subpath_i == subpath_j else xrange(len(subpath1))):
+ if subpath_i == subpath_j and j == i:
+ # Find self intersections of a segment
+ sp1, sp2, sp3 = csp_split(subpath[i - 1], subpath[i], .5)
+ intersections = csp_segments_intersection(sp1, sp2, sp2, sp3)
+ summ += 1
+ for t in intersections:
+ summ1 += 1
+ if not (small(t[0] - 1) and small(t[1])) and 0 <= t[0] <= 1 and 0 <= t[1] <= 1:
+ intersection[subpath_i] += [[i, t[0] / 2], [j, t[1] / 2 + .5]]
+ else:
+ intersections = csp_segments_intersection(subpath[i - 1], subpath[i], subpath1[j - 1], subpath1[j])
+ summ += 1
+ for t in intersections:
+ summ1 += 1
+ # TODO tolerance dependence to cpsp_length(t)
+ if len(t) == 2 and 0 <= t[0] <= 1 and 0 <= t[1] <= 1 and not (
+ subpath_i == subpath_j and (
+ (j - i - 1) % (len(subpath) - 1) == 0 and small(t[0] - 1) and small(t[1]) or
+ (i - j - 1) % (len(subpath) - 1) == 0 and small(t[1] - 1) and small(t[0]))):
+ intersection[subpath_i] += [[i, t[0]]]
+ intersection[subpath_j] += [[j, t[1]]]
+
+ elif len(t) == 5 and t[4] == "Overlap":
+ intersection[subpath_i] += [[i, t[0]], [i, t[1]]]
+ intersection[subpath_j] += [[j, t[1]], [j, t[3]]]
+
+ print_("Intersections found in {}".format(time.time() - time_))
+ print_("Examined {} segments".format(summ))
+ print_("found {} intersections".format(summ1))
+ time_ = time.time()
+
+ ########################################################################
+ # Split unclipped offset by intersection points into splitted_offset
+ ########################################################################
+ splitted_offset = []
+ for i in xrange(csp_len):
+ subpath = unclipped_offset[i]
+ if len(intersection[i]) > 0:
+ parts = csp_subpath_split_by_points(subpath, intersection[i])
+ # Close parts list to close path (The first and the last parts are joined together)
+ if [1, 0.] not in intersection[i]:
+ parts[0][0][0] = parts[-1][-1][0]
+ parts[0] = csp_concat_subpaths(parts[-1], parts[0])
+ splitted_offset += parts[:-1]
+ else:
+ splitted_offset += parts[:]
+ else:
+ splitted_offset += [subpath[:]]
+
+ print_("Split in {}".format(time.time() - time_))
+ time_ = time.time()
+
+ ########################################################################
+ # Clipping
+ ########################################################################
+ result = []
+ for subpath_i in range(len(splitted_offset)):
+ clip = False
+ s1 = splitted_offset[subpath_i]
+ for subpath_j in range(len(splitted_offset)):
+ s2 = splitted_offset[subpath_j]
+ if (P(s1[0][1]) - P(s2[-1][1])).l2() < 0.0001 and ((subpath_i + 1) % len(splitted_offset) != subpath_j):
+ if dot(csp_normalized_normal(s2[-2], s2[-1], 1.), csp_normalized_slope(s1[0], s1[1], 0.)) * r < -0.0001:
+ clip = True
+ break
+ if (P(s2[0][1]) - P(s1[-1][1])).l2() < 0.0001 and ((subpath_j + 1) % len(splitted_offset) != subpath_i):
+ if dot(csp_normalized_normal(s2[0], s2[1], 0.), csp_normalized_slope(s1[-2], s1[-1], 1.)) * r > 0.0001:
+ clip = True
+ break
+
+ if not clip:
+ result += [s1[:]]
+ elif options.offset_draw_clippend_path:
+ draw_csp([s1], width=.1)
+ draw_pointer(csp_at_t(s2[-2], s2[-1], 1.) +
+ (P(csp_at_t(s2[-2], s2[-1], 1.)) + P(csp_normalized_normal(s2[-2], s2[-1], 1.)) * 10).to_list(), "Green", "line")
+ draw_pointer(csp_at_t(s1[0], s1[1], 0.) +
+ (P(csp_at_t(s1[0], s1[1], 0.)) + P(csp_normalized_slope(s1[0], s1[1], 0.)) * 10).to_list(), "Red", "line")
+
+ # Now join all together and check closure and orientation of result
+ joined_result = csp_join_subpaths(result)
+ # Check if each subpath from joined_result is closed
+
+ for s in joined_result[:]:
+ if csp_subpaths_end_to_start_distance2(s, s) > 0.001:
+ # Remove open parts
+ if options.offset_draw_clippend_path:
+ draw_csp([s], width=1)
+ draw_pointer(s[0][1], comment=csp_subpaths_end_to_start_distance2(s, s))
+ draw_pointer(s[-1][1], comment=csp_subpaths_end_to_start_distance2(s, s))
+ joined_result.remove(s)
+ else:
+ # Remove small parts
+ minx, miny, maxx, maxy = csp_true_bounds([s])
+ if (minx[0] - maxx[0]) ** 2 + (miny[1] - maxy[1]) ** 2 < 0.1:
+ joined_result.remove(s)
+ print_("Clipped and joined path in {}".format(time.time() - time_))
+
+ ########################################################################
+ # Now to the Dummy clipping: remove parts from split offset if their
+ # centers are closer to the original path than offset radius.
+ ########################################################################
+
+ if abs(r * .01) < 1:
+ r1 = (0.99 * r) ** 2
+ r2 = (1.01 * r) ** 2
+ else:
+ r1 = (abs(r) - 1) ** 2
+ r2 = (abs(r) + 1) ** 2
+
+ for s in joined_result[:]:
+ dist = csp_to_point_distance(original_csp, s[int(len(s) / 2)][1], dist_bounds=[r1, r2])
+ if not r1 < dist[0] < r2:
+ joined_result.remove(s)
+ if options.offset_draw_clippend_path:
+ draw_csp([s], comment=math.sqrt(dist[0]))
+ draw_pointer(csp_at_t(csp[dist[1]][dist[2] - 1], csp[dist[1]][dist[2]], dist[3]) + s[int(len(s) / 2)][1], "blue", "line", comment=[math.sqrt(dist[0]), i, j, sp])
+
+ print_("-----------------------------")
+ print_("Total offset time {}".format(time.time() - time_start))
+ print_()
+ return joined_result
+
+
+################################################################################
+#
+# Biarc function
+#
+# Calculates biarc approximation of cubic super path segment
+# splits segment if needed or approximates it with straight line
+#
+################################################################################
+def biarc(sp1, sp2, z1, z2, depth=0):
+ def biarc_split(sp1, sp2, z1, z2, depth):
+ if depth < options.biarc_max_split_depth:
+ sp1, sp2, sp3 = csp_split(sp1, sp2)
+ l1 = cspseglength(sp1, sp2)
+ l2 = cspseglength(sp2, sp3)
+ if l1 + l2 == 0:
+ zm = z1
+ else:
+ zm = z1 + (z2 - z1) * l1 / (l1 + l2)
+ return biarc(sp1, sp2, z1, zm, depth + 1) + biarc(sp2, sp3, zm, z2, depth + 1)
+ else:
+ return [[sp1[1], 'line', 0, 0, sp2[1], [z1, z2]]]
+
+ P0 = P(sp1[1])
+ P4 = P(sp2[1])
+ TS = (P(sp1[2]) - P0)
+ TE = -(P(sp2[0]) - P4)
+ v = P0 - P4
+ tsa = TS.angle()
+ tea = TE.angle()
+ va = v.angle()
+ if TE.mag() < STRAIGHT_DISTANCE_TOLERANCE and TS.mag() < STRAIGHT_DISTANCE_TOLERANCE:
+ # Both tangents are zero - line straight
+ return [[sp1[1], 'line', 0, 0, sp2[1], [z1, z2]]]
+ if TE.mag() < STRAIGHT_DISTANCE_TOLERANCE:
+ TE = -(TS + v).unit()
+ r = TS.mag() / v.mag() * 2
+ elif TS.mag() < STRAIGHT_DISTANCE_TOLERANCE:
+ TS = -(TE + v).unit()
+ r = 1 / (TE.mag() / v.mag() * 2)
+ else:
+ r = TS.mag() / TE.mag()
+ TS = TS.unit()
+ TE = TE.unit()
+ tang_are_parallel = ((tsa - tea) % math.pi < STRAIGHT_TOLERANCE or math.pi - (tsa - tea) % math.pi < STRAIGHT_TOLERANCE)
+ if (tang_are_parallel and
+ ((v.mag() < STRAIGHT_DISTANCE_TOLERANCE or TE.mag() < STRAIGHT_DISTANCE_TOLERANCE or TS.mag() < STRAIGHT_DISTANCE_TOLERANCE) or
+ 1 - abs(TS * v / (TS.mag() * v.mag())) < STRAIGHT_TOLERANCE)):
+ # Both tangents are parallel and start and end are the same - line straight
+ # or one of tangents still smaller then tolerance
+
+ # Both tangents and v are parallel - line straight
+ return [[sp1[1], 'line', 0, 0, sp2[1], [z1, z2]]]
+
+ c = v * v
+ b = 2 * v * (r * TS + TE)
+ a = 2 * r * (TS * TE - 1)
+ if v.mag() == 0:
+ return biarc_split(sp1, sp2, z1, z2, depth)
+ asmall = abs(a) < 10 ** -10
+ bsmall = abs(b) < 10 ** -10
+ csmall = abs(c) < 10 ** -10
+ if asmall and b != 0:
+ beta = -c / b
+ elif csmall and a != 0:
+ beta = -b / a
+ elif not asmall:
+ discr = b * b - 4 * a * c
+ if discr < 0:
+ raise ValueError(a, b, c, discr)
+ disq = discr ** .5
+ beta1 = (-b - disq) / 2 / a
+ beta2 = (-b + disq) / 2 / a
+ if beta1 * beta2 > 0:
+ raise ValueError(a, b, c, disq, beta1, beta2)
+ beta = max(beta1, beta2)
+ elif asmall and bsmall:
+ return biarc_split(sp1, sp2, z1, z2, depth)
+ alpha = beta * r
+ ab = alpha + beta
+ P1 = P0 + alpha * TS
+ P3 = P4 - beta * TE
+ P2 = (beta / ab) * P1 + (alpha / ab) * P3
+
+ def calculate_arc_params(P0, P1, P2):
+ D = (P0 + P2) / 2
+ if (D - P1).mag() == 0:
+ return None, None
+ R = D - ((D - P0).mag() ** 2 / (D - P1).mag()) * (P1 - D).unit()
+ p0a = (P0 - R).angle() % (2 * math.pi)
+ p1a = (P1 - R).angle() % (2 * math.pi)
+ p2a = (P2 - R).angle() % (2 * math.pi)
+ alpha = (p2a - p0a) % (2 * math.pi)
+ if (p0a < p2a and (p1a < p0a or p2a < p1a)) or (p2a < p1a < p0a):
+ alpha = -2 * math.pi + alpha
+ if abs(R.x) > 1000000 or abs(R.y) > 1000000 or (R - P0).mag() < options.min_arc_radius ** 2:
+ return None, None
+ else:
+ return R, alpha
+
+ R1, a1 = calculate_arc_params(P0, P1, P2)
+ R2, a2 = calculate_arc_params(P2, P3, P4)
+ if R1 is None or R2 is None or (R1 - P0).mag() < STRAIGHT_TOLERANCE or (R2 - P2).mag() < STRAIGHT_TOLERANCE:
+ return [[sp1[1], 'line', 0, 0, sp2[1], [z1, z2]]]
+
+ d = csp_to_arc_distance(sp1, sp2, [P0, P2, R1, a1], [P2, P4, R2, a2])
+ if d > options.biarc_tolerance and depth < options.biarc_max_split_depth:
+ return biarc_split(sp1, sp2, z1, z2, depth)
+ else:
+ if R2.mag() * a2 == 0:
+ zm = z2
+ else:
+ zm = z1 + (z2 - z1) * (abs(R1.mag() * a1)) / (abs(R2.mag() * a2) + abs(R1.mag() * a1))
+
+ l = (P0 - P2).l2()
+ if l < EMC_TOLERANCE_EQUAL ** 2 or l < EMC_TOLERANCE_EQUAL ** 2 * R1.l2() / 100:
+ # arc should be straight otherwise it could be treated as full circle
+ arc1 = [sp1[1], 'line', 0, 0, [P2.x, P2.y], [z1, zm]]
+ else:
+ arc1 = [sp1[1], 'arc', [R1.x, R1.y], a1, [P2.x, P2.y], [z1, zm]]
+
+ l = (P4 - P2).l2()
+ if l < EMC_TOLERANCE_EQUAL ** 2 or l < EMC_TOLERANCE_EQUAL ** 2 * R2.l2() / 100:
+ # arc should be straight otherwise it could be treated as full circle
+ arc2 = [[P2.x, P2.y], 'line', 0, 0, [P4.x, P4.y], [zm, z2]]
+ else:
+ arc2 = [[P2.x, P2.y], 'arc', [R2.x, R2.y], a2, [P4.x, P4.y], [zm, z2]]
+
+ return [arc1, arc2]
+
+
+class Postprocessor(object):
+ def __init__(self, error_function_handler):
+ self.error = error_function_handler
+ self.functions = {
+ "remap": self.remap,
+ "remapi": self.remapi,
+ "scale": self.scale,
+ "move": self.move,
+ "flip": self.flip_axis,
+ "flip_axis": self.flip_axis,
+ "round": self.round_coordinates,
+ "parameterize": self.parameterize,
+ "regex": self.re_sub_on_gcode_lines
+ }
+
+ def process(self, command):
+ command = re.sub(r"\\\\", ":#:#:slash:#:#:", command)
+ command = re.sub(r"\\;", ":#:#:semicolon:#:#:", command)
+ command = command.split(";")
+ for s in command:
+ s = re.sub(":#:#:slash:#:#:", "\\\\", s)
+ s = re.sub(":#:#:semicolon:#:#:", "\\;", s)
+ s = s.strip()
+ if s != "":
+ self.parse_command(s)
+
+ def parse_command(self, command):
+ r = re.match(r"([A-Za-z0-9_]+)\s*\(\s*(.*)\)", command)
+ if not r:
+ self.error("Parse error while postprocessing.\n(Command: '{}')".format(command), "error")
+ function = r.group(1).lower()
+ parameters = r.group(2)
+ if function in self.functions:
+ print_("Postprocessor: executing function {}({})".format(function, parameters))
+ self.functions[function](parameters)
+ else:
+ self.error("Unrecognized function '{}' while postprocessing.\n(Command: '{}')".format(function, command), "error")
+
+ def re_sub_on_gcode_lines(self, parameters):
+ gcode = self.gcode.split("\n")
+ self.gcode = ""
+ try:
+ for line in gcode:
+ self.gcode += eval("re.sub({},line)".format(parameters)) + "\n"
+
+ except Exception as ex:
+ self.error("Bad parameters for regexp. "
+ "They should be as re.sub pattern and replacement parameters! "
+ "For example: r\"G0(\\d)\", r\"G\\1\" \n"
+ "(Parameters: '{}')\n {}".format(parameters, ex), "error")
+
+ def remapi(self, parameters):
+ self.remap(parameters, case_sensitive=True)
+
+ def remap(self, parameters, case_sensitive=False):
+ # remap parameters should be like "x->y,y->x"
+ parameters = parameters.replace("\\,", ":#:#:coma:#:#:")
+ parameters = parameters.split(",")
+ pattern = []
+ remap = []
+ for s in parameters:
+ s = s.replace(":#:#:coma:#:#:", "\\,")
+ r = re.match("""\\s*(\'|\")(.*)\\1\\s*->\\s*(\'|\")(.*)\\3\\s*""", s)
+ if not r:
+ self.error("Bad parameters for remap.\n(Parameters: '{}')".format(parameters), "error")
+ pattern += [r.group(2)]
+ remap += [r.group(4)]
+
+ for i in range(len(pattern)):
+ if case_sensitive:
+ self.gcode = ireplace(self.gcode, pattern[i], ":#:#:remap_pattern{}:#:#:".format(i))
+ else:
+ self.gcode = self.gcode.replace(pattern[i], ":#:#:remap_pattern{}:#:#:".format(i))
+
+ for i in range(len(remap)):
+ self.gcode = self.gcode.replace(":#:#:remap_pattern{}:#:#:".format(i), remap[i])
+
+ def transform(self, move, scale):
+ axis = ["xi", "yj", "zk", "a"]
+ flip = scale[0] * scale[1] * scale[2] < 0
+ gcode = ""
+ warned = []
+ r_scale = scale[0]
+ plane = "g17"
+ for s in self.gcode.split("\n"):
+ # get plane selection:
+ s_wo_comments = re.sub(r"\([^\)]*\)", "", s)
+ r = re.search(r"(?i)(G17|G18|G19)", s_wo_comments)
+ if r:
+ plane = r.group(1).lower()
+ if plane == "g17":
+ r_scale = scale[0] # plane XY -> scale x
+ if plane == "g18":
+ r_scale = scale[0] # plane XZ -> scale x
+ if plane == "g19":
+ r_scale = scale[1] # plane YZ -> scale y
+ # Raise warning if scale factors are not the game for G02 and G03
+ if plane not in warned:
+ r = re.search(r"(?i)(G02|G03)", s_wo_comments)
+ if r:
+ if plane == "g17" and scale[0] != scale[1]:
+ self.error("Post-processor: Scale factors for X and Y axis are not the same. G02 and G03 codes will be corrupted.")
+ if plane == "g18" and scale[0] != scale[2]:
+ self.error("Post-processor: Scale factors for X and Z axis are not the same. G02 and G03 codes will be corrupted.")
+ if plane == "g19" and scale[1] != scale[2]:
+ self.error("Post-processor: Scale factors for Y and Z axis are not the same. G02 and G03 codes will be corrupted.")
+ warned += [plane]
+ # Transform
+ for i in range(len(axis)):
+ if move[i] != 0 or scale[i] != 1:
+ for a in axis[i]:
+ r = re.search(r"(?i)(" + a + r")\s*(-?)\s*(\d*\.?\d*)", s)
+ if r and r.group(3) != "":
+ s = re.sub(r"(?i)(" + a + r")\s*(-?)\s*(\d*\.?\d*)", r"\1 {:f}".format(float(r.group(2) + r.group(3)) * scale[i] + (move[i] if a not in ["i", "j", "k"] else 0)), s)
+ # scale radius R
+ if r_scale != 1:
+ r = re.search(r"(?i)(r)\s*(-?\s*(\d*\.?\d*))", s)
+ if r and r.group(3) != "":
+ try:
+ s = re.sub(r"(?i)(r)\s*(-?)\s*(\d*\.?\d*)", r"\1 {:f}".format(float(r.group(2) + r.group(3)) * r_scale), s)
+ except:
+ pass
+
+ gcode += s + "\n"
+
+ self.gcode = gcode
+ if flip:
+ self.remapi("'G02'->'G03', 'G03'->'G02'")
+
+ def parameterize(self, parameters):
+ planes = []
+ feeds = {}
+ coords = []
+ gcode = ""
+ coords_def = {"x": "x", "y": "y", "z": "z", "i": "x", "j": "y", "k": "z", "a": "a"}
+ for s in self.gcode.split("\n"):
+ s_wo_comments = re.sub(r"\([^\)]*\)", "", s)
+ # get Planes
+ r = re.search(r"(?i)(G17|G18|G19)", s_wo_comments)
+ if r:
+ plane = r.group(1).lower()
+ if plane not in planes:
+ planes += [plane]
+ # get Feeds
+ r = re.search(r"(?i)(F)\s*(-?)\s*(\d*\.?\d*)", s_wo_comments)
+ if r:
+ feed = float(r.group(2) + r.group(3))
+ if feed not in feeds:
+ feeds[feed] = "#" + str(len(feeds) + 20)
+
+ # Coordinates
+ for c in "xyzijka":
+ r = re.search(r"(?i)(" + c + r")\s*(-?)\s*(\d*\.?\d*)", s_wo_comments)
+ if r:
+ c = coords_def[r.group(1).lower()]
+ if c not in coords:
+ coords += [c]
+ # Add offset parametrization
+ offset = {"x": "#6", "y": "#7", "z": "#8", "a": "#9"}
+ for c in coords:
+ gcode += "{} = 0 ({} axis offset)\n".format(offset[c], c.upper())
+
+ # Add scale parametrization
+ if not planes:
+ planes = ["g17"]
+ if len(planes) > 1: # have G02 and G03 in several planes scale_x = scale_y = scale_z required
+ gcode += "#10 = 1 (Scale factor)\n"
+ scale = {"x": "#10", "i": "#10", "y": "#10", "j": "#10", "z": "#10", "k": "#10", "r": "#10"}
+ else:
+ gcode += "#10 = 1 ({} Scale factor)\n".format({"g17": "XY", "g18": "XZ", "g19": "YZ"}[planes[0]])
+ gcode += "#11 = 1 ({} Scale factor)\n".format({"g17": "Z", "g18": "Y", "g19": "X"}[planes[0]])
+ scale = {"x": "#10", "i": "#10", "y": "#10", "j": "#10", "z": "#10", "k": "#10", "r": "#10"}
+ if "g17" in planes:
+ scale["z"] = "#11"
+ scale["k"] = "#11"
+ if "g18" in planes:
+ scale["y"] = "#11"
+ scale["j"] = "#11"
+ if "g19" in planes:
+ scale["x"] = "#11"
+ scale["i"] = "#11"
+ # Add a scale
+ if "a" in coords:
+ gcode += "#12 = 1 (A axis scale)\n"
+ scale["a"] = "#12"
+
+ # Add feed parametrization
+ for f in feeds:
+ gcode += "{} = {:f} (Feed definition)\n".format(feeds[f], f)
+
+ # Parameterize Gcode
+ for s in self.gcode.split("\n"):
+ # feed replace :
+ r = re.search(r"(?i)(F)\s*(-?)\s*(\d*\.?\d*)", s)
+ if r and len(r.group(3)) > 0:
+ s = re.sub(r"(?i)(F)\s*(-?)\s*(\d*\.?\d*)", "F [{}]".format(feeds[float(r.group(2) + r.group(3))]), s)
+ # Coords XYZA replace
+ for c in "xyza":
+ r = re.search(r"(?i)((" + c + r")\s*(-?)\s*(\d*\.?\d*))", s)
+ if r and len(r.group(4)) > 0:
+ s = re.sub(r"(?i)(" + c + r")\s*((-?)\s*(\d*\.?\d*))", r"\1[\2*{}+{}]".format(scale[c], offset[c]), s)
+
+ # Coords IJKR replace
+ for c in "ijkr":
+ r = re.search(r"(?i)((" + c + r")\s*(-?)\s*(\d*\.?\d*))", s)
+ if r and len(r.group(4)) > 0:
+ s = re.sub(r"(?i)(" + c + r")\s*((-?)\s*(\d*\.?\d*))", r"\1[\2*{}]".format(scale[c]), s)
+
+ gcode += s + "\n"
+
+ self.gcode = gcode
+
+ def round_coordinates(self, parameters):
+ try:
+ round_ = int(parameters)
+ except:
+ self.error("Bad parameters for round. Round should be an integer! \n(Parameters: '{}')".format(parameters), "error")
+ gcode = ""
+ for s in self.gcode.split("\n"):
+ for a in "xyzijkaf":
+ r = re.search(r"(?i)(" + a + r")\s*(-?\s*(\d*\.?\d*))", s)
+ if r:
+
+ if r.group(2) != "":
+ s = re.sub(
+ r"(?i)(" + a + r")\s*(-?)\s*(\d*\.?\d*)",
+ (r"\1 %0." + str(round_) + "f" if round_ > 0 else r"\1 %d") % round(float(r.group(2)), round_),
+ s)
+ gcode += s + "\n"
+ self.gcode = gcode
+
+ def scale(self, parameters):
+ parameters = parameters.split(",")
+ scale = [1., 1., 1., 1.]
+ try:
+ for i in range(len(parameters)):
+ if float(parameters[i]) == 0:
+ self.error("Bad parameters for scale. Scale should not be 0 at any axis! \n(Parameters: '{}')".format(parameters), "error")
+ scale[i] = float(parameters[i])
+ except:
+ self.error("Bad parameters for scale.\n(Parameters: '{}')".format(parameters), "error")
+ self.transform([0, 0, 0, 0], scale)
+
+ def move(self, parameters):
+ parameters = parameters.split(",")
+ move = [0., 0., 0., 0.]
+ try:
+ for i in range(len(parameters)):
+ move[i] = float(parameters[i])
+ except:
+ self.error("Bad parameters for move.\n(Parameters: '{}')".format(parameters), "error")
+ self.transform(move, [1., 1., 1., 1.])
+
+ def flip_axis(self, parameters):
+ parameters = parameters.lower()
+ axis = {"x": 1., "y": 1., "z": 1., "a": 1.}
+ for p in parameters:
+ if p in [",", " ", " ", "\r", "'", '"']:
+ continue
+ if p not in ["x", "y", "z", "a"]:
+ self.error("Bad parameters for flip_axis. Parameter should be string consists of 'xyza' \n(Parameters: '{}')".format(parameters), "error")
+ axis[p] = -axis[p]
+ self.scale("{:f},{:f},{:f},{:f}".format(axis["x"], axis["y"], axis["z"], axis["a"]))
+
+
+################################################################################
+# Polygon class
+################################################################################
+class Polygon(object):
+ def __init__(self, polygon=None):
+ self.polygon = [] if polygon is None else polygon[:]
+
+ def move(self, x, y):
+ for i in range(len(self.polygon)):
+ for j in range(len(self.polygon[i])):
+ self.polygon[i][j][0] += x
+ self.polygon[i][j][1] += y
+
+ def bounds(self):
+ minx = 1e400
+ miny = 1e400
+ maxx = -1e400
+ maxy = -1e400
+ for poly in self.polygon:
+ for p in poly:
+ if minx > p[0]:
+ minx = p[0]
+ if miny > p[1]:
+ miny = p[1]
+ if maxx < p[0]:
+ maxx = p[0]
+ if maxy < p[1]:
+ maxy = p[1]
+ return minx * 1, miny * 1, maxx * 1, maxy * 1
+
+ def width(self):
+ b = self.bounds()
+ return b[2] - b[0]
+
+ def rotate_(self, sin, cos):
+ self.polygon = [
+ [
+ [point[0] * cos - point[1] * sin, point[0] * sin + point[1] * cos] for point in subpoly
+ ]
+ for subpoly in self.polygon
+ ]
+
+ def rotate(self, a):
+ cos = math.cos(a)
+ sin = math.sin(a)
+ self.rotate_(sin, cos)
+
+ def drop_into_direction(self, direction, surface):
+ # Polygon is a list of simple polygons
+ # Surface is a polygon + line y = 0
+ # Direction is [dx,dy]
+ if len(self.polygon) == 0 or len(self.polygon[0]) == 0:
+ return
+ if direction[0] ** 2 + direction[1] ** 2 < 1e-10:
+ return
+ direction = normalize(direction)
+ sin = direction[0]
+ cos = -direction[1]
+ self.rotate_(-sin, cos)
+ surface.rotate_(-sin, cos)
+ self.drop_down(surface, zerro_plane=False)
+ self.rotate_(sin, cos)
+ surface.rotate_(sin, cos)
+
+ def centroid(self):
+ centroids = []
+ sa = 0
+ for poly in self.polygon:
+ cx = 0
+ cy = 0
+ a = 0
+ for i in range(len(poly)):
+ [x1, y1] = poly[i - 1]
+ [x2, y2] = poly[i]
+ cx += (x1 + x2) * (x1 * y2 - x2 * y1)
+ cy += (y1 + y2) * (x1 * y2 - x2 * y1)
+ a += (x1 * y2 - x2 * y1)
+ a *= 3.
+ if abs(a) > 0:
+ cx /= a
+ cy /= a
+ sa += abs(a)
+ centroids += [[cx, cy, a]]
+ if sa == 0:
+ return [0., 0.]
+ cx = 0
+ cy = 0
+ for c in centroids:
+ cx += c[0] * c[2]
+ cy += c[1] * c[2]
+ cx /= sa
+ cy /= sa
+ return [cx, cy]
+
+ def drop_down(self, surface, zerro_plane=True):
+ # Polygon is a list of simple polygons
+ # Surface is a polygon + line y = 0
+ # Down means min y (0,-1)
+ if len(self.polygon) == 0 or len(self.polygon[0]) == 0:
+ return
+ # Get surface top point
+ top = surface.bounds()[3]
+ if zerro_plane:
+ top = max(0, top)
+ # Get polygon bottom point
+ bottom = self.bounds()[1]
+ self.move(0, top - bottom + 10)
+ # Now get shortest distance from surface to polygon in positive x=0 direction
+ # Such distance = min(distance(vertex, edge)...) where edge from surface and
+ # vertex from polygon and vice versa...
+ dist = 1e300
+ for poly in surface.polygon:
+ for i in range(len(poly)):
+ for poly1 in self.polygon:
+ for i1 in range(len(poly1)):
+ st = poly[i - 1]
+ end = poly[i]
+ vertex = poly1[i1]
+ if st[0] <= vertex[0] <= end[0] or end[0] <= vertex[0] <= st[0]:
+ if st[0] == end[0]:
+ d = min(vertex[1] - st[1], vertex[1] - end[1])
+ else:
+ d = vertex[1] - st[1] - (end[1] - st[1]) * (vertex[0] - st[0]) / (end[0] - st[0])
+ if dist > d:
+ dist = d
+ # and vice versa just change the sign because vertex now under the edge
+ st = poly1[i1 - 1]
+ end = poly1[i1]
+ vertex = poly[i]
+ if st[0] <= vertex[0] <= end[0] or end[0] <= vertex[0] <= st[0]:
+ if st[0] == end[0]:
+ d = min(- vertex[1] + st[1], -vertex[1] + end[1])
+ else:
+ d = - vertex[1] + st[1] + (end[1] - st[1]) * (vertex[0] - st[0]) / (end[0] - st[0])
+ if dist > d:
+ dist = d
+
+ if zerro_plane and dist > 10 + top:
+ dist = 10 + top
+ self.move(0, -dist)
+
+ def draw(self, color="#075", width=.1, group=None):
+ csp = [csp_subpath_line_to([], poly + [poly[0]]) for poly in self.polygon]
+ draw_csp(csp, width=width, group=group)
+
+ def add(self, add):
+ if type(add) == type([]):
+ self.polygon += add[:]
+ else:
+ self.polygon += add.polygon[:]
+
+ def point_inside(self, p):
+ inside = False
+ for poly in self.polygon:
+ for i in range(len(poly)):
+ st = poly[i - 1]
+ end = poly[i]
+ if p == st or p == end:
+ return True # point is a vertex = point is on the edge
+ if st[0] > end[0]:
+ st, end = end, st # This will be needed to check that edge if open only at right end
+ c = (p[1] - st[1]) * (end[0] - st[0]) - (end[1] - st[1]) * (p[0] - st[0])
+ if st[0] <= p[0] < end[0]:
+ if c < 0:
+ inside = not inside
+ elif c == 0:
+ return True # point is on the edge
+ elif st[0] == end[0] == p[0] and (st[1] <= p[1] <= end[1] or end[1] <= p[1] <= st[1]): # point is on the edge
+ return True
+ return inside
+
+ def hull(self):
+ # Add vertices at all self intersection points.
+ hull = []
+ for i1 in range(len(self.polygon)):
+ poly1 = self.polygon[i1]
+ poly_ = []
+ for j1 in range(len(poly1)):
+ s = poly1[j1 - 1]
+ e = poly1[j1]
+ poly_ += [s]
+
+ # Check self intersections
+ for j2 in range(j1 + 1, len(poly1)):
+ s1 = poly1[j2 - 1]
+ e1 = poly1[j2]
+ int_ = line_line_intersection_points(s, e, s1, e1)
+ for p in int_:
+ if point_to_point_d2(p, s) > 0.000001 and point_to_point_d2(p, e) > 0.000001:
+ poly_ += [p]
+ # Check self intersections with other polys
+ for i2 in range(len(self.polygon)):
+ if i1 == i2:
+ continue
+ poly2 = self.polygon[i2]
+ for j2 in range(len(poly2)):
+ s1 = poly2[j2 - 1]
+ e1 = poly2[j2]
+ int_ = line_line_intersection_points(s, e, s1, e1)
+ for p in int_:
+ if point_to_point_d2(p, s) > 0.000001 and point_to_point_d2(p, e) > 0.000001:
+ poly_ += [p]
+ hull += [poly_]
+ # Create the dictionary containing all edges in both directions
+ edges = {}
+ for poly in self.polygon:
+ for i in range(len(poly)):
+ s = tuple(poly[i - 1])
+ e = tuple(poly[i])
+ if point_to_point_d2(e, s) < 0.000001:
+ continue
+ break_s = False
+ break_e = False
+ for p in edges:
+ if point_to_point_d2(p, s) < 0.000001:
+ break_s = True
+ s = p
+ if point_to_point_d2(p, e) < 0.000001:
+ break_e = True
+ e = p
+ if break_s and break_e:
+ break
+ l = point_to_point_d(s, e)
+ if not break_s and not break_e:
+ edges[s] = [[s, e, l]]
+ edges[e] = [[e, s, l]]
+ else:
+ if e in edges:
+ for edge in edges[e]:
+ if point_to_point_d2(edge[1], s) < 0.000001:
+ break
+ if point_to_point_d2(edge[1], s) > 0.000001:
+ edges[e] += [[e, s, l]]
+ else:
+ edges[e] = [[e, s, l]]
+ if s in edges:
+ for edge in edges[s]:
+ if point_to_point_d2(edge[1], e) < 0.000001:
+ break
+ if point_to_point_d2(edge[1], e) > 0.000001:
+ edges[s] += [[s, e, l]]
+ else:
+ edges[s] = [[s, e, l]]
+
+ def angle_quadrant(sin, cos):
+ # quadrants are (0,pi/2], (pi/2,pi], (pi,3*pi/2], (3*pi/2, 2*pi], i.e. 0 is in the 4-th quadrant
+ if sin > 0 and cos >= 0:
+ return 1
+ if sin >= 0 and cos < 0:
+ return 2
+ if sin < 0 and cos <= 0:
+ return 3
+ if sin <= 0 and cos > 0:
+ return 4
+
+ def angle_is_less(sin, cos, sin1, cos1):
+ # 0 = 2*pi is the largest angle
+ if [sin1, cos1] == [0, 1]:
+ return True
+ if [sin, cos] == [0, 1]:
+ return False
+ if angle_quadrant(sin, cos) > angle_quadrant(sin1, cos1):
+ return False
+ if angle_quadrant(sin, cos) < angle_quadrant(sin1, cos1):
+ return True
+ if sin >= 0 and cos > 0:
+ return sin < sin1
+ if sin > 0 and cos <= 0:
+ return sin > sin1
+ if sin <= 0 and cos < 0:
+ return sin > sin1
+ if sin < 0 and cos >= 0:
+ return sin < sin1
+
+ def get_closes_edge_by_angle(edges, last):
+ # Last edge is normalized vector of the last edge.
+ min_angle = [0, 1]
+ next = last
+ last_edge = [(last[0][0] - last[1][0]) / last[2], (last[0][1] - last[1][1]) / last[2]]
+ for p in edges:
+
+ cur = [(p[1][0] - p[0][0]) / p[2], (p[1][1] - p[0][1]) / p[2]]
+ cos = dot(cur, last_edge)
+ sin = cross(cur, last_edge)
+
+ if angle_is_less(sin, cos, min_angle[0], min_angle[1]):
+ min_angle = [sin, cos]
+ next = p
+
+ return next
+
+ # Join edges together into new polygon cutting the vertexes inside new polygon
+ self.polygon = []
+ len_edges = sum([len(edges[p]) for p in edges])
+ loops = 0
+
+ while len(edges) > 0:
+ poly = []
+ if loops > len_edges:
+ raise ValueError("Hull error")
+ loops += 1
+ # Find left most vertex.
+ start = (1e100, 1)
+ for edge in edges:
+ start = min(start, min(edges[edge]))
+ last = [(start[0][0] - 1, start[0][1]), start[0], 1]
+ first_run = True
+ loops1 = 0
+ while last[1] != start[0] or first_run:
+ first_run = False
+ if loops1 > len_edges:
+ raise ValueError("Hull error")
+ loops1 += 1
+ next = get_closes_edge_by_angle(edges[last[1]], last)
+
+ last = next
+ poly += [list(last[0])]
+ self.polygon += [poly]
+ # Remove all edges that are intersects new poly (any vertex inside new poly)
+ poly_ = Polygon([poly])
+ for p in edges.keys()[:]:
+ if poly_.point_inside(list(p)):
+ del edges[p]
+ self.draw(color="Green", width=1)
+
+
+################################################################################
+#
+# Gcodetools class
+#
+################################################################################
+
+class Gcodetools(inkex.EffectExtension):
+ multi_inx = True # XXX Remove this after refactoring
+
+ def export_gcode(self, gcode, no_headers=False):
+ if self.options.postprocessor != "" or self.options.postprocessor_custom != "":
+ postprocessor = Postprocessor(self.error)
+ postprocessor.gcode = gcode
+ if self.options.postprocessor != "":
+ postprocessor.process(self.options.postprocessor)
+ if self.options.postprocessor_custom != "":
+ postprocessor.process(self.options.postprocessor_custom)
+
+ if not no_headers:
+ postprocessor.gcode = self.header + postprocessor.gcode + self.footer
+
+ with open(os.path.join(self.options.directory, self.options.file), "w") as f:
+ f.write(postprocessor.gcode)
+
+ ################################################################################
+ # In/out paths:
+ # TODO move it to the bottom
+ ################################################################################
+ def tab_plasma_prepare_path(self):
+ self.get_info_plus()
+
+ def add_arc(sp1, sp2, end=False, l=10., r=10.):
+ if not end:
+ n = csp_normalized_normal(sp1, sp2, 0.)
+ return csp_reverse([arc_from_s_r_n_l(sp1[1], r, n, -l)])[0]
+ else:
+ n = csp_normalized_normal(sp1, sp2, 1.)
+ return arc_from_s_r_n_l(sp2[1], r, n, l)
+
+ def add_normal(sp1, sp2, end=False, l=10., r=10.):
+ # r is needed only for be compatible with add_arc
+ if not end:
+ n = csp_normalized_normal(sp1, sp2, 0.)
+ p = [n[0] * l + sp1[1][0], n[1] * l + sp1[1][1]]
+ return csp_subpath_line_to([], [p, sp1[1]])
+ else:
+ n = csp_normalized_normal(sp1, sp2, 1.)
+ p = [n[0] * l + sp2[1][0], n[1] * l + sp2[1][1]]
+ return csp_subpath_line_to([], [sp2[1], p])
+
+ def add_tangent(sp1, sp2, end=False, l=10., r=10.):
+ # r is needed only for be compatible with add_arc
+ if not end:
+ n = csp_normalized_slope(sp1, sp2, 0.)
+ p = [-n[0] * l + sp1[1][0], -n[1] * l + sp1[1][1]]
+ return csp_subpath_line_to([], [p, sp1[1]])
+ else:
+ n = csp_normalized_slope(sp1, sp2, 1.)
+ p = [n[0] * l + sp2[1][0], n[1] * l + sp2[1][1]]
+ return csp_subpath_line_to([], [sp2[1], p])
+
+ if not self.options.in_out_path and not self.options.plasma_prepare_corners and self.options.in_out_path_do_not_add_reference_point:
+ self.error("Warning! Extension is not said to do anything! Enable one of Create in-out paths or Prepare corners checkboxes or disable Do not add in-out reference point!")
+ return
+
+ # Add in-out-reference point if there is no one yet.
+ if ((len(self.in_out_reference_points) == 0 and self.options.in_out_path
+ or not self.options.in_out_path and not self.options.plasma_prepare_corners)
+ and not self.options.in_out_path_do_not_add_reference_point):
+ self.options.orientation_points_count = "in-out reference point"
+ #self.orientation()
+
+ if self.options.in_out_path or self.options.plasma_prepare_corners:
+ self.set_markers()
+ add_func = {"Round": add_arc, "Perpendicular": add_normal, "Tangent": add_tangent}[self.options.in_out_path_type]
+ if self.options.in_out_path_type == "Round" and self.options.in_out_path_len > self.options.in_out_path_radius * 3 / 2 * math.pi:
+ self.error("In-out len is to big for in-out radius will cropp it to be r*3/2*pi!")
+
+ if self.selected_paths == {} and self.options.auto_select_paths:
+ self.selected_paths = self.paths
+ self.error("No paths are selected! Trying to work on all available paths.")
+
+ if self.selected_paths == {}:
+ self.error("Nothing is selected. Please select something.")
+ a = self.options.plasma_prepare_corners_tolerance
+ corner_tolerance = cross([1., 0.], [math.cos(a), math.sin(a)])
+
+ for layer in self.layers:
+ if layer in self.selected_paths:
+ max_dist = self.transform_scalar(self.options.in_out_path_point_max_dist, layer, reverse=True)
+ l = self.transform_scalar(self.options.in_out_path_len, layer, reverse=True)
+ plasma_l = self.transform_scalar(self.options.plasma_prepare_corners_distance, layer, reverse=True)
+ r = self.transform_scalar(self.options.in_out_path_radius, layer, reverse=True)
+ l = min(l, r * 3 / 2 * math.pi)
+
+ for path in self.selected_paths[layer]:
+ csp = self.apply_transforms(path, path.path.to_superpath())
+ csp = csp_remove_zero_segments(csp)
+ res = []
+
+ for subpath in csp:
+ # Find closes point to in-out reference point
+ # If subpath is open skip this step
+ if self.options.in_out_path:
+ # split and reverse path for further add in-out points
+ if point_to_point_d2(subpath[0][1], subpath[-1][1]) < 1.e-10:
+ d = [1e100, 1, 1, 1.]
+ for p in self.in_out_reference_points:
+ d1 = csp_to_point_distance([subpath], p, dist_bounds=[0, max_dist])
+ if d1[0] < d[0]:
+ d = d1[:]
+ p_ = p
+ if d[0] < max_dist ** 2:
+ # Lets find is there any angles near this point to put in-out path in
+ # the angle if it's possible
+ # remove last node to make iterations easier
+ subpath[0][0] = subpath[-1][0]
+ del subpath[-1]
+ max_cross = [-1e100, None]
+ for j in range(len(subpath)):
+ sp1 = subpath[j - 2]
+ sp2 = subpath[j - 1]
+ sp3 = subpath[j]
+ if point_to_point_d2(sp2[1], p_) < max_dist ** 2:
+ s1 = csp_normalized_slope(sp1, sp2, 1.)
+ s2 = csp_normalized_slope(sp2, sp3, 0.)
+ max_cross = max(max_cross, [cross(s1, s2), j - 1])
+ # return back last point
+ subpath.append(subpath[0])
+ if max_cross[1] is not None and max_cross[0] > corner_tolerance:
+ # there's an angle near the point
+ j = max_cross[1]
+ if j < 0:
+ j -= 1
+ if j != 0:
+ subpath = csp_concat_subpaths(subpath[j:], subpath[:j + 1])
+ else:
+ # have to cut path's segment
+ d, i, j, t = d
+ sp1, sp2, sp3 = csp_split(subpath[j - 1], subpath[j], t)
+ subpath = csp_concat_subpaths([sp2, sp3], subpath[j:], subpath[:j], [sp1, sp2])
+
+ if self.options.plasma_prepare_corners:
+ # prepare corners
+ # find corners and add some nodes
+ # corner at path's start/end is ignored
+ res_ = [subpath[0]]
+ for sp2, sp3 in zip(subpath[1:], subpath[2:]):
+ sp1 = res_[-1]
+ s1 = csp_normalized_slope(sp1, sp2, 1.)
+ s2 = csp_normalized_slope(sp2, sp3, 0.)
+ if cross(s1, s2) > corner_tolerance:
+ # got a corner to process
+ S1 = P(s1)
+ S2 = P(s2)
+ N = (S1 - S2).unit() * plasma_l
+ SP2 = P(sp2[1])
+ P1 = (SP2 + N)
+ res_ += [
+ [sp2[0], sp2[1], (SP2 + S1 * plasma_l).to_list()],
+ [(P1 - N.ccw() / 2).to_list(), P1.to_list(), (P1 + N.ccw() / 2).to_list()],
+ [(SP2 - S2 * plasma_l).to_list(), sp2[1], sp2[2]]
+ ]
+ else:
+ res_ += [sp2]
+ res_ += [sp3]
+ subpath = res_
+ if self.options.in_out_path:
+ # finally add let's add in-out paths...
+ subpath = csp_concat_subpaths(
+ add_func(subpath[0], subpath[1], False, l, r),
+ subpath,
+ add_func(subpath[-2], subpath[-1], True, l, r)
+ )
+
+ res += [subpath]
+
+ if self.options.in_out_path_replace_original_path:
+ path.path = CubicSuperPath(self.apply_transforms(path, res, True))
+ else:
+ draw_csp(res, width=1, style=MARKER_STYLE["in_out_path_style"])
+
+ def add_arguments(self, pars):
+ add_argument = pars.add_argument
+ add_argument("-d", "--directory", default="/home/", help="Directory for gcode file")
+ add_argument("-f", "--filename", dest="file", default="-1.0", help="File name")
+ add_argument("--add-numeric-suffix-to-filename", type=inkex.Boolean, default=True, help="Add numeric suffix to filename")
+ add_argument("--Zscale", type=float, default="1.0", help="Scale factor Z")
+ add_argument("--Zoffset", type=float, default="0.0", help="Offset along Z")
+ add_argument("-s", "--Zsafe", type=float, default="0.5", help="Z above all obstacles")
+ add_argument("-z", "--Zsurface", type=float, default="0.0", help="Z of the surface")
+ add_argument("-c", "--Zdepth", type=float, default="-0.125", help="Z depth of cut")
+ add_argument("--Zstep", type=float, default="-0.125", help="Z step of cutting")
+ add_argument("-p", "--feed", type=float, default="4.0", help="Feed rate in unit/min")
+
+ add_argument("--biarc-tolerance", type=float, default="1", help="Tolerance used when calculating biarc interpolation.")
+ add_argument("--biarc-max-split-depth", type=int, default="4", help="Defines maximum depth of splitting while approximating using biarcs.")
+ add_argument("--path-to-gcode-order", default="path by path", help="Defines cutting order path by path or layer by layer.")
+ add_argument("--path-to-gcode-depth-function", default="zd", help="Path to gcode depth function.")
+ add_argument("--path-to-gcode-sort-paths", type=inkex.Boolean, default=True, help="Sort paths to reduce rapid distance.")
+ add_argument("--comment-gcode", default="", help="Comment Gcode")
+ add_argument("--comment-gcode-from-properties", type=inkex.Boolean, default=False, help="Get additional comments from Object Properties")
+
+ add_argument("--tool-diameter", type=float, default="3", help="Tool diameter used for area cutting")
+ add_argument("--max-area-curves", type=int, default="100", help="Maximum area curves for each area")
+ add_argument("--area-inkscape-radius", type=float, default="0", help="Area curves overlapping (depends on tool diameter [0, 0.9])")
+ add_argument("--area-tool-overlap", type=float, default="-10", help="Radius for preparing curves using inkscape")
+ add_argument("--unit", default="G21 (All units in mm)", help="Units")
+ add_argument("--active-tab", type=self.arg_method('tab'), default=self.tab_help, help="Defines which tab is active")
+
+ add_argument("--area-fill-angle", type=float, default="0", help="Fill area with lines heading this angle")
+ add_argument("--area-fill-shift", type=float, default="0", help="Shift the lines by tool d * shift")
+ add_argument("--area-fill-method", default="zig-zag", help="Filling method either zig-zag or spiral")
+
+ add_argument("--area-find-artefacts-diameter", type=float, default="1", help="Artefacts seeking radius")
+ add_argument("--area-find-artefacts-action", default="mark with an arrow", help="Artefacts action type")
+
+ add_argument("--auto_select_paths", type=inkex.Boolean, default=True, help="Select all paths if nothing is selected.")
+
+ add_argument("--loft-distances", default="10", help="Distances between paths.")
+ add_argument("--loft-direction", default="crosswise", help="Direction of loft's interpolation.")
+ add_argument("--loft-interpolation-degree", type=float, default="2", help="Which interpolation use to loft the paths smooth interpolation or staright.")
+
+ add_argument("--min-arc-radius", type=float, default=".1", help="All arc having radius less than minimum will be considered as straight line")
+
+ add_argument("--engraving-sharp-angle-tollerance", type=float, default="150", help="All angles thar are less than engraving-sharp-angle-tollerance will be thought sharp")
+ add_argument("--engraving-max-dist", type=float, default="10", help="Distance from original path where engraving is not needed (usually it's cutting tool diameter)")
+ add_argument("--engraving-newton-iterations", type=int, default="4", help="Number of sample points used to calculate distance")
+ add_argument("--engraving-draw-calculation-paths", type=inkex.Boolean, default=False, help="Draw additional graphics to debug engraving path")
+ add_argument("--engraving-cutter-shape-function", default="w", help="Cutter shape function z(w). Ex. cone: w. ")
+
+ add_argument("--lathe-width", type=float, default=10., help="Lathe width")
+ add_argument("--lathe-fine-cut-width", type=float, default=1., help="Fine cut width")
+ add_argument("--lathe-fine-cut-count", type=int, default=1., help="Fine cut count")
+ add_argument("--lathe-create-fine-cut-using", default="Move path", help="Create fine cut using")
+ add_argument("--lathe-x-axis-remap", default="X", help="Lathe X axis remap")
+ add_argument("--lathe-z-axis-remap", default="Z", help="Lathe Z axis remap")
+
+ add_argument("--lathe-rectangular-cutter-width", type=float, default="4", help="Rectangular cutter width")
+
+ add_argument("--create-log", type=inkex.Boolean, dest="log_create_log", default=False, help="Create log files")
+ add_argument("--log-filename", default='', help="Create log files")
+
+ add_argument("--orientation-points-count", default="2", help="Orientation points count")
+ add_argument("--tools-library-type", default='cylinder cutter', help="Create tools definition")
+
+ add_argument("--dxfpoints-action", default='replace', help="dxfpoint sign toggle")
+
+ add_argument("--help-language", default='http://www.cnc-club.ru/forum/viewtopic.php?f=33&t=35', help="Open help page in webbrowser.")
+
+ add_argument("--offset-radius", type=float, default=10., help="Offset radius")
+ add_argument("--offset-step", type=float, default=10., help="Offset step")
+ add_argument("--offset-draw-clippend-path", type=inkex.Boolean, default=False, help="Draw clipped path")
+ add_argument("--offset-just-get-distance", type=inkex.Boolean, default=False, help="Don't do offset just get distance")
+
+ add_argument("--postprocessor", default='', help="Postprocessor command.")
+ add_argument("--postprocessor-custom", default='', help="Postprocessor custom command.")
+
+ add_argument("--graffiti-max-seg-length", type=float, default=1., help="Graffiti maximum segment length.")
+ add_argument("--graffiti-min-radius", type=float, default=10., help="Graffiti minimal connector's radius.")
+ add_argument("--graffiti-start-pos", default="(0;0)", help="Graffiti Start position (x;y).")
+ add_argument("--graffiti-create-linearization-preview", type=inkex.Boolean, default=True, help="Graffiti create linearization preview.")
+ add_argument("--graffiti-create-preview", type=inkex.Boolean, default=True, help="Graffiti create preview.")
+ add_argument("--graffiti-preview-size", type=int, default=800, help="Graffiti preview's size.")
+ add_argument("--graffiti-preview-emmit", type=int, default=800, help="Preview's paint emmit (pts/s).")
+
+ add_argument("--in-out-path", type=inkex.Boolean, default=True, help="Create in-out paths")
+ add_argument("--in-out-path-do-not-add-reference-point", type=inkex.Boolean, default=False, help="Just add reference in-out point")
+ add_argument("--in-out-path-point-max-dist", type=float, default=10., help="In-out path max distance to reference point")
+ add_argument("--in-out-path-type", default="Round", help="In-out path type")
+ add_argument("--in-out-path-len", type=float, default=10., help="In-out path length")
+ add_argument("--in-out-path-replace-original-path", type=inkex.Boolean, default=False, help="Replace original path")
+ add_argument("--in-out-path-radius", type=float, default=10., help="In-out path radius for round path")
+
+ add_argument("--plasma-prepare-corners", type=inkex.Boolean, default=True, help="Prepare corners")
+ add_argument("--plasma-prepare-corners-distance", type=float, default=10., help="Stepout distance for corners")
+ add_argument("--plasma-prepare-corners-tolerance", type=float, default=10., help="Maximum angle for corner (0-180 deg)")
+
+ def __init__(self):
+ super(Gcodetools, self).__init__()
+ self.default_tool = {
+ "name": "Default tool",
+ "id": "default tool",
+ "diameter": 10.,
+ "shape": "10",
+ "penetration angle": 90.,
+ "penetration feed": 100.,
+ "depth step": 1.,
+ "feed": 400.,
+ "in trajectotry": "",
+ "out trajectotry": "",
+ "gcode before path": "",
+ "gcode after path": "",
+ "sog": "",
+ "spinlde rpm": "",
+ "CW or CCW": "",
+ "tool change gcode": " ",
+ "4th axis meaning": " ",
+ "4th axis scale": 1.,
+ "4th axis offset": 0.,
+ "passing feed": "800",
+ "fine feed": "800",
+ }
+ self.tools_field_order = [
+ 'name',
+ 'id',
+ 'diameter',
+ 'feed',
+ 'shape',
+ 'penetration angle',
+ 'penetration feed',
+ "passing feed",
+ 'depth step',
+ "in trajectotry",
+ "out trajectotry",
+ "gcode before path",
+ "gcode after path",
+ "sog",
+ "spinlde rpm",
+ "CW or CCW",
+ "tool change gcode",
+ ]
+
+ def parse_curve(self, p, layer, w=None, f=None):
+ c = []
+ if len(p) == 0:
+ return []
+ p = self.transform_csp(p, layer)
+
+ # Sort to reduce Rapid distance
+ k = list(range(1, len(p)))
+ keys = [0]
+ while len(k) > 0:
+ end = p[keys[-1]][-1][1]
+ dist = None
+ for i in range(len(k)):
+ start = p[k[i]][0][1]
+ dist = max((-((end[0] - start[0]) ** 2 + (end[1] - start[1]) ** 2), i), dist)
+ keys += [k[dist[1]]]
+ del k[dist[1]]
+ for k in keys:
+ subpath = p[k]
+ c += [[[subpath[0][1][0], subpath[0][1][1]], 'move', 0, 0]]
+ for i in range(1, len(subpath)):
+ sp1 = [[subpath[i - 1][j][0], subpath[i - 1][j][1]] for j in range(3)]
+ sp2 = [[subpath[i][j][0], subpath[i][j][1]] for j in range(3)]
+ c += biarc(sp1, sp2, 0, 0) if w is None else biarc(sp1, sp2, -f(w[k][i - 1]), -f(w[k][i]))
+ c += [[[subpath[-1][1][0], subpath[-1][1][1]], 'end', 0, 0]]
+ return c
+
+ ################################################################################
+ # Draw csp
+ ################################################################################
+
+ def draw_csp(self, csp, layer=None, group=None, fill='none', stroke='#178ade', width=0.354, style=None):
+ if layer is not None:
+ csp = self.transform_csp(csp, layer, reverse=True)
+ if group is None and layer is None:
+ group = self.document.getroot()
+ elif group is None and layer is not None:
+ group = layer
+ csp = self.apply_transforms(group, csp, reverse=True)
+ if style is not None:
+ return draw_csp(csp, group=group, style=style)
+ else:
+ return draw_csp(csp, group=group, fill=fill, stroke=stroke, width=width)
+
+ def draw_curve(self, curve, layer, group=None, style=MARKER_STYLE["biarc_style"]):
+ self.set_markers()
+
+ for i in [0, 1]:
+ sid = 'biarc{}_r'.format(i)
+ style[sid] = style['biarc{}'.format(i)].copy()
+ style[sid]["marker-start"] = "url(#DrawCurveMarker_r)"
+ del style[sid]["marker-end"]
+
+ if group is None:
+ group = self.layers[min(1, len(self.layers) - 1)].add(Group(gcodetools="Preview group"))
+ if not hasattr(self, "preview_groups"):
+ self.preview_groups = {layer: group}
+ elif layer not in self.preview_groups:
+ self.preview_groups[layer] = group
+ group = self.preview_groups[layer]
+
+ s = ''
+ arcn = 0
+
+ transform = self.get_transforms(group)
+ if transform:
+ transform = self.reverse_transform(transform)
+ transform = str(Transform(transform))
+
+ a = [0., 0.]
+ b = [1., 0.]
+ c = [0., 1.]
+ k = (b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1])
+ a = self.transform(a, layer, True)
+ b = self.transform(b, layer, True)
+ c = self.transform(c, layer, True)
+ if ((b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1])) * k > 0:
+ reverse_angle = 1
+ else:
+ reverse_angle = -1
+ for sk in curve:
+ si = sk[:]
+ si[0] = self.transform(si[0], layer, True)
+ si[2] = self.transform(si[2], layer, True) if type(si[2]) == type([]) and len(si[2]) == 2 else si[2]
+
+ if s != '':
+ if s[1] == 'line':
+ elem = group.add(PathElement(gcodetools="Preview"))
+ elem.transform = transform
+ elem.style = style['line']
+ elem.path = 'M {},{} L {},{}'.format(s[0][0], s[0][1], si[0][0], si[0][1])
+ elif s[1] == 'arc':
+ arcn += 1
+ sp = s[0]
+ c = s[2]
+ s[3] = s[3] * reverse_angle
+
+ a = ((P(si[0]) - P(c)).angle() - (P(s[0]) - P(c)).angle()) % TAU # s[3]
+ if s[3] * a < 0:
+ if a > 0:
+ a = a - TAU
+ else:
+ a = TAU + a
+ r = math.sqrt((sp[0] - c[0]) ** 2 + (sp[1] - c[1]) ** 2)
+ a_st = (math.atan2(sp[0] - c[0], - (sp[1] - c[1])) - math.pi / 2) % (math.pi * 2)
+ if a > 0:
+ a_end = a_st + a
+ st = style['biarc{}'.format(arcn % 2)]
+ else:
+ a_end = a_st * 1
+ a_st = a_st + a
+ st = style['biarc{}_r'.format(arcn % 2)]
+
+ elem = group.add(PathElement.arc(c, r, start=a_st, end=a_end,
+ open=True, gcodetools="Preview"))
+ elem.transform = transform
+ elem.style = st
+
+ s = si
+
+ def check_dir(self):
+ print_("Checking directory: '{}'".format(self.options.directory))
+ if os.path.isdir(self.options.directory):
+ if os.path.isfile(os.path.join(self.options.directory, 'header')):
+ with open(os.path.join(self.options.directory, 'header')) as f:
+ self.header = f.read()
+ else:
+ self.header = defaults['header']
+ if os.path.isfile(os.path.join(self.options.directory, 'footer')):
+ with open(os.path.join(self.options.directory, 'footer')) as f:
+ self.footer = f.read()
+ else:
+ self.footer = defaults['footer']
+ self.header += self.options.unit + "\n"
+ else:
+ self.error("Directory does not exist! Please specify existing directory at Preferences tab!", "error")
+ return False
+
+ if self.options.add_numeric_suffix_to_filename:
+ dir_list = os.listdir(self.options.directory)
+ if "." in self.options.file:
+ r = re.match(r"^(.*)(\..*)$", self.options.file)
+ ext = r.group(2)
+ name = r.group(1)
+ else:
+ ext = ""
+ name = self.options.file
+ max_n = 0
+ for s in dir_list:
+ r = re.match(r"^{}_0*(\d+){}$".format(re.escape(name), re.escape(ext)), s)
+ if r:
+ max_n = max(max_n, int(r.group(1)))
+ filename = name + "_" + ("0" * (4 - len(str(max_n + 1))) + str(max_n + 1)) + ext
+ self.options.file = filename
+
+ try:
+ with open(os.path.join(self.options.directory, self.options.file), "w") as f:
+ pass
+ except:
+ self.error("Can not write to specified file!\n{}".format(os.path.join(self.options.directory, self.options.file)), "error")
+ return False
+ return True
+
+ ################################################################################
+ #
+ # Generate Gcode
+ # Generates Gcode on given curve.
+ #
+ # Curve definition [start point, type = {'arc','line','move','end'}, arc center, arc angle, end point, [zstart, zend]]
+ #
+ ################################################################################
+ def generate_gcode(self, curve, layer, depth):
+ Zauto_scale = self.Zauto_scale[layer]
+ tool = self.tools[layer][0]
+ g = ""
+
+ def c(c):
+ c = [c[i] if i < len(c) else None for i in range(6)]
+ if c[5] == 0:
+ c[5] = None
+ s = [" X", " Y", " Z", " I", " J", " K"]
+ s1 = ["", "", "", "", "", ""]
+ m = [1, 1, self.options.Zscale * Zauto_scale, 1, 1, self.options.Zscale * Zauto_scale]
+ a = [0, 0, self.options.Zoffset, 0, 0, 0]
+ r = ''
+ for i in range(6):
+ if c[i] is not None:
+ r += s[i] + ("{:f}".format(c[i] * m[i] + a[i])) + s1[i]
+ return r
+
+ def calculate_angle(a, current_a):
+ return min(
+ [abs(a - current_a % TAU + TAU), a + current_a - current_a % TAU + TAU],
+ [abs(a - current_a % TAU - TAU), a + current_a - current_a % TAU - TAU],
+ [abs(a - current_a % TAU), a + current_a - current_a % TAU])[1]
+
+ if len(curve) == 0:
+ return ""
+
+ try:
+ self.last_used_tool is None
+ except:
+ self.last_used_tool = None
+ print_("working on curve")
+ print_(curve)
+
+ if tool != self.last_used_tool:
+ g += ("(Change tool to {})\n".format(re.sub("\"'\\(\\)\\\\", " ", tool["name"]))) + tool["tool change gcode"] + "\n"
+
+ lg = 'G00'
+ zs = self.options.Zsafe
+ f = " F{:f}".format(tool['feed'])
+ current_a = 0
+ go_to_safe_distance = "G00" + c([None, None, zs]) + "\n"
+ penetration_feed = " F{}".format(tool['penetration feed'])
+ for i in range(1, len(curve)):
+ # Creating Gcode for curve between s=curve[i-1] and si=curve[i] start at s[0] end at s[4]=si[0]
+ s = curve[i - 1]
+ si = curve[i]
+ feed = f if lg not in ['G01', 'G02', 'G03'] else ''
+ if s[1] == 'move':
+ g += go_to_safe_distance + "G00" + c(si[0]) + "\n" + tool['gcode before path'] + "\n"
+ lg = 'G00'
+ elif s[1] == 'end':
+ g += go_to_safe_distance + tool['gcode after path'] + "\n"
+ lg = 'G00'
+ elif s[1] == 'line':
+ if tool['4th axis meaning'] == "tangent knife":
+ a = atan2(si[0][0] - s[0][0], si[0][1] - s[0][1])
+ a = calculate_angle(a, current_a)
+ g += "G01 A{}\n".format(a * tool['4th axis scale'] + tool['4th axis offset'])
+ current_a = a
+ if lg == "G00":
+ g += "G01" + c([None, None, s[5][0] + depth]) + penetration_feed + "(Penetrate)\n"
+ g += "G01" + c(si[0] + [s[5][1] + depth]) + feed + "\n"
+ lg = 'G01'
+ elif s[1] == 'arc':
+ r = [(s[2][0] - s[0][0]), (s[2][1] - s[0][1])]
+ if tool['4th axis meaning'] == "tangent knife":
+ if s[3] < 0: # CW
+ a1 = atan2(s[2][1] - s[0][1], -s[2][0] + s[0][0]) + math.pi
+ else: # CCW
+ a1 = atan2(-s[2][1] + s[0][1], s[2][0] - s[0][0]) + math.pi
+ a = calculate_angle(a1, current_a)
+ g += "G01 A{}\n".format(a * tool['4th axis scale'] + tool['4th axis offset'])
+ current_a = a
+ axis4 = " A{}".format((current_a + s[3]) * tool['4th axis scale'] + tool['4th axis offset'])
+ current_a = current_a + s[3]
+ else:
+ axis4 = ""
+ if lg == "G00":
+ g += "G01" + c([None, None, s[5][0] + depth]) + penetration_feed + "(Penetrate)\n"
+ if (r[0] ** 2 + r[1] ** 2) > self.options.min_arc_radius ** 2:
+ r1 = (P(s[0]) - P(s[2]))
+ r2 = (P(si[0]) - P(s[2]))
+ if abs(r1.mag() - r2.mag()) < 0.001:
+ g += ("G02" if s[3] < 0 else "G03") + c(si[0] + [s[5][1] + depth, (s[2][0] - s[0][0]), (s[2][1] - s[0][1])]) + feed + axis4 + "\n"
+ else:
+ r = (r1.mag() + r2.mag()) / 2
+ g += ("G02" if s[3] < 0 else "G03") + c(si[0] + [s[5][1] + depth]) + " R{:f}".format(r) + feed + axis4 + "\n"
+ lg = 'G02'
+ else:
+ if tool['4th axis meaning'] == "tangent knife":
+ a = atan2(si[0][0] - s[0][0], si[0][1] - s[0][1]) + math.pi
+ a = calculate_angle(a, current_a)
+ g += "G01 A{}\n".format(a * tool['4th axis scale'] + tool['4th axis offset'])
+ current_a = a
+ g += "G01" + c(si[0] + [s[5][1] + depth]) + feed + "\n"
+ lg = 'G01'
+ if si[1] == 'end':
+ g += go_to_safe_distance + tool['gcode after path'] + "\n"
+ return g
+
+ def get_transforms(self, g):
+ root = self.document.getroot()
+ trans = []
+ while g != root:
+ if 'transform' in g.keys():
+ t = g.get('transform')
+ t = Transform(t).matrix
+ trans = (Transform(t) * Transform(trans)).matrix if trans != [] else t
+
+ print_(trans)
+ g = g.getparent()
+ return trans
+
+ def reverse_transform(self, transform):
+ trans = numpy.array(transform + ([0, 0, 1],))
+ if numpy.linalg.det(trans) != 0:
+ trans = numpy.linalg.inv(trans).tolist()[:2]
+ return trans
+ else:
+ return transform
+
+ def apply_transforms(self, g, csp, reverse=False):
+ trans = self.get_transforms(g)
+ if trans:
+ if not reverse:
+ # TODO: This was applyTransformToPath but was deprecated. Candidate for refactoring.
+ for comp in csp:
+ for ctl in comp:
+ for pt in ctl:
+ pt[0], pt[1] = Transform(trans).apply_to_point(pt)
+
+ else:
+ # TODO: This was applyTransformToPath but was deprecated. Candidate for refactoring.
+ for comp in csp:
+ for ctl in comp:
+ for pt in ctl:
+ pt[0], pt[1] = Transform(self.reverse_transform(trans)).apply_to_point(pt)
+ return csp
+
+ def transform_scalar(self, x, layer, reverse=False):
+ return self.transform([x, 0], layer, reverse)[0] - self.transform([0, 0], layer, reverse)[0]
+
+ def transform(self, source_point, layer, reverse=False):
+ if layer not in self.transform_matrix:
+ for i in range(self.layers.index(layer), -1, -1):
+ if self.layers[i] in self.orientation_points:
+ break
+ if self.layers[i] not in self.orientation_points:
+ self.error(f"Orientation points for '{layer.label}' layer have not been found! Please add orientation points using Orientation tab!", "error")
+ elif self.layers[i] in self.transform_matrix:
+ self.transform_matrix[layer] = self.transform_matrix[self.layers[i]]
+ self.Zcoordinates[layer] = self.Zcoordinates[self.layers[i]]
+ else:
+ orientation_layer = self.layers[i]
+ if len(self.orientation_points[orientation_layer]) > 1:
+ self.error(f"There are more than one orientation point groups in '{orientation_layer.label}' layer")
+ points = self.orientation_points[orientation_layer][0]
+ if len(points) == 2:
+ points += [[[(points[1][0][1] - points[0][0][1]) + points[0][0][0], -(points[1][0][0] - points[0][0][0]) + points[0][0][1]], [-(points[1][1][1] - points[0][1][1]) + points[0][1][0], points[1][1][0] - points[0][1][0] + points[0][1][1]]]]
+ if len(points) == 3:
+ print_("Layer '{orientation_layer.label}' Orientation points: ")
+ for point in points:
+ print_(point)
+ # Zcoordinates definition taken from Orientatnion point 1 and 2
+ self.Zcoordinates[layer] = [max(points[0][1][2], points[1][1][2]), min(points[0][1][2], points[1][1][2])]
+ matrix = numpy.array([
+ [points[0][0][0], points[0][0][1], 1, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, points[0][0][0], points[0][0][1], 1, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, points[0][0][0], points[0][0][1], 1],
+ [points[1][0][0], points[1][0][1], 1, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, points[1][0][0], points[1][0][1], 1, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, points[1][0][0], points[1][0][1], 1],
+ [points[2][0][0], points[2][0][1], 1, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, points[2][0][0], points[2][0][1], 1, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, points[2][0][0], points[2][0][1], 1]
+ ])
+
+ if numpy.linalg.det(matrix) != 0:
+ m = numpy.linalg.solve(matrix,
+ numpy.array(
+ [[points[0][1][0]], [points[0][1][1]], [1], [points[1][1][0]], [points[1][1][1]], [1], [points[2][1][0]], [points[2][1][1]], [1]]
+ )
+ ).tolist()
+ self.transform_matrix[layer] = [[m[j * 3 + i][0] for i in range(3)] for j in range(3)]
+
+ else:
+ self.error("Orientation points are wrong! (if there are two orientation points they should not be the same. If there are three orientation points they should not be in a straight line.)", "error")
+ else:
+ self.error("Orientation points are wrong! (if there are two orientation points they should not be the same. If there are three orientation points they should not be in a straight line.)", "error")
+
+ self.transform_matrix_reverse[layer] = numpy.linalg.inv(self.transform_matrix[layer]).tolist()
+ print_(f"\n Layer '{layer.label}' transformation matrixes:")
+ print_(self.transform_matrix)
+ print_(self.transform_matrix_reverse)
+
+ # Zautoscale is obsolete
+ self.Zauto_scale[layer] = 1
+ print_("Z automatic scale = {} (computed according orientation points)".format(self.Zauto_scale[layer]))
+
+ x = source_point[0]
+ y = source_point[1]
+ if not reverse:
+ t = self.transform_matrix[layer]
+ else:
+ t = self.transform_matrix_reverse[layer]
+ return [t[0][0] * x + t[0][1] * y + t[0][2], t[1][0] * x + t[1][1] * y + t[1][2]]
+
+ def transform_csp(self, csp_, layer, reverse=False):
+ csp = [[[csp_[i][j][0][:], csp_[i][j][1][:], csp_[i][j][2][:]] for j in range(len(csp_[i]))] for i in range(len(csp_))]
+ for i in xrange(len(csp)):
+ for j in xrange(len(csp[i])):
+ for k in xrange(len(csp[i][j])):
+ csp[i][j][k] = self.transform(csp[i][j][k], layer, reverse)
+ return csp
+
+ def error(self, s, msg_type="warning"):
+ """
+ Errors handling function
+ warnings are printed into log file and warning message is displayed but
+ extension continues working,
+ errors causes log and execution is halted
+ """
+ if msg_type == "warning":
+ print_(s)
+ inkex.errormsg(s + "\n")
+
+ elif msg_type == "error":
+ print_(s)
+ raise inkex.AbortExtension(s)
+
+ else:
+ print_("Unknown message type: {}".format(msg_type))
+ print_(s)
+ raise inkex.AbortExtension(s)
+
+ ################################################################################
+ # Set markers
+ ################################################################################
+ def set_markers(self):
+ """Make sure all markers are available"""
+ def ensure_marker(elem_id, x=-4, polA='', polB='-', fill='#000044'):
+ if self.svg.getElementById(elem_id) is None:
+ marker = self.svg.defs.add(Marker(
+ id=elem_id, orient="auto", refX=str(x), refY="-1.687441",
+ style="overflow:visible"))
+ path = marker.add(PathElement(
+ d="m {0}4.588864,-1.687441 0.0,0.0 L {0}9.177728,0.0 "\
+ "c {1}0.73311,-0.996261 {1}0.728882,-2.359329 0.0,-3.374882"\
+ .format(polA, polB)))
+ path.style = "fill:{};fill-rule:evenodd;stroke:none;".format(fill)
+
+ ensure_marker("CheckToolsAndOPMarker")
+ ensure_marker("DrawCurveMarker")
+ ensure_marker("DrawCurveMarker_r", x=4, polA='-', polB='')
+ ensure_marker("InOutPathMarker", fill='#0072a7')
+
+ def get_info(self):
+ """Get Gcodetools info from the svg"""
+ self.selected_paths = {}
+ self.paths = {}
+ self.tools = {}
+ self.orientation_points = {}
+ self.graffiti_reference_points = {}
+ self.layers = [self.document.getroot()]
+ self.Zcoordinates = {}
+ self.transform_matrix = {}
+ self.transform_matrix_reverse = {}
+ self.Zauto_scale = {}
+ self.in_out_reference_points = []
+ self.my3Dlayer = None
+
+ def recursive_search(g, layer, selected=False):
+ items = g.getchildren()
+ items.reverse()
+ for i in items:
+ if selected:
+ self.svg.selected[i.get("id")] = i
+ if isinstance(i, Layer):
+ if i.label == '3D':
+ self.my3Dlayer = i
+ else:
+ self.layers += [i]
+ recursive_search(i, i)
+
+ elif i.get('gcodetools') == "Gcodetools orientation group":
+ points = self.get_orientation_points(i)
+ if points is not None:
+ self.orientation_points[layer] = self.orientation_points[layer] + [points[:]] if layer in self.orientation_points else [points[:]]
+ print_(f"Found orientation points in '{layer.label}' layer: {points}")
+ else:
+ self.error(f"Warning! Found bad orientation points in '{layer.label}' layer. Resulting Gcode could be corrupt!")
+
+ # Need to recognise old files ver 1.6.04 and earlier
+ elif i.get("gcodetools") == "Gcodetools tool definition" or i.get("gcodetools") == "Gcodetools tool definition":
+ tool = self.get_tool(i)
+ self.tools[layer] = self.tools[layer] + [tool.copy()] if layer in self.tools else [tool.copy()]
+ print_(f"Found tool in '{layer.label}' layer: {tool}")
+
+ elif i.get("gcodetools") == "Gcodetools graffiti reference point":
+ point = self.get_graffiti_reference_points(i)
+ if point:
+ self.graffiti_reference_points[layer] = self.graffiti_reference_points[layer] + [point[:]] if layer in self.graffiti_reference_points else [point]
+ else:
+ self.error(f"Warning! Found bad graffiti reference point in '{layer.label}' layer. Resulting Gcode could be corrupt!")
+
+ elif isinstance(i, inkex.PathElement):
+ if "gcodetools" not in i.keys():
+ self.paths[layer] = self.paths[layer] + [i] if layer in self.paths else [i]
+ if i.get("id") in self.svg.selected.ids:
+ self.selected_paths[layer] = self.selected_paths[layer] + [i] if layer in self.selected_paths else [i]
+
+ elif i.get("gcodetools") == "In-out reference point group":
+ items_ = i.getchildren()
+ items_.reverse()
+ for j in items_:
+ if j.get("gcodetools") == "In-out reference point":
+ self.in_out_reference_points.append(self.apply_transforms(j, j.path.to_superpath())[0][0][1])
+
+ elif isinstance(i, inkex.Group):
+ recursive_search(i, layer, (i.get("id") in self.svg.selected))
+
+ elif i.get("id") in self.svg.selected:
+ # xgettext:no-pango-format
+ self.error("This extension works with Paths and Dynamic Offsets and groups of them only! "
+ "All other objects will be ignored!\n"
+ "Solution 1: press Path->Object to path or Shift+Ctrl+C.\n"
+ "Solution 2: Path->Dynamic offset or Ctrl+J.\n"
+ "Solution 3: export all contours to PostScript level 2 (File->Save As->.ps) and File->Import this file.")
+
+ recursive_search(self.document.getroot(), self.document.getroot())
+
+ if len(self.layers) == 1:
+ self.error("Document has no layers! Add at least one layer using layers panel (Ctrl+Shift+L)", "error")
+ root = self.document.getroot()
+
+ if root in self.selected_paths or root in self.paths:
+ self.error("Warning! There are some paths in the root of the document, but not in any layer! Using bottom-most layer for them.")
+
+ if root in self.selected_paths:
+ if self.layers[-1] in self.selected_paths:
+ self.selected_paths[self.layers[-1]] += self.selected_paths[root][:]
+ else:
+ self.selected_paths[self.layers[-1]] = self.selected_paths[root][:]
+ del self.selected_paths[root]
+
+ if root in self.paths:
+ if self.layers[-1] in self.paths:
+ self.paths[self.layers[-1]] += self.paths[root][:]
+ else:
+ self.paths[self.layers[-1]] = self.paths[root][:]
+ del self.paths[root]
+
+ def get_orientation_points(self, g):
+ items = g.getchildren()
+ items.reverse()
+ p2 = []
+ p3 = []
+ p = None
+ for i in items:
+ if isinstance(i, inkex.Group):
+ if i.get("gcodetools") == "Gcodetools orientation point (2 points)":
+ p2 += [i]
+ if i.get("gcodetools") == "Gcodetools orientation point (3 points)":
+ p3 += [i]
+ if len(p2) == 2:
+ p = p2
+ elif len(p3) == 3:
+ p = p3
+ if p is None:
+ return None
+ points = []
+ for i in p:
+ point = [[], []]
+ for node in i:
+ if node.get('gcodetools') == "Gcodetools orientation point arrow":
+ csp = node.path.transform(node.composed_transform()).to_superpath()
+ point[0] = csp[0][0][1]
+ if node.get('gcodetools') == "Gcodetools orientation point text":
+ inkex.errormsg(node.get_text())
+ r = re.match(r'(?i)\s*\(\s*(-?\s*\d*(?:,|\.)*\d*)\s*;\s*(-?\s*\d*(?:,|\.)*\d*)\s*;\s*(-?\s*\d*(?:,|\.)*\d*)\s*\)\s*', node.get_text())
+ point[1] = [float(r.group(1)), float(r.group(2)), float(r.group(3))]
+ if point[0] != [] and point[1] != []:
+ points += [point]
+ if len(points) == len(p2) == 2 or len(points) == len(p3) == 3:
+ return points
+ else:
+ return None
+
+ def get_graffiti_reference_points(self, g):
+ point = [[], '']
+ for node in g:
+ if node.get('gcodetools') == "Gcodetools graffiti reference point arrow":
+ point[0] = self.apply_transforms(node, node.path.to_superpath())[0][0][1]
+ if node.get('gcodetools') == "Gcodetools graffiti reference point text":
+ point[1] = node.get_text()
+ if point[0] != [] and point[1] != '':
+ return point
+ else:
+ return []
+
+ def get_tool(self, g):
+ tool = self.default_tool.copy()
+ tool["self_group"] = g
+ for i in g:
+ # Get parameters
+ if i.get("gcodetools") == "Gcodetools tool background":
+ tool["style"] = dict(i.style)
+ elif i.get("gcodetools") == "Gcodetools tool parameter":
+ key = None
+ value = None
+ for j in i:
+ # need to recognise old tools from ver 1.6.04
+ if j.get("gcodetools") == "Gcodetools tool definition field name" or j.get("gcodetools") == "Gcodetools tool defention field name":
+ key = j.get_text()
+ if j.get("gcodetools") == "Gcodetools tool definition field value" or j.get("gcodetools") == "Gcodetools tool defention field value":
+ value = j.get_text()
+ if value == "(None)":
+ value = ""
+ if value is None or key is None:
+ continue
+ if key in self.default_tool.keys():
+ try:
+ tool[key] = type(self.default_tool[key])(value)
+ except:
+ tool[key] = self.default_tool[key]
+ self.error("Warning! Tool's and default tool's parameter's ({}) types are not the same ( type('{}') != type('{}') ).".format(key, value, self.default_tool[key]))
+ else:
+ tool[key] = value
+ self.error("Warning! Tool has parameter that default tool has not ( '{}': '{}' ).".format(key, value))
+ return tool
+
+ def set_tool(self, layer):
+ for i in range(self.layers.index(layer), -1, -1):
+ if self.layers[i] in self.tools:
+ break
+ if self.layers[i] in self.tools:
+ if self.layers[i] != layer:
+ self.tools[layer] = self.tools[self.layers[i]]
+ if len(self.tools[layer]) > 1:
+ label = self.layers[i].label
+ self.error(f"Layer '{label}' contains more than one tool!")
+ return self.tools[layer]
+ else:
+ self.error(f"Can not find tool for '{layer.label}' layer! Please add one with Tools library tab!", "error")
+
+ ################################################################################
+ #
+ # Path to Gcode
+ #
+ ################################################################################
+ def tab_path_to_gcode(self):
+ self.get_info_plus()
+ def get_boundaries(points):
+ minx = None
+ miny = None
+ maxx = None
+ maxy = None
+ out = [[], [], [], []]
+ for p in points:
+ if minx == p[0]:
+ out[0] += [p]
+ if minx is None or p[0] < minx:
+ minx = p[0]
+ out[0] = [p]
+
+ if miny == p[1]:
+ out[1] += [p]
+ if miny is None or p[1] < miny:
+ miny = p[1]
+ out[1] = [p]
+
+ if maxx == p[0]:
+ out[2] += [p]
+ if maxx is None or p[0] > maxx:
+ maxx = p[0]
+ out[2] = [p]
+
+ if maxy == p[1]:
+ out[3] += [p]
+ if maxy is None or p[1] > maxy:
+ maxy = p[1]
+ out[3] = [p]
+ return out
+
+ def remove_duplicates(points):
+ i = 0
+ out = []
+ for p in points:
+ for j in xrange(i, len(points)):
+ if p == points[j]:
+ points[j] = [None, None]
+ if p != [None, None]:
+ out += [p]
+ i += 1
+ return out
+
+ def get_way_len(points):
+ l = 0
+ for i in xrange(1, len(points)):
+ l += math.sqrt((points[i][0] - points[i - 1][0]) ** 2 + (points[i][1] - points[i - 1][1]) ** 2)
+ return l
+
+ def sort_dxfpoints(points):
+ points = remove_duplicates(points)
+ ways = [
+ # l=0, d=1, r=2, u=3
+ [3, 0], # ul
+ [3, 2], # ur
+ [1, 0], # dl
+ [1, 2], # dr
+ [0, 3], # lu
+ [0, 1], # ld
+ [2, 3], # ru
+ [2, 1], # rd
+ ]
+ minimal_way = []
+ minimal_len = None
+ for w in ways:
+ tpoints = points[:]
+ cw = []
+ for j in xrange(0, len(points)):
+ p = get_boundaries(get_boundaries(tpoints)[w[0]])[w[1]]
+ tpoints.remove(p[0])
+ cw += p
+ curlen = get_way_len(cw)
+ if minimal_len is None or curlen < minimal_len:
+ minimal_len = curlen
+ minimal_way = cw
+
+ return minimal_way
+
+ def sort_lines(lines):
+ if len(lines) == 0:
+ return []
+ lines = [[key] + lines[key] for key in range(len(lines))]
+ keys = [0]
+ end_point = lines[0][3:]
+ print_("!!!", lines, "\n", end_point)
+ del lines[0]
+ while len(lines) > 0:
+ dist = [[point_to_point_d2(end_point, lines[i][1:3]), i] for i in range(len(lines))]
+ i = min(dist)[1]
+ keys.append(lines[i][0])
+ end_point = lines[i][3:]
+ del lines[i]
+ return keys
+
+ def sort_curves(curves):
+ lines = []
+ for curve in curves:
+ lines += [curve[0][0][0] + curve[-1][-1][0]]
+ return sort_lines(lines)
+
+ def print_dxfpoints(points):
+ gcode = ""
+ for point in points:
+ gcode += "(drilling dxfpoint)\nG00 Z{:f}\nG00 X{:f} Y{:f}\nG01 Z{:f} F{:f}\nG04 P{:f}\nG00 Z{:f}\n".format(self.options.Zsafe, point[0], point[1], self.Zcoordinates[layer][1], self.tools[layer][0]["penetration feed"], 0.2, self.options.Zsafe)
+ return gcode
+
+ def get_path_properties(node):
+ res = {}
+ done = False
+ while not done and node != self.svg:
+ for i in node.getchildren():
+ if isinstance(i, inkex.Desc):
+ res["Description"] = i.text
+ elif isinstance(i, inkex.Title):
+ res["Title"] = i.text
+ done = True
+ node = node.getparent()
+ return res
+
+ if self.selected_paths == {} and self.options.auto_select_paths:
+ paths = self.paths
+ self.error("No paths are selected! Trying to work on all available paths.")
+ else:
+ paths = self.selected_paths
+ self.check_dir()
+ gcode = ""
+
+ parent = list(self.selected_paths)[0] if self.selected_paths else self.layers[0]
+ biarc_group = parent.add(Group())
+ print_(("self.layers=", self.layers))
+ print_(("paths=", paths))
+ colors = {}
+ for layer in self.layers:
+ if layer in paths:
+ print_(("layer", layer))
+ # transform simple path to get all var about orientation
+ self.transform_csp([[[[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]]], layer)
+
+ self.set_tool(layer)
+ curves = []
+ dxfpoints = []
+
+ try:
+ depth_func = eval('lambda c,d,s: ' + self.options.path_to_gcode_depth_function.strip('"'))
+ except:
+ self.error("Bad depth function! Enter correct function at Path to Gcode tab!")
+
+ for path in paths[layer]:
+ if "d" not in path.keys():
+ self.error("Warning: One or more paths do not have 'd' parameter, try to Ungroup (Ctrl+Shift+G) and Object to Path (Ctrl+Shift+C)!")
+ continue
+ csp = path.path.to_superpath()
+ csp = self.apply_transforms(path, csp)
+ id_ = path.get("id")
+
+ def set_comment(match, path):
+ if match.group(1) in path.keys():
+ return path.get(match.group(1))
+ else:
+ return "None"
+
+ if self.options.comment_gcode != "":
+ comment = re.sub("\\[([A-Za-z_\\-\\:]+)\\]", partial(set_comment, path=path), self.options.comment_gcode)
+ comment = comment.replace(":newline:", "\n")
+ comment = gcode_comment_str(comment)
+ else:
+ comment = ""
+ if self.options.comment_gcode_from_properties:
+ tags = get_path_properties(path)
+ for tag in tags:
+ comment += gcode_comment_str("{}: {}".format(tag, tags[tag]))
+
+ stroke = path.style('stroke')
+ colors[id_] = inkex.Color(stroke if stroke != None else "#000").to_rgb()
+ if path.get("dxfpoint") == "1":
+ tmp_curve = self.transform_csp(csp, layer)
+ x = tmp_curve[0][0][0][0]
+ y = tmp_curve[0][0][0][1]
+ print_("got dxfpoint (scaled) at ({:f},{:f})".format(x, y))
+ dxfpoints += [[x, y]]
+ else:
+
+ zd = self.Zcoordinates[layer][1]
+ zs = self.Zcoordinates[layer][0]
+ c = 1. - float(sum(colors[id_])) / 255 / 3
+ curves += [
+ [
+ [id_, depth_func(c, zd, zs), comment],
+ [self.parse_curve([subpath], layer) for subpath in csp]
+ ]
+ ]
+ dxfpoints = sort_dxfpoints(dxfpoints)
+ gcode += print_dxfpoints(dxfpoints)
+
+ for curve in curves:
+ for subcurve in curve[1]:
+ self.draw_curve(subcurve, layer)
+
+ if self.options.path_to_gcode_order == 'subpath by subpath':
+ curves_ = []
+ for curve in curves:
+ curves_ += [[curve[0], [subcurve]] for subcurve in curve[1]]
+ curves = curves_
+
+ self.options.path_to_gcode_order = 'path by path'
+
+ if self.options.path_to_gcode_order == 'path by path':
+ if self.options.path_to_gcode_sort_paths:
+ keys = sort_curves([curve[1] for curve in curves])
+ else:
+ keys = range(len(curves))
+ for key in keys:
+ d = curves[key][0][1]
+ for step in range(0, int(math.ceil(abs((zs - d) / self.tools[layer][0]["depth step"])))):
+ z = max(d, zs - abs(self.tools[layer][0]["depth step"] * (step + 1)))
+
+ gcode += gcode_comment_str("\nStart cutting path id: {}".format(curves[key][0][0]))
+ if curves[key][0][2] != "()":
+ gcode += curves[key][0][2] # add comment
+
+ for curve in curves[key][1]:
+ gcode += self.generate_gcode(curve, layer, z)
+
+ gcode += gcode_comment_str("End cutting path id: {}\n\n".format(curves[key][0][0]))
+
+ else: # pass by pass
+ mind = min([curve[0][1] for curve in curves])
+ for step in range(0, 1 + int(math.ceil(abs((zs - mind) / self.tools[layer][0]["depth step"])))):
+ z = zs - abs(self.tools[layer][0]["depth step"] * step)
+ curves_ = []
+ for curve in curves:
+ if curve[0][1] < z:
+ curves_.append(curve)
+
+ z = zs - abs(self.tools[layer][0]["depth step"] * (step + 1))
+ gcode += "\n(Pass at depth {})\n".format(z)
+
+ if self.options.path_to_gcode_sort_paths:
+ keys = sort_curves([curve[1] for curve in curves_])
+ else:
+ keys = range(len(curves_))
+ for key in keys:
+
+ gcode += gcode_comment_str("Start cutting path id: {}".format(curves[key][0][0]))
+ if curves[key][0][2] != "()":
+ gcode += curves[key][0][2] # add comment
+
+ for subcurve in curves_[key][1]:
+ gcode += self.generate_gcode(subcurve, layer, max(z, curves_[key][0][1]))
+
+ gcode += gcode_comment_str("End cutting path id: {}\n\n".format(curves[key][0][0]))
+
+ self.export_gcode(gcode)
+
+ ################################################################################
+ #
+ # dxfpoints
+ #
+ ################################################################################
+ def tab_dxfpoints(self):
+ self.get_info_plus()
+ if self.selected_paths == {}:
+ self.error("Nothing is selected. Please select something to convert to drill point (dxfpoint) or clear point sign.")
+ for layer in self.layers:
+ if layer in self.selected_paths:
+ for path in self.selected_paths[layer]:
+ if self.options.dxfpoints_action == 'replace':
+
+ path.set("dxfpoint", "1")
+ r = re.match("^\\s*.\\s*(\\S+)", path.get("d"))
+ if r is not None:
+ print_(("got path=", r.group(1)))
+ path.set("d", "m {} 2.9375,-6.343750000001 0.8125,1.90625 6.843748640396,-6.84374864039 0,0 0.6875,0.6875 -6.84375,6.84375 1.90625,0.812500000001 z".format(r.group(1)))
+ path.set("style", MARKER_STYLE["dxf_points"])
+
+ if self.options.dxfpoints_action == 'save':
+ path.set("dxfpoint", "1")
+
+ if self.options.dxfpoints_action == 'clear' and path.get("dxfpoint") == "1":
+ path.set("dxfpoint", "0")
+
+ ################################################################################
+ #
+ # Artefacts
+ #
+ ################################################################################
+ def tab_area_artefacts(self):
+ self.get_info_plus()
+ if self.selected_paths == {} and self.options.auto_select_paths:
+ paths = self.paths
+ self.error("No paths are selected! Trying to work on all available paths.")
+ else:
+ paths = self.selected_paths
+ for layer in paths:
+ for path in paths[layer]:
+ parent = path.getparent()
+ if "d" not in path.keys():
+ self.error("Warning: One or more paths do not have 'd' parameter, try to Ungroup (Ctrl+Shift+G) and Object to Path (Ctrl+Shift+C)!")
+ continue
+ csp = path.path.to_superpath()
+ remove = []
+ for i in range(len(csp)):
+ subpath = [[point[:] for point in points] for points in csp[i]]
+ subpath = self.apply_transforms(path, [subpath])[0]
+ bounds = csp_simple_bound([subpath])
+ if (bounds[2] - bounds[0]) ** 2 + (bounds[3] - bounds[1]) ** 2 < self.options.area_find_artefacts_diameter ** 2:
+ if self.options.area_find_artefacts_action == "mark with an arrow":
+ arrow = Path('m {},{} 2.9375,-6.343750000001 0.8125,1.90625 6.843748640396,-6.84374864039 0,0 0.6875,0.6875 -6.84375,6.84375 1.90625,0.812500000001 z'.format(subpath[0][1][0], subpath[0][1][1])).to_superpath()
+ arrow = self.apply_transforms(path, arrow, True)
+ node = parent.add(PathElement())
+ node.path = CubicSuperPath(arrow)
+ node.style = MARKER_STYLE["area artefact arrow"]
+ node.set('gcodetools', 'area artefact arrow')
+ elif self.options.area_find_artefacts_action == "mark with style":
+ node = parent.add(PathElement())
+ node.path = CubicSuperPath(csp[i])
+ node.style = MARKER_STYLE["area artefact"]
+ remove.append(i)
+ elif self.options.area_find_artefacts_action == "delete":
+ remove.append(i)
+ print_("Deleted artefact {}".format(subpath))
+ remove.reverse()
+ for i in remove:
+ del csp[i]
+ if len(csp) == 0:
+ parent.remove(path)
+ else:
+ path.path = CubicSuperPath(csp)
+
+ return
+
+ def tab_area(self):
+ """Calculate area curves"""
+ self.get_info_plus()
+ if len(self.selected_paths) <= 0:
+ self.error("This extension requires at least one selected path.")
+ return
+ for layer in self.layers:
+ if layer in self.selected_paths:
+ self.set_tool(layer)
+ if self.tools[layer][0]['diameter'] <= 0:
+ self.error(f"Tool diameter must be > 0 but tool's diameter on '{layer.label}' layer is not!", "error")
+
+ for path in self.selected_paths[layer]:
+ print_(("doing path", path.get("style"), path.get("d")))
+
+ area_group = path.getparent().add(Group())
+
+ csp = path.path.to_superpath()
+ print_(csp)
+ if not csp:
+ print_("omitting non-path")
+ self.error("Warning: omitting non-path")
+ continue
+
+ if path.get('sodipodi:type') != "inkscape:offset":
+ print_("Path {} is not an offset. Preparation started.".format(path.get("id")))
+ # Path is not offset. Preparation will be needed.
+ # Finding top most point in path (min y value)
+
+ min_x, min_y, min_i, min_j, min_t = csp_true_bounds(csp)[1]
+
+ # Reverse path if needed.
+ if min_y != float("-inf"):
+ # Move outline subpath to the beginning of csp
+ subp = csp[min_i]
+ del csp[min_i]
+ j = min_j
+ # Split by the topmost point and join again
+ if min_t in [0, 1]:
+ if min_t == 0:
+ j = j - 1
+ subp[-1][2], subp[0][0] = subp[-1][1], subp[0][1]
+ subp = [[subp[j][1], subp[j][1], subp[j][2]]] + subp[j + 1:] + subp[:j] + [[subp[j][0], subp[j][1], subp[j][1]]]
+ else:
+ sp1, sp2, sp3 = csp_split(subp[j - 1], subp[j], min_t)
+ subp[-1][2], subp[0][0] = subp[-1][1], subp[0][1]
+ subp = [[sp2[1], sp2[1], sp2[2]]] + [sp3] + subp[j + 1:] + subp[:j - 1] + [sp1] + [[sp2[0], sp2[1], sp2[1]]]
+ csp = [subp] + csp
+ # reverse path if needed
+ if csp_subpath_ccw(csp[0]):
+ for i in range(len(csp)):
+ n = []
+ for j in csp[i]:
+ n = [[j[2][:], j[1][:], j[0][:]]] + n
+ csp[i] = n[:]
+
+ # What the absolute fudge is this doing? Closing paths? Ugh.
+ # Not sure but it most be at this level and not in the if statement, or it will not work with dynamic offsets
+ d = str(CubicSuperPath(csp))
+ print_(("original d=", d))
+ d = re.sub(r'(?i)(m[^mz]+)', r'\1 Z ', d)
+ d = re.sub(r'(?i)\s*z\s*z\s*', r' Z ', d)
+ d = re.sub(r'(?i)\s*([A-Za-z])\s*', r' \1 ', d)
+ print_(("formatted d=", d))
+ p0 = self.transform([0, 0], layer)
+ p1 = self.transform([0, 1], layer)
+ scale = (P(p0) - P(p1)).mag()
+ if scale == 0:
+ scale = 1.
+ else:
+ scale = 1. / scale
+ print_(scale)
+ tool_d = self.tools[layer][0]['diameter'] * scale
+ r = self.options.area_inkscape_radius * scale
+ sign = 1 if r > 0 else -1
+ print_("Tool diameter = {}, r = {}".format(tool_d, r))
+
+ # avoiding infinite loops
+ if self.options.area_tool_overlap > 0.9:
+ self.options.area_tool_overlap = .9
+
+ for i in range(self.options.max_area_curves):
+ radius = - tool_d * (i * (1 - self.options.area_tool_overlap) + 0.5) * sign
+ if abs(radius) > abs(r):
+ radius = -r
+
+ elem = area_group.add(PathElement(style=str(MARKER_STYLE["biarc_style_i"]['area'])))
+ elem.set('sodipodi:type', 'inkscape:offset')
+ elem.set('inkscape:radius', radius)
+ elem.set('inkscape:original', d)
+ print_(("adding curve", area_group, d, str(MARKER_STYLE["biarc_style_i"]['area'])))
+ if radius == -r:
+ break
+
+ def tab_area_fill(self):
+ """Fills area with lines"""
+ self.get_info_plus()
+ # convert degrees into rad
+ self.options.area_fill_angle = self.options.area_fill_angle * math.pi / 180
+ if len(self.selected_paths) <= 0:
+ self.error("This extension requires at least one selected path.")
+ return
+ for layer in self.layers:
+ if layer in self.selected_paths:
+ self.set_tool(layer)
+ if self.tools[layer][0]['diameter'] <= 0:
+ self.error(f"Tool diameter must be > 0 but tool's diameter on '{layer.label}' layer is not!", "error")
+ tool = self.tools[layer][0]
+ for path in self.selected_paths[layer]:
+ lines = []
+ print_(("doing path", path.get("style"), path.get("d")))
+ area_group = path.getparent().add(Group())
+ csp = path.path.to_superpath()
+ if not csp:
+ print_("omitting non-path")
+ self.error("Warning: omitting non-path")
+ continue
+ csp = self.apply_transforms(path, csp)
+ csp = csp_close_all_subpaths(csp)
+ csp = self.transform_csp(csp, layer)
+
+ # rotate the path to get bounds in defined direction.
+ a = - self.options.area_fill_angle
+ rotated_path = [[[[point[0] * math.cos(a) - point[1] * math.sin(a), point[0] * math.sin(a) + point[1] * math.cos(a)] for point in sp] for sp in subpath] for subpath in csp]
+ bounds = csp_true_bounds(rotated_path)
+
+ # Draw the lines
+ # Get path's bounds
+ b = [0.0, 0.0, 0.0, 0.0] # [minx,miny,maxx,maxy]
+ for k in range(4):
+ i = bounds[k][2]
+ j = bounds[k][3]
+ t = bounds[k][4]
+
+ b[k] = csp_at_t(rotated_path[i][j - 1], rotated_path[i][j], t)[k % 2]
+
+ # Zig-zag
+ r = tool['diameter'] * (1 - self.options.area_tool_overlap)
+ if r <= 0:
+ self.error('Tools diameter must be greater than 0!', 'error')
+ return
+
+ lines += [[]]
+
+ if self.options.area_fill_method == 'zig-zag':
+ i = b[0] - self.options.area_fill_shift * r
+ top = True
+ last_one = True
+ while i < b[2] or last_one:
+ if i >= b[2]:
+ last_one = False
+ if not lines[-1]:
+ lines[-1] += [[i, b[3]]]
+
+ if top:
+ lines[-1] += [[i, b[1]], [i + r, b[1]]]
+
+ else:
+ lines[-1] += [[i, b[3]], [i + r, b[3]]]
+
+ top = not top
+ i += r
+ else:
+
+ w = b[2] - b[0] + self.options.area_fill_shift * r
+ h = b[3] - b[1] + self.options.area_fill_shift * r
+ x = b[0] - self.options.area_fill_shift * r
+ y = b[1] - self.options.area_fill_shift * r
+ lines[-1] += [[x, y]]
+ stage = 0
+ start = True
+ while w > 0 and h > 0:
+ stage = (stage + 1) % 4
+ if stage == 0:
+ y -= h
+ h -= r
+ elif stage == 1:
+ x += w
+ if not start:
+ w -= r
+ start = False
+ elif stage == 2:
+ y += h
+ h -= r
+ elif stage == 3:
+ x -= w
+ w -= r
+
+ lines[-1] += [[x, y]]
+
+ stage = (stage + 1) % 4
+ if w <= 0 and h > 0:
+ y = y - h if stage == 0 else y + h
+ if h <= 0 and w > 0:
+ x = x - w if stage == 3 else x + w
+ lines[-1] += [[x, y]]
+ # Rotate created paths back
+ a = self.options.area_fill_angle
+ lines = [[[point[0] * math.cos(a) - point[1] * math.sin(a), point[0] * math.sin(a) + point[1] * math.cos(a)] for point in subpath] for subpath in lines]
+
+ # get the intersection points
+
+ splitted_line = [[lines[0][0]]]
+ intersections = {}
+ for l1, l2, in zip(lines[0], lines[0][1:]):
+ ints = []
+
+ if l1[0] == l2[0] and l1[1] == l2[1]:
+ continue
+ for i in range(len(csp)):
+ for j in range(1, len(csp[i])):
+ sp1 = csp[i][j - 1]
+ sp2 = csp[i][j]
+ roots = csp_line_intersection(l1, l2, sp1, sp2)
+ for t in roots:
+ p = tuple(csp_at_t(sp1, sp2, t))
+ if l1[0] == l2[0]:
+ t1 = (p[1] - l1[1]) / (l2[1] - l1[1])
+ else:
+ t1 = (p[0] - l1[0]) / (l2[0] - l1[0])
+ if 0 <= t1 <= 1:
+ ints += [[t1, p[0], p[1], i, j, t]]
+ if p in intersections:
+ intersections[p] += [[i, j, t]]
+ else:
+ intersections[p] = [[i, j, t]]
+
+ ints.sort()
+ for i in ints:
+ splitted_line[-1] += [[i[1], i[2]]]
+ splitted_line += [[[i[1], i[2]]]]
+ splitted_line[-1] += [l2]
+ i = 0
+ print_(splitted_line)
+ while i < len(splitted_line):
+ # check if the middle point of the first lines segment is inside the path.
+ # and remove the subline if not.
+ l1 = splitted_line[i][0]
+ l2 = splitted_line[i][1]
+ p = [(l1[0] + l2[0]) / 2, (l1[1] + l2[1]) / 2]
+ if not point_inside_csp(p, csp):
+ del splitted_line[i]
+ else:
+ i += 1
+
+ # and apply back transrormations to draw them
+ csp_line = csp_from_polyline(splitted_line)
+ csp_line = self.transform_csp(csp_line, layer, True)
+
+ self.draw_csp(csp_line, group=area_group)
+
+ ################################################################################
+ #
+ # Engraving
+ #
+ # LT Notes to self: See wiki.inkscape.org/wiki/index.php/PythonEffectTutorial
+ # To create anything in the Inkscape document, look at the XML editor for
+ # details of how such an element looks in XML, then follow this model.
+ # layer number n appears in XML as <svg:g id="layern" inkscape:label="layername">
+ #
+ # to create it, use
+ # Mylayer = self.svg.add(Layer.new('layername'))
+ #
+ # group appears in XML as <svg:g id="gnnnnn"> where nnnnn is a number
+ #
+ # to create it, use
+ # Mygroup = parent.add(Group(gcodetools="My group label")
+ # where parent may be the layer or a parent group. To get the parent group, you can use
+ # parent = self.selected_paths[layer][0].getparent()
+ ################################################################################
+ def tab_engraving(self):
+ self.get_info_plus()
+ global cspm
+ global wl
+ global nlLT
+ global i
+ global j
+ global gcode_3Dleft
+ global gcode_3Dright
+ global max_dist # minimum of tool radius and user's requested maximum distance
+ global eye_dist
+ eye_dist = 100 # 3D constant. Try varying it for your eyes
+
+ def bisect(nxy1, nxy2):
+ """LT Find angle bisecting the normals n1 and n2
+
+ Parameters: Normalised normals
+ Returns: nx - Normal of bisector, normalised to 1/cos(a)
+ ny -
+ sinBis2 - sin(angle turned/2): positive if turning in
+ Note that bisect(n1,n2) and bisect(n2,n1) give opposite sinBis2 results
+ If sinturn is less than the user's requested angle tolerance, I return 0
+ """
+ (nx1, ny1) = nxy1
+ (nx2, ny2) = nxy2
+ cosBis = math.sqrt(max(0, (1.0 + nx1 * nx2 - ny1 * ny2) / 2.0))
+ # We can get correct sign of the sin, assuming cos is positive
+ if (abs(ny1 - ny2) < ENGRAVING_TOLERANCE) or (abs(cosBis) < ENGRAVING_TOLERANCE):
+ if abs(nx1 - nx2) < ENGRAVING_TOLERANCE:
+ return nx1, ny1, 0.0
+ sinBis = math.copysign(1, ny1)
+ else:
+ sinBis = cosBis * (nx2 - nx1) / (ny1 - ny2)
+ # We can correct signs by noting that the dot product
+ # of bisector and either normal must be >0
+ costurn = cosBis * nx1 + sinBis * ny1
+ if costurn == 0:
+ return ny1 * 100, -nx1 * 100, 1 # Path doubles back on itself
+ sinturn = sinBis * nx1 - cosBis * ny1
+ if costurn < 0:
+ sinturn = -sinturn
+ if 0 < sinturn * 114.6 < (180 - self.options.engraving_sharp_angle_tollerance):
+ sinturn = 0 # set to zero if less than the user wants to see.
+ return cosBis / costurn, sinBis / costurn, sinturn
+ # end bisect
+
+ def get_radius_to_line(xy1, n_xy1, n_xy2, xy2, n_xy23, xy3, n_xy3):
+ """LT find biggest circle we can engrave here, if constrained by line 2-3
+
+ Parameters:
+ x1,y1,nx1,ny1 coordinates and normal of the line we're currently engraving
+ nx2,ny2 angle bisector at point 2
+ x2,y2 coordinates of first point of line 2-3
+ nx23,ny23 normal to the line 2-3
+ x3,y3 coordinates of the other end
+ nx3,ny3 angle bisector at point 3
+ Returns:
+ radius or self.options.engraving_max_dist if line doesn't limit radius
+ This function can be used in three ways:
+ - With nx1=ny1=0 it finds circle centred at x1,y1
+ - with nx1,ny1 normalised, it finds circle tangential at x1,y1
+ - with nx1,ny1 scaled by 1/cos(a) it finds circle centred on an angle bisector
+ where a is the angle between the bisector and the previous/next normals
+
+ If the centre of the circle tangential to the line 2-3 is outside the
+ angle bisectors at its ends, ignore this line.
+
+ Note that it handles corners in the conventional manner of letter cutting
+ by mitering, not rounding.
+ Algorithm uses dot products of normals to find radius
+ and hence coordinates of centre
+ """
+ (x1, y1) = xy1
+ (nx1, ny1) = n_xy1
+ (nx2, ny2) = n_xy2
+ (x2, y2) = xy2
+ (nx23, ny23) = n_xy23
+ (x3, y3) = xy3
+ (nx3, ny3) = n_xy3
+ global max_dist
+
+ # Start by converting coordinates to be relative to x1,y1
+ x2, y2 = x2 - x1, y2 - y1
+ x3, y3 = x3 - x1, y3 - y1
+
+ # The logic uses vector arithmetic.
+ # The dot product of two vectors gives the product of their lengths
+ # multiplied by the cos of the angle between them.
+ # So, the perpendicular distance from x1y1 to the line 2-3
+ # is equal to the dot product of its normal and x2y2 or x3y3
+ # It is also equal to the projection of x1y1-xcyc on the line's normal
+ # plus the radius. But, as the normal faces inside the path we must negate it.
+
+ # Make sure the line in question is facing x1,y1 and vice versa
+ dist = -x2 * nx23 - y2 * ny23
+ if dist < 0:
+ return max_dist
+ denom = 1. - nx23 * nx1 - ny23 * ny1
+ if denom < ENGRAVING_TOLERANCE:
+ return max_dist
+
+ # radius and centre are:
+ r = dist / denom
+ cx = r * nx1
+ cy = r * ny1
+ # if c is not between the angle bisectors at the ends of the line, ignore
+ # Use vector cross products. Not sure if I need the .0001 safety margins:
+ if (x2 - cx) * ny2 > (y2 - cy) * nx2 + 0.0001:
+ return max_dist
+ if (x3 - cx) * ny3 < (y3 - cy) * nx3 - 0.0001:
+ return max_dist
+ return min(r, max_dist)
+ # end of get_radius_to_line
+
+ def get_radius_to_point(xy1, n_xy, xy2):
+ """LT find biggest circle we can engrave here, constrained by point x2,y2
+
+ This function can be used in three ways:
+ - With nx=ny=0 it finds circle centred at x1,y1
+ - with nx,ny normalised, it finds circle tangential at x1,y1
+ - with nx,ny scaled by 1/cos(a) it finds circle centred on an angle bisector
+ where a is the angle between the bisector and the previous/next normals
+
+ Note that I wrote this to replace find_cutter_centre. It is far less
+ sophisticated but, I hope, far faster.
+ It turns out that finding a circle touching a point is harder than a circle
+ touching a line.
+ """
+ (x1, y1) = xy1
+ (nx, ny) = n_xy
+ (x2, y2) = xy2
+ global max_dist
+
+ # Start by converting coordinates to be relative to x1,y1
+ x2 = x2 - x1
+ y2 = y2 - y1
+ denom = nx ** 2 + ny ** 2 - 1
+ if denom <= ENGRAVING_TOLERANCE: # Not a corner bisector
+ if denom == -1: # Find circle centre x1,y1
+ return math.sqrt(x2 ** 2 + y2 ** 2)
+ # if x2,y2 not in front of the normal...
+ if x2 * nx + y2 * ny <= 0:
+ return max_dist
+ return (x2 ** 2 + y2 ** 2) / (2 * (x2 * nx + y2 * ny))
+ # It is a corner bisector, so..
+ discriminator = (x2 * nx + y2 * ny) ** 2 - denom * (x2 ** 2 + y2 ** 2)
+ if discriminator < 0:
+ return max_dist # this part irrelevant
+ r = (x2 * nx + y2 * ny - math.sqrt(discriminator)) / denom
+ return min(r, max_dist)
+ # end of get_radius_to_point
+
+ def bez_divide(a, b, c, d):
+ """LT recursively divide a Bezier.
+
+ Divides until difference between each
+ part and a straight line is less than some limit
+ Note that, as simple as this code is, it is mathematically correct.
+ Parameters:
+ a,b,c and d are each a list of x,y real values
+ Bezier end points a and d, control points b and c
+ Returns:
+ a list of Beziers.
+ Each Bezier is a list with four members,
+ each a list holding a coordinate pair
+ Note that the final point of one member is the same as
+ the first point of the next, and the control points
+ there are smooth and symmetrical. I use this fact later.
+ """
+ bx = b[0] - a[0]
+ by = b[1] - a[1]
+ cx = c[0] - a[0]
+ cy = c[1] - a[1]
+ dx = d[0] - a[0]
+ dy = d[1] - a[1]
+ limit = 8 * math.hypot(dx, dy) / self.options.engraving_newton_iterations
+ # LT This is the only limit we get from the user currently
+ if abs(dx * by - bx * dy) < limit and abs(dx * cy - cx * dy) < limit:
+ return [[a, b, c, d]]
+ abx = (a[0] + b[0]) / 2.0
+ aby = (a[1] + b[1]) / 2.0
+ bcx = (b[0] + c[0]) / 2.0
+ bcy = (b[1] + c[1]) / 2.0
+ cdx = (c[0] + d[0]) / 2.0
+ cdy = (c[1] + d[1]) / 2.0
+ abcx = (abx + bcx) / 2.0
+ abcy = (aby + bcy) / 2.0
+ bcdx = (bcx + cdx) / 2.0
+ bcdy = (bcy + cdy) / 2.0
+ m = [(abcx + bcdx) / 2.0, (abcy + bcdy) / 2.0]
+ return bez_divide(a, [abx, aby], [abcx, abcy], m) + bez_divide(m, [bcdx, bcdy], [cdx, cdy], d)
+ # end of bez_divide
+
+ def get_biggest(nxy1, nxy2):
+ """LT Find biggest circle we can draw inside path at point x1,y1 normal nx,ny
+
+ Parameters:
+ point - either on a line or at a reflex corner
+ normal - normalised to 1 if on a line, to 1/cos(a) at a corner
+ Returns:
+ tuple (j,i,r)
+ ..where j and i are indices of limiting segment, r is radius
+ """
+ (x1, y1) = nxy1
+ (nx, ny) = nxy2
+ global max_dist
+ global nlLT
+ global i
+ global j
+
+ n1 = nlLT[j][i - 1] # current node
+ jjmin = -1
+ iimin = -1
+ r = max_dist
+ # set limits within which to look for lines
+ xmin = x1 + r * nx - r
+ xmax = x1 + r * nx + r
+ ymin = y1 + r * ny - r
+ ymax = y1 + r * ny + r
+ for jj in xrange(0, len(nlLT)): # for every subpath of this object
+ for ii in xrange(0, len(nlLT[jj])): # for every point and line
+ if nlLT[jj][ii - 1][2]: # if a point
+ if jj == j: # except this one
+ if abs(ii - i) < 3 or abs(ii - i) > len(nlLT[j]) - 3:
+ continue
+ t1 = get_radius_to_point((x1, y1), (nx, ny), nlLT[jj][ii - 1][0])
+ else: # doing a line
+ if jj == j: # except this one
+ if abs(ii - i) < 2 or abs(ii - i) == len(nlLT[j]) - 1:
+ continue
+ if abs(ii - i) == 2 and nlLT[j][(ii + i) / 2 - 1][3] <= 0:
+ continue
+ if (abs(ii - i) == len(nlLT[j]) - 2) and nlLT[j][-1][3] <= 0:
+ continue
+ nx2, ny2 = nlLT[jj][ii - 2][1]
+ x2, y2 = nlLT[jj][ii - 1][0]
+ nx23, ny23 = nlLT[jj][ii - 1][1]
+ x3, y3 = nlLT[jj][ii][0]
+ nx3, ny3 = nlLT[jj][ii][1]
+ if nlLT[jj][ii - 2][3] > 0: # acute, so use normal, not bisector
+ nx2 = nx23
+ ny2 = ny23
+ if nlLT[jj][ii][3] > 0: # acute, so use normal, not bisector
+ nx3 = nx23
+ ny3 = ny23
+ x23min = min(x2, x3)
+ x23max = max(x2, x3)
+ y23min = min(y2, y3)
+ y23max = max(y2, y3)
+ # see if line in range
+ if n1[2] == False and (x23max < xmin or x23min > xmax or y23max < ymin or y23min > ymax):
+ continue
+ t1 = get_radius_to_line((x1, y1), (nx, ny), (nx2, ny2), (x2, y2), (nx23, ny23), (x3, y3), (nx3, ny3))
+ if 0 <= t1 < r:
+ r = t1
+ iimin = ii
+ jjmin = jj
+ xmin = x1 + r * nx - r
+ xmax = x1 + r * nx + r
+ ymin = y1 + r * ny - r
+ ymax = y1 + r * ny + r
+ # next ii
+ # next jj
+ return jjmin, iimin, r
+ # end of get_biggest
+
+ def line_divide(xy0, j0, i0, xy1, j1, i1, n_xy, length):
+ """LT recursively divide a line as much as necessary
+
+ NOTE: This function is not currently used
+ By noting which other path segment is touched by the circles at each end,
+ we can see if anything is to be gained by a further subdivision, since
+ if they touch the same bit of path we can move linearly between them.
+ Also, we can handle points correctly.
+ Parameters:
+ end points and indices of limiting path, normal, length
+ Returns:
+ list of toolpath points
+ each a list of 3 reals: x, y coordinates, radius
+
+ """
+ (x0, y0) = xy0
+ (x1, y1) = xy1
+ (nx, ny) = n_xy
+ global nlLT
+ global i
+ global j
+ global lmin
+ x2 = (x0 + x1) / 2
+ y2 = (y0 + y1) / 2
+ j2, i2, r2 = get_biggest((x2, y2), (nx, ny))
+ if length < lmin:
+ return [[x2, y2, r2]]
+ if j2 == j0 and i2 == i0: # Same as left end. Don't subdivide this part any more
+ return [[x2, y2, r2], line_divide((x2, y2), j2, i2, (x1, y1), j1, i1, (nx, ny), length / 2)]
+ if j2 == j1 and i2 == i1: # Same as right end. Don't subdivide this part any more
+ return [line_divide((x0, y0), j0, i0, (x2, y2), j2, i2, (nx, ny), length / 2), [x2, y2, r2]]
+ return [line_divide((x0, y0), j0, i0, (x2, y2), j2, i2, (nx, ny), length / 2), line_divide((x2, y2), j2, i2, (x1, y1), j1, i1, (nx, ny), length / 2)]
+ # end of line_divide()
+
+ def save_point(xy, w, i, j, ii, jj):
+ """LT Save this point and delete previous one if linear
+
+ The point is, we generate tons of points but many may be in a straight 3D line.
+ There is no benefit in saving the intermediate points.
+ """
+ (x, y) = xy
+ global wl
+ global cspm
+ x = round(x, 4) # round to 4 decimals
+ y = round(y, 4) # round to 4 decimals
+ w = round(w, 4) # round to 4 decimals
+ if len(cspm) > 1:
+ xy1a, xy1, xy1b, i1, j1, ii1, jj1 = cspm[-1]
+ w1 = wl[-1]
+ if i == i1 and j == j1 and ii == ii1 and jj == jj1: # one match
+ xy1a, xy2, xy1b, i1, j1, ii1, jj1 = cspm[-2]
+ w2 = wl[-2]
+ if i == i1 and j == j1 and ii == ii1 and jj == jj1: # two matches. Now test linearity
+ length1 = math.hypot(xy1[0] - x, xy1[1] - y)
+ length2 = math.hypot(xy2[0] - x, xy2[1] - y)
+ length12 = math.hypot(xy2[0] - xy1[0], xy2[1] - xy1[1])
+ # get the xy distance of point 1 from the line 0-2
+ if length2 > length1 and length2 > length12: # point 1 between them
+ xydist = abs((xy2[0] - x) * (xy1[1] - y) - (xy1[0] - x) * (xy2[1] - y)) / length2
+ if xydist < ENGRAVING_TOLERANCE: # so far so good
+ wdist = w2 + (w - w2) * length1 / length2 - w1
+ if abs(wdist) < ENGRAVING_TOLERANCE:
+ cspm.pop()
+ wl.pop()
+ cspm += [[[x, y], [x, y], [x, y], i, j, ii, jj]]
+ wl += [w]
+ # end of save_point
+
+ def draw_point(xy0, xy, w, t):
+ """LT Draw this point as a circle with a 1px dot in the middle (x,y)
+ and a 3D line from (x0,y0) down to x,y. 3D line thickness should be t/2
+
+ Note that points that are subsequently erased as being unneeded do get
+ displayed, but this helps the user see the total area covered.
+ """
+ (x0, y0) = xy0
+ (x, y) = xy
+ global gcode_3Dleft
+ global gcode_3Dright
+ if self.options.engraving_draw_calculation_paths:
+ elem = engraving_group.add(PathElement.arc((x, y), 1))
+ elem.set('gcodetools', "Engraving calculation toolpath")
+ elem.style = "fill:#ff00ff; fill-opacity:0.46; stroke:#000000; stroke-width:0.1;"
+
+ # Don't draw zero radius circles
+ if w:
+ elem = engraving_group.add(PathElement.arc((x, y), w))
+ elem.set('gcodetools', "Engraving calculation paths")
+ elem.style = "fill:none; fill-opacity:0.46; stroke:#000000; stroke-width:0.1;"
+
+ # Find slope direction for shading
+ s = math.atan2(y - y0, x - x0) # -pi to pi
+ # convert to 2 hex digits as a shade of red
+ s2 = "#{0:x}0000".format(int(101 * (1.5 - math.sin(s + 0.5))))
+ style = "stroke:{}; stroke-opacity:1;stroke-width:{};fill:none".format(s2, t/2)
+ right = gcode_3Dleft.add(PathElement(style=style, gcodetools="Gcode G1R"))
+ right.path = "M {:f},{:f} L {:f},{:f}".format(
+ x0 - eye_dist, y0, x - eye_dist - 0.14 * w, y)
+ left = gcode_3Dright.add(PathElement(style=style, gcodetools="Gcode G1L"))
+ left.path = "M {:f},{:f} L {:f},{:f}".format(
+ x0 + eye_dist, y0, x + eye_dist + 0.14 * r, y)
+
+ # end of subfunction definitions. engraving() starts here:
+ gcode = ''
+ r = 0 # theoretical and tool-radius-limited radii in pixels
+ w = 0
+ wmax = 0
+ cspe = []
+ we = []
+ if not self.selected_paths:
+ self.error("Please select at least one path to engrave and run again.")
+ return
+ if not self.check_dir():
+ return
+ # Find what units the user uses
+ unit = " mm"
+ if self.options.unit == "G20 (All units in inches)":
+ unit = " inches"
+ elif self.options.unit != "G21 (All units in mm)":
+ self.error("Unknown unit selected. mm assumed")
+ print_("engraving_max_dist mm/inch", self.options.engraving_max_dist)
+
+ # LT See if we can use this parameter for line and Bezier subdivision:
+ bitlen = 20 / self.options.engraving_newton_iterations
+
+ for layer in self.layers:
+ if layer in self.selected_paths and layer in self.orientation_points:
+ # Calculate scale in pixels per user unit (mm or inch)
+ p1 = self.orientation_points[layer][0][0]
+ p2 = self.orientation_points[layer][0][1]
+ ol = math.hypot(p1[0][0] - p2[0][0], p1[0][1] - p2[0][1])
+ oluu = math.hypot(p1[1][0] - p2[1][0], p1[1][1] - p2[1][1])
+ print_("Orientation2 p1 p2 ol oluu", p1, p2, ol, oluu)
+ orientation_scale = ol / oluu
+
+ self.set_tool(layer)
+ shape = self.tools[layer][0]['shape']
+ if re.search('w', shape):
+ toolshape = eval('lambda w: ' + shape.strip('"'))
+ else:
+ self.error("Tool '{}' has no shape. 45 degree cone assumed!".format(self.tools[layer][0]['name']))
+ toolshape = lambda w: w
+ # Get tool radius in pixels
+ toolr = self.tools[layer][0]['diameter'] * orientation_scale / 2
+ print_("tool radius in pixels=", toolr)
+ # max dist from path to engrave in user's units
+ max_distuu = min(self.tools[layer][0]['diameter'] / 2, self.options.engraving_max_dist)
+ max_dist = max_distuu * orientation_scale
+ print_("max_dist pixels", max_dist)
+
+ engraving_group = self.selected_paths[layer][0].getparent().add(Group())
+ if self.options.engraving_draw_calculation_paths and (self.my3Dlayer is None):
+ self.svg.add(Layer.new("3D"))
+ # Create groups for left and right eyes
+ if self.options.engraving_draw_calculation_paths:
+ gcode_3Dleft = self.my3Dlayer.add(Group(gcodetools="Gcode 3D L"))
+ gcode_3Dright = self.my3Dlayer.add(Group(gcodetools="Gcode 3D R"))
+
+ for node in self.selected_paths[layer]:
+ if isinstance(node, inkex.PathElement):
+ cspi = node.path.to_superpath()
+ # LT: Create my own list. n1LT[j] is for subpath j
+ nlLT = []
+ for j in xrange(len(cspi)): # LT For each subpath...
+ # Remove zero length segments, assume closed path
+ i = 0 # LT was from i=1
+ while i < len(cspi[j]):
+ if abs(cspi[j][i - 1][1][0] - cspi[j][i][1][0]) < ENGRAVING_TOLERANCE and abs(cspi[j][i - 1][1][1] - cspi[j][i][1][1]) < ENGRAVING_TOLERANCE:
+ cspi[j][i - 1][2] = cspi[j][i][2]
+ del cspi[j][i]
+ else:
+ i += 1
+ for csp in cspi: # LT6a For each subpath...
+ # Create copies in 3D layer
+ print_("csp is zz ", csp)
+ cspl = []
+ cspr = []
+ # create list containing lines and points, starting with a point
+ # line members: [x,y],[nx,ny],False,i
+ # x,y is start of line. Normal on engraved side.
+ # Normal is normalised (unit length)
+ # Note that Y axis increases down the page
+ # corner members: [x,y],[nx,ny],True,sin(halfangle)
+ # if halfangle>0: radius 0 here. normal is bisector
+ # if halfangle<0. reflex angle. normal is bisector
+ # corner normals are divided by cos(halfangle)
+ # so that they will engrave correctly
+ print_("csp is", csp)
+ nlLT.append([])
+ for i in range(0, len(csp)): # LT for each point
+ sp0 = csp[i - 2]
+ sp1 = csp[i - 1]
+ sp2 = csp[i]
+ if self.options.engraving_draw_calculation_paths:
+ # Copy it to 3D layer objects
+ spl = []
+ spr = []
+ for j in range(0, 3):
+ pl = [sp2[j][0] - eye_dist, sp2[j][1]]
+ pr = [sp2[j][0] + eye_dist, sp2[j][1]]
+ spl += [pl]
+ spr += [pr]
+ cspl += [spl]
+ cspr += [spr]
+ # LT find angle between this and previous segment
+ x0, y0 = sp1[1]
+ nx1, ny1 = csp_normalized_normal(sp1, sp2, 0)
+ # I don't trust this function, so test result
+ if abs(1 - math.hypot(nx1, ny1)) > 0.00001:
+ print_("csp_normalised_normal error t=0", nx1, ny1, sp1, sp2)
+ self.error("csp_normalised_normal error. See log.")
+
+ nx0, ny0 = csp_normalized_normal(sp0, sp1, 1)
+ if abs(1 - math.hypot(nx0, ny0)) > 0.00001:
+ print_("csp_normalised_normal error t=1", nx0, ny0, sp1, sp2)
+ self.error("csp_normalised_normal error. See log.")
+ bx, by, s = bisect((nx0, ny0), (nx1, ny1))
+ # record x,y,normal,ifCorner, sin(angle-turned/2)
+ nlLT[-1] += [[[x0, y0], [bx, by], True, s]]
+
+ # LT now do the line
+ if sp1[1] == sp1[2] and sp2[0] == sp2[1]: # straightline
+ nlLT[-1] += [[sp1[1], [nx1, ny1], False, i]]
+ else: # Bezier. First, recursively cut it up:
+ nn = bez_divide(sp1[1], sp1[2], sp2[0], sp2[1])
+ first = True # Flag entry to divided Bezier
+ for bLT in nn: # save as two line segments
+ for seg in range(3):
+ if seg > 0 or first:
+ nx1 = bLT[seg][1] - bLT[seg + 1][1]
+ ny1 = bLT[seg + 1][0] - bLT[seg][0]
+ l1 = math.hypot(nx1, ny1)
+ if l1 < ENGRAVING_TOLERANCE:
+ continue
+ nx1 = nx1 / l1 # normalise them
+ ny1 = ny1 / l1
+ nlLT[-1] += [[bLT[seg], [nx1, ny1], False, i]]
+ first = False
+ if seg < 2: # get outgoing bisector
+ nx0 = nx1
+ ny0 = ny1
+ nx1 = bLT[seg + 1][1] - bLT[seg + 2][1]
+ ny1 = bLT[seg + 2][0] - bLT[seg + 1][0]
+ l1 = math.hypot(nx1, ny1)
+ if l1 < ENGRAVING_TOLERANCE:
+ continue
+ nx1 = nx1 / l1 # normalise them
+ ny1 = ny1 / l1
+ # bisect
+ bx, by, s = bisect((nx0, ny0), (nx1, ny1))
+ nlLT[-1] += [[bLT[seg + 1], [bx, by], True, 0.]]
+ # LT for each segment - ends here.
+ print_(("engraving_draw_calculation_paths=", self.options.engraving_draw_calculation_paths))
+ if self.options.engraving_draw_calculation_paths:
+ # Copy complete paths to 3D layer
+ cspl += [cspl[0]] # Close paths
+ cspr += [cspr[0]] # Close paths
+ style = "stroke:#808080; stroke-opacity:1; stroke-width:0.6; fill:none"
+ elem = gcode_3Dleft.add(PathElement(style=style, gcodetools="G1L outline"))
+ elem.path = CubicSuperPath([cspl])
+ elem = gcode_3Dright.add(Pathelement(style=style, gcodetools="G1R outline"))
+ elem.path = CubicSuperPath([cspr])
+
+ for p in nlLT[-1]: # For last sub-path
+ if p[2]:
+ elem = engraving_group.add(PathElement(gcodetools="Engraving normals"))
+ elem.path = "M {:f},{:f} L {:f},{:f}".format(p[0][0], p[0][1],
+ p[0][0] + p[1][0] * 10, p[0][1] + p[1][1] * 10)
+ elem.style = "stroke:#f000af; stroke-opacity:0.46; stroke-width:0.1; fill:none"
+ else:
+ elem = engraving_group.add(PathElement(gcodetools="Engraving bisectors"))
+ elem.path = "M {:f},{:f} L {:f},{:f}".format(p[0][0], p[0][1],
+ p[0][0] + p[1][0] * 10, p[0][1] + p[1][1] * 10)
+ elem.style = "stroke:#0000ff; stroke-opacity:0.46; stroke-width:0.1; fill:none"
+
+ # LT6a build nlLT[j] for each subpath - ends here
+ # Calculate offset points
+ reflex = False
+ for j in xrange(len(nlLT)): # LT6b for each subpath
+ cspm = [] # Will be my output. List of csps.
+ wl = [] # Will be my w output list
+ w = r = 0 # LT initial, as first point is an angle
+ for i in xrange(len(nlLT[j])): # LT for each node
+ # LT Note: Python enables wrapping of array indices
+ # backwards to -1, -2, but not forwards. Hence:
+ n0 = nlLT[j][i - 2] # previous node
+ n1 = nlLT[j][i - 1] # current node
+ n2 = nlLT[j][i] # next node
+ # if n1[2] == True and n1[3]==0 : # A straight angle
+ # continue
+ x1a, y1a = n1[0] # this point/start of this line
+ nx, ny = n1[1]
+ x1b, y1b = n2[0] # next point/end of this line
+ if n1[2]: # We're at a corner
+ bits = 1
+ bit0 = 0
+ # lastr=r #Remember r from last line
+ lastw = w # Remember w from last line
+ w = max_dist
+ if n1[3] > 0: # acute. Limit radius
+ len1 = math.hypot((n0[0][0] - n1[0][0]), (n0[0][1] - n1[0][1]))
+ if i < (len(nlLT[j]) - 1):
+ len2 = math.hypot((nlLT[j][i + 1][0][0] - n1[0][0]), (nlLT[j][i + 1][0][1] - n1[0][1]))
+ else:
+ len2 = math.hypot((nlLT[j][0][0][0] - n1[0][0]), (nlLT[j][0][0][1] - n1[0][1]))
+ # set initial r value, not to be exceeded
+ w = math.sqrt(min(len1, len2)) / n1[3]
+ else: # line. Cut it up if long.
+ if n0[3] > 0 and not self.options.engraving_draw_calculation_paths:
+ bit0 = r * n0[3] # after acute corner
+ else:
+ bit0 = 0.0
+ length = math.hypot((x1b - x1a), (y1a - y1b))
+ bit0 = (min(length, bit0))
+ bits = int((length - bit0) / bitlen)
+ # split excess evenly at both ends
+ bit0 += (length - bit0 - bitlen * bits) / 2
+ for b in xrange(bits): # divide line into bits
+ x1 = x1a + ny * (b * bitlen + bit0)
+ y1 = y1a - nx * (b * bitlen + bit0)
+ jjmin, iimin, w = get_biggest((x1, y1), (nx, ny))
+ print_("i,j,jjmin,iimin,w", i, j, jjmin, iimin, w)
+ wmax = max(wmax, w)
+ if reflex: # just after a reflex corner
+ reflex = False
+ if w < lastw: # need to adjust it
+ draw_point((x1, y1), (n0[0][0] + n0[1][0] * w, n0[0][1] + n0[1][1] * w), w, (lastw - w) / 2)
+ save_point((n0[0][0] + n0[1][0] * w, n0[0][1] + n0[1][1] * w), w, i, j, iimin, jjmin)
+ if n1[2]: # We're at a corner
+ if n1[3] > 0: # acute
+ save_point((x1 + nx * w, y1 + ny * w), w, i, j, iimin, jjmin)
+ draw_point((x1, y1), (x1, y1), 0, 0)
+ save_point((x1, y1), 0, i, j, iimin, jjmin)
+ elif n1[3] < 0: # reflex
+ if w > lastw:
+ draw_point((x1, y1), (x1 + nx * lastw, y1 + ny * lastw), w, (w - lastw) / 2)
+ wmax = max(wmax, w)
+ save_point((x1 + nx * w, y1 + ny * w), w, i, j, iimin, jjmin)
+ elif b > 0 and n2[3] > 0 and not self.options.engraving_draw_calculation_paths: # acute corner coming up
+ if jjmin == j and iimin == i + 2:
+ break
+ draw_point((x1, y1), (x1 + nx * w, y1 + ny * w), w, bitlen)
+ save_point((x1 + nx * w, y1 + ny * w), w, i, j, iimin, jjmin)
+
+ # LT end of for each bit of this line
+ if n1[2] == True and n1[3] < 0: # reflex angle
+ reflex = True
+ lastw = w # remember this w
+ # LT next i
+ cspm += [cspm[0]]
+ print_("cspm", cspm)
+ wl += [wl[0]]
+ print_("wl", wl)
+ # Note: Original csp_points was a list, each element
+ # being 4 points, with the first being the same as the
+ # last of the previous set.
+ # Each point is a list of [cx,cy,r,w]
+ # I have flattened it to a flat list of points.
+
+ if self.options.engraving_draw_calculation_paths:
+ node = engraving_group.add(PathElement(
+ gcodetools="Engraving calculation paths",
+ style=MARKER_STYLE["biarc_style_i"]['biarc1']))
+ node.path = CubicSuperPath([cspm])
+ for i in xrange(len(cspm)):
+ elem = engraving_group.add(PathElement.arc(cspm[i][1], wl[i]))
+ elem.set('gcodetools', "Engraving calculation paths")
+ elem.style = "fill:none;fill-opacity:0.46;stroke:#000000;stroke-width:0.1;"
+ cspe += [cspm]
+ wluu = [] # width list in user units: mm/inches
+ for w in wl:
+ wluu += [w / orientation_scale]
+ print_("wl in pixels", wl)
+ print_("wl in user units", wluu)
+ # LT previously, we was in pixels so gave wrong depth
+ we += [wluu]
+ # LT6b For each subpath - ends here
+ # LT5 if it is a path - ends here
+ # LT4 for each selected object in this layer - ends here
+
+ if cspe:
+ curve = self.parse_curve(cspe, layer, we, toolshape) # convert to lines
+ self.draw_curve(curve, layer, engraving_group)
+ gcode += self.generate_gcode(curve, layer, self.options.Zsurface)
+
+ # LT3 for layers loop ends here
+ if gcode != '':
+ self.header += "(Tool diameter should be at least " + str(2 * wmax / orientation_scale) + unit + ")\n"
+ self.header += "(Depth, as a function of radius w, must be " + self.tools[layer][0]['shape'] + ")\n"
+ self.header += "(Rapid feeds use safe Z=" + str(self.options.Zsafe) + unit + ")\n"
+ self.header += "(Material surface at Z=" + str(self.options.Zsurface) + unit + ")\n"
+ self.export_gcode(gcode)
+ else:
+ self.error("No need to engrave sharp angles.")
+
+ ################################################################################
+ #
+ # Orientation
+ #
+ ################################################################################
+ def tab_orientation(self, layer=None):
+ self.get_info()
+ Zsurface = f"{self.options.Zsurface:.5f}"
+ Zdepth = f"{self.options.Zdepth:.5f}"
+ if layer is None:
+ layer = self.svg.get_current_layer() if self.svg.get_current_layer() is not None else self.document.getroot()
+
+ transform = self.get_transforms(layer)
+ if transform:
+ transform = self.reverse_transform(transform)
+ transform = str(Transform(transform))
+
+ if self.options.orientation_points_count == "graffiti":
+ print_(self.graffiti_reference_points)
+ print_("Inserting graffiti points")
+ if layer in self.graffiti_reference_points:
+ graffiti_reference_points_count = len(self.graffiti_reference_points[layer])
+ else:
+ graffiti_reference_points_count = 0
+ axis = ["X", "Y", "Z", "A"][graffiti_reference_points_count % 4]
+ attr = {'gcodetools': "Gcodetools graffiti reference point"}
+ if transform:
+ attr["transform"] = transform
+ group = layer.add(Group(**attr))
+ elem = group.add(PathElement(style="stroke:none;fill:#00ff00;"))
+ elem.set('gcodetools', "Gcodetools graffiti reference point arrow")
+ elem.path = 'm {},{} 2.9375,-6.343750000001 0.8125,1.90625 6.843748640396,'\
+ '-6.84374864039 0,0 0.6875,0.6875 -6.84375,6.84375 1.90625,0.8125000000'\
+ '01 z z'.format(graffiti_reference_points_count * 100, 0)
+
+ draw_text(axis, graffiti_reference_points_count * 100 + 10, -10, group=group, gcodetools_tag="Gcodetools graffiti reference point text")
+
+ elif self.options.orientation_points_count == "in-out reference point":
+ draw_pointer(group=self.svg.get_current_layer(), x=self.svg.namedview.center, figure="arrow", pointer_type="In-out reference point", text="In-out point")
+
+ else:
+ print_("Inserting orientation points")
+
+ if layer in self.orientation_points:
+ self.error("Active layer already has orientation points! Remove them or select another layer!", "error")
+
+ attr = {"gcodetools": "Gcodetools orientation group"}
+ if transform:
+ attr["transform"] = transform
+
+ orientation_group = layer.add(Group(**attr))
+ doc_height = self.svg.unittouu(self.document.getroot().get('height'))
+ if self.document.getroot().get('height') == "100%":
+ doc_height = 1052.3622047
+ print_("Overriding height from 100 percents to {}".format(doc_height))
+ if self.options.unit == "G21 (All units in mm)":
+ points = [[0., 0., Zsurface], [100., 0., Zdepth], [0., 100., 0.]]
+ elif self.options.unit == "G20 (All units in inches)":
+ points = [[0., 0., Zsurface], [5., 0., Zdepth], [0., 5., 0.]]
+ if self.options.orientation_points_count == "2":
+ points = points[:2]
+ for i in points:
+ name = "Gcodetools orientation point ({} points)".format(
+ self.options.orientation_points_count)
+ grp = orientation_group.add(Group(gcodetools=name))
+ elem = grp.add(PathElement(style="stroke:none;fill:#000000;"))
+ elem.set('gcodetools', "Gcodetools orientation point arrow")
+ elem.path = 'm {},{} 2.9375,-6.343750000001 0.8125,1.90625 6.843748640396,'\
+ '-6.84374864039 0,0 0.6875,0.6875 -6.84375,6.84375 1.90625,0.812500000'\
+ '001 z'.format(i[0], -i[1] + doc_height)
+
+ draw_text("({}; {}; {})".format(i[0], i[1], i[2]), (i[0] + 10), (-i[1] - 10 + doc_height), group=grp, gcodetools_tag="Gcodetools orientation point text")
+
+ ################################################################################
+ #
+ # Tools library
+ #
+ ################################################################################
+ def tab_tools_library(self, layer=None):
+ self.get_info()
+
+ if self.options.tools_library_type == "check":
+ return self.check_tools_and_op()
+
+ # Add a tool to the drawing
+ if layer is None:
+ layer = self.svg.get_current_layer() if self.svg.get_current_layer() is not None else self.document.getroot()
+ if layer in self.tools:
+ self.error("Active layer already has a tool! Remove it or select another layer!", "error")
+
+ if self.options.tools_library_type == "cylinder cutter":
+ tool = {
+ "name": "Cylindrical cutter",
+ "id": "Cylindrical cutter 0001",
+ "diameter": 10,
+ "penetration angle": 90,
+ "feed": "400",
+ "penetration feed": "100",
+ "depth step": "1",
+ "tool change gcode": " "
+ }
+ elif self.options.tools_library_type == "lathe cutter":
+ tool = {
+ "name": "Lathe cutter",
+ "id": "Lathe cutter 0001",
+ "diameter": 10,
+ "penetration angle": 90,
+ "feed": "400",
+ "passing feed": "800",
+ "fine feed": "100",
+ "penetration feed": "100",
+ "depth step": "1",
+ "tool change gcode": " "
+ }
+ elif self.options.tools_library_type == "cone cutter":
+ tool = {
+ "name": "Cone cutter",
+ "id": "Cone cutter 0001",
+ "diameter": 10,
+ "shape": "w",
+ "feed": "400",
+ "penetration feed": "100",
+ "depth step": "1",
+ "tool change gcode": " "
+ }
+ elif self.options.tools_library_type == "tangent knife":
+ tool = {
+ "name": "Tangent knife",
+ "id": "Tangent knife 0001",
+ "feed": "400",
+ "penetration feed": "100",
+ "depth step": "100",
+ "4th axis meaning": "tangent knife",
+ "4th axis scale": 1.,
+ "4th axis offset": 0,
+ "tool change gcode": " "
+ }
+
+ elif self.options.tools_library_type == "plasma cutter":
+ tool = {
+ "name": "Plasma cutter",
+ "id": "Plasma cutter 0001",
+ "diameter": 10,
+ "penetration feed": 100,
+ "feed": 400,
+ "gcode before path": """G31 Z-100 F500 (find metal)
+G92 Z0 (zero z)
+G00 Z10 F500 (going up)
+M03 (turn on plasma)
+G04 P0.2 (pause)
+G01 Z1 (going to cutting z)\n""",
+ "gcode after path": "M05 (turn off plasma)\n",
+ }
+ elif self.options.tools_library_type == "graffiti":
+ tool = {
+ "name": "Graffiti",
+ "id": "Graffiti 0001",
+ "diameter": 10,
+ "penetration feed": 100,
+ "feed": 400,
+ "gcode before path": """M03 S1(Turn spray on)\n """,
+ "gcode after path": "M05 (Turn spray off)\n ",
+ "tool change gcode": "(Add G00 here to change sprayer if needed)\n",
+
+ }
+
+ else:
+ tool = self.default_tool
+
+ tool_num = sum([len(self.tools[i]) for i in self.tools])
+ colors = ["00ff00", "0000ff", "ff0000", "fefe00", "00fefe", "fe00fe", "fe7e00", "7efe00", "00fe7e", "007efe", "7e00fe", "fe007e"]
+
+ tools_group = layer.add(Group(gcodetools="Gcodetools tool definition"))
+ bg = tools_group.add(PathElement(gcodetools="Gcodetools tool background"))
+ bg.style = "fill-opacity:0.5;stroke:#444444;"
+ bg.style['fill'] = "#" + colors[tool_num % len(colors)]
+
+ y = 0
+ keys = []
+ for key in self.tools_field_order:
+ if key in tool:
+ keys += [key]
+ for key in tool:
+ if key not in keys:
+ keys += [key]
+ for key in keys:
+ g = tools_group.add(Group(gcodetools="Gcodetools tool parameter"))
+ draw_text(key, 0, y, group=g, gcodetools_tag="Gcodetools tool definition field name", font_size=10 if key != 'name' else 20)
+ param = tool[key]
+ if type(param) == str and re.match("^\\s*$", param):
+ param = "(None)"
+ draw_text(param, 150, y, group=g, gcodetools_tag="Gcodetools tool definition field value", font_size=10 if key != 'name' else 20)
+ v = str(param).split("\n")
+ y += 15 * len(v) if key != 'name' else 20 * len(v)
+
+ bg.set('d', "m -20,-20 l 400,0 0,{:f} -400,0 z ".format(y + 50))
+ tools_group.transform.add_translate(*self.svg.namedview.center)
+ tools_group.transform.add_translate(-150, 0)
+
+ ################################################################################
+ #
+ # Check tools and OP assignment
+ #
+ ################################################################################
+ def check_tools_and_op(self):
+ if len(self.svg.selected) <= 0:
+ self.error("Selection is empty! Will compute whole drawing.")
+ paths = self.paths
+ else:
+ paths = self.selected_paths
+ # Set group
+ parent = self.selected_paths.keys()[0] if len(self.selected_paths.keys()) > 0 else self.layers[0]
+ group = parent.add(Group())
+ trans_ = [[1, 0.3, 0], [0, 0.5, 0]]
+
+ self.set_markers()
+
+ bounds = [float('inf'), float('inf'), float('-inf'), float('-inf')]
+ tools_bounds = {}
+ for layer in self.layers:
+ if layer in paths:
+ self.set_tool(layer)
+ tool = self.tools[layer][0]
+ tools_bounds[layer] = tools_bounds[layer] if layer in tools_bounds else [float("inf"), float("-inf")]
+ for path in paths[layer]:
+ group.insert(0, PathElement(**path.attrib))
+ new = group.getchildren()[0]
+ new.style = Style(
+ stroke='#000044', stroke_width=1,
+ marker_mid='url(#CheckToolsAndOPMarker)',
+ fill=tool["style"].get('fill', '#00ff00'),
+ fill_opacity=tool["style"].get('fill-opacity', 0.5))
+
+ trans = trans_ * self.get_transforms(path)
+ csp = path.path.transform(trans).to_superpath()
+
+ path_bounds = csp_simple_bound(csp)
+ trans = str(Transform(trans))
+ bounds = [min(bounds[0], path_bounds[0]), min(bounds[1], path_bounds[1]), max(bounds[2], path_bounds[2]), max(bounds[3], path_bounds[3])]
+ tools_bounds[layer] = [min(tools_bounds[layer][0], path_bounds[1]), max(tools_bounds[layer][1], path_bounds[3])]
+
+ new.set("transform", trans)
+ trans_[1][2] += 20
+ trans_[1][2] += 100
+
+ for layer in self.layers:
+ if layer in self.tools:
+ if layer in tools_bounds:
+ tool = self.tools[layer][0]
+ g = copy.deepcopy(tool["self_group"])
+ g.attrib["gcodetools"] = "Check tools and OP assignment"
+ trans = [[1, 0.3, bounds[2]], [0, 0.5, tools_bounds[layer][0]]]
+ g.set("transform", str(Transform(trans)))
+ group.insert(0, g)
+
+ ################################################################################
+ # TODO Launch browser on help tab
+ ################################################################################
+ def tab_help(self):
+ self.error("Switch to another tab to run the extensions.\n"
+ "No changes are made if the preferences or help tabs are active.\n\n"
+ "Tutorials, manuals and support can be found at\n"
+ " English support forum:\n"
+ " http://www.cnc-club.ru/gcodetools\n"
+ "and Russian support forum:\n"
+ " http://www.cnc-club.ru/gcodetoolsru")
+ return
+
+ def tab_about(self):
+ return self.tab_help()
+
+ def tab_preferences(self):
+ return self.tab_help()
+
+ def tab_options(self):
+ return self.tab_help()
+
+
+ ################################################################################
+ # Lathe
+ ################################################################################
+ def generate_lathe_gcode(self, subpath, layer, feed_type):
+ if len(subpath) < 2:
+ return ""
+ feed = " F {:f}".format(self.tool[feed_type])
+ x = self.options.lathe_x_axis_remap
+ z = self.options.lathe_z_axis_remap
+ flip_angle = -1 if x.lower() + z.lower() in ["xz", "yx", "zy"] else 1
+ alias = {"X": "I", "Y": "J", "Z": "K", "x": "i", "y": "j", "z": "k"}
+ i_ = alias[x]
+ k_ = alias[z]
+ c = [[subpath[0][1], "move", 0, 0, 0]]
+ for sp1, sp2 in zip(subpath, subpath[1:]):
+ c += biarc(sp1, sp2, 0, 0)
+ for i in range(1, len(c)): # Just in case check end point of each segment
+ c[i - 1][4] = c[i][0][:]
+ c += [[subpath[-1][1], "end", 0, 0, 0]]
+ self.draw_curve(c, layer, style=MARKER_STYLE["biarc_style_lathe_{}".format(feed_type)])
+
+ gcode = ("G01 {} {:f} {} {:f}".format(x, c[0][4][0], z, c[0][4][1])) + feed + "\n" # Just in case move to the start...
+ for s in c:
+ if s[1] == 'line':
+ gcode += ("G01 {} {:f} {} {:f}".format(x, s[4][0], z, s[4][1])) + feed + "\n"
+ elif s[1] == 'arc':
+ r = [(s[2][0] - s[0][0]), (s[2][1] - s[0][1])]
+ if (r[0] ** 2 + r[1] ** 2) > self.options.min_arc_radius ** 2:
+ r1 = (P(s[0]) - P(s[2]))
+ r2 = (P(s[4]) - P(s[2]))
+ if abs(r1.mag() - r2.mag()) < 0.001:
+ gcode += ("G02" if s[3] * flip_angle < 0 else "G03") + (" {} {:f} {} {:f} {} {:f} {} {:f}".format(x, s[4][0], z, s[4][1], i_, (s[2][0] - s[0][0]), k_, (s[2][1] - s[0][1]))) + feed + "\n"
+ else:
+ r = (r1.mag() + r2.mag()) / 2
+ gcode += ("G02" if s[3] * flip_angle < 0 else "G03") + (" {} {:f} {} {:f}".format(x, s[4][0], z, s[4][1])) + " R{:f}".format(r) + feed + "\n"
+ return gcode
+
+ def tab_lathe(self):
+ self.get_info_plus()
+ if not self.check_dir():
+ return
+ x = self.options.lathe_x_axis_remap
+ z = self.options.lathe_z_axis_remap
+ x = re.sub("^\\s*([XYZxyz])\\s*$", r"\1", x)
+ z = re.sub("^\\s*([XYZxyz])\\s*$", r"\1", z)
+ if x not in ["X", "Y", "Z", "x", "y", "z"] or z not in ["X", "Y", "Z", "x", "y", "z"]:
+ self.error("Lathe X and Z axis remap should be 'X', 'Y' or 'Z'. Exiting...")
+ return
+ if x.lower() == z.lower():
+ self.error("Lathe X and Z axis remap should be the same. Exiting...")
+ return
+ if x.lower() + z.lower() in ["xy", "yx"]:
+ gcode_plane_selection = "G17 (Using XY plane)\n"
+ if x.lower() + z.lower() in ["xz", "zx"]:
+ gcode_plane_selection = "G18 (Using XZ plane)\n"
+ if x.lower() + z.lower() in ["zy", "yz"]:
+ gcode_plane_selection = "G19 (Using YZ plane)\n"
+ self.options.lathe_x_axis_remap = x
+ self.options.lathe_z_axis_remap = z
+
+ paths = self.selected_paths
+ self.tool = []
+ gcode = ""
+ for layer in self.layers:
+ if layer in paths:
+ self.set_tool(layer)
+ if self.tool != self.tools[layer][0]:
+ self.tool = self.tools[layer][0]
+ self.tool["passing feed"] = float(self.tool["passing feed"] if "passing feed" in self.tool else self.tool["feed"])
+ self.tool["feed"] = float(self.tool["feed"])
+ self.tool["fine feed"] = float(self.tool["fine feed"] if "fine feed" in self.tool else self.tool["feed"])
+ gcode += ("(Change tool to {})\n".format(re.sub("\"'\\(\\)\\\\", " ", self.tool["name"]))) + self.tool["tool change gcode"] + "\n"
+
+ for path in paths[layer]:
+ csp = self.transform_csp(path.path.to_superpath(), layer)
+
+ for subpath in csp:
+ # Offset the path if fine cut is defined.
+ fine_cut = subpath[:]
+ if self.options.lathe_fine_cut_width > 0:
+ r = self.options.lathe_fine_cut_width
+ if self.options.lathe_create_fine_cut_using == "Move path":
+ subpath = [[[i2[0], i2[1] + r] for i2 in i1] for i1 in subpath]
+ else:
+ # Close the path to make offset correct
+ bound = csp_simple_bound([subpath])
+ minx, miny, maxx, maxy = csp_true_bounds([subpath])
+ offsetted_subpath = csp_subpath_line_to(subpath[:], [[subpath[-1][1][0], miny[1] - r * 10], [subpath[0][1][0], miny[1] - r * 10], [subpath[0][1][0], subpath[0][1][1]]])
+ left = subpath[-1][1][0]
+ right = subpath[0][1][0]
+ if left > right:
+ left, right = right, left
+ offsetted_subpath = csp_offset([offsetted_subpath], r if not csp_subpath_ccw(offsetted_subpath) else -r)
+ offsetted_subpath = csp_clip_by_line(offsetted_subpath, [left, 10], [left, 0])
+ offsetted_subpath = csp_clip_by_line(offsetted_subpath, [right, 0], [right, 10])
+ offsetted_subpath = csp_clip_by_line(offsetted_subpath, [0, miny[1] - r], [10, miny[1] - r])
+ # Join offsetted_subpath together
+ # Hope there won't be any circles
+ subpath = csp_join_subpaths(offsetted_subpath)[0]
+
+ # Create solid object from path and lathe_width
+ bound = csp_simple_bound([subpath])
+ top_start = [subpath[0][1][0], self.options.lathe_width + self.options.Zsafe + self.options.lathe_fine_cut_width]
+ top_end = [subpath[-1][1][0], self.options.lathe_width + self.options.Zsafe + self.options.lathe_fine_cut_width]
+
+ gcode += ("G01 {} {:f} F {:f} \n".format(z, top_start[1], self.tool["passing feed"]))
+ gcode += ("G01 {} {:f} {} {:f} F {:f} \n".format(x, top_start[0], z, top_start[1], self.tool["passing feed"]))
+
+ subpath = csp_concat_subpaths(csp_subpath_line_to([], [top_start, subpath[0][1]]), subpath)
+ subpath = csp_subpath_line_to(subpath, [top_end, top_start])
+
+ width = max(0, self.options.lathe_width - max(0, bound[1]))
+ step = self.tool['depth step']
+ steps = int(math.ceil(width / step))
+ for i in range(steps + 1):
+ current_width = self.options.lathe_width - step * i
+ intersections = []
+ for j in range(1, len(subpath)):
+ sp1 = subpath[j - 1]
+ sp2 = subpath[j]
+ intersections += [[j, k] for k in csp_line_intersection([bound[0] - 10, current_width], [bound[2] + 10, current_width], sp1, sp2)]
+ intersections += [[j, k] for k in csp_line_intersection([bound[0] - 10, current_width + step], [bound[2] + 10, current_width + step], sp1, sp2)]
+ parts = csp_subpath_split_by_points(subpath, intersections)
+ for part in parts:
+ minx, miny, maxx, maxy = csp_true_bounds([part])
+ y = (maxy[1] + miny[1]) / 2
+ if y > current_width + step:
+ gcode += self.generate_lathe_gcode(part, layer, "passing feed")
+ elif current_width <= y <= current_width + step:
+ gcode += self.generate_lathe_gcode(part, layer, "feed")
+ else:
+ # full step cut
+ part = csp_subpath_line_to([], [part[0][1], part[-1][1]])
+ gcode += self.generate_lathe_gcode(part, layer, "feed")
+
+ top_start = [fine_cut[0][1][0], self.options.lathe_width + self.options.Zsafe + self.options.lathe_fine_cut_width]
+ top_end = [fine_cut[-1][1][0], self.options.lathe_width + self.options.Zsafe + self.options.lathe_fine_cut_width]
+ gcode += "\n(Fine cutting start)\n(Calculating fine cut using {})\n".format(self.options.lathe_create_fine_cut_using)
+ for i in range(int(self.options.lathe_fine_cut_count)):
+ width = self.options.lathe_fine_cut_width * (1 - float(i + 1) / self.options.lathe_fine_cut_count)
+ if width == 0:
+ current_pass = fine_cut
+ else:
+ if self.options.lathe_create_fine_cut_using == "Move path":
+ current_pass = [[[i2[0], i2[1] + width] for i2 in i1] for i1 in fine_cut]
+ else:
+ minx, miny, maxx, maxy = csp_true_bounds([fine_cut])
+ offsetted_subpath = csp_subpath_line_to(fine_cut[:], [[fine_cut[-1][1][0], miny[1] - r * 10], [fine_cut[0][1][0], miny[1] - r * 10], [fine_cut[0][1][0], fine_cut[0][1][1]]])
+ left = fine_cut[-1][1][0]
+ right = fine_cut[0][1][0]
+ if left > right:
+ left, right = right, left
+ offsetted_subpath = csp_offset([offsetted_subpath], width if not csp_subpath_ccw(offsetted_subpath) else -width)
+ offsetted_subpath = csp_clip_by_line(offsetted_subpath, [left, 10], [left, 0])
+ offsetted_subpath = csp_clip_by_line(offsetted_subpath, [right, 0], [right, 10])
+ offsetted_subpath = csp_clip_by_line(offsetted_subpath, [0, miny[1] - r], [10, miny[1] - r])
+ current_pass = csp_join_subpaths(offsetted_subpath)[0]
+
+ gcode += "\n(Fine cut {:d}-th cicle start)\n".format(i + 1)
+ gcode += ("G01 {} {:f} {} {:f} F {:f} \n".format(x, top_start[0], z, top_start[1], self.tool["passing feed"]))
+ gcode += ("G01 {} {:f} {} {:f} F {:f} \n".format(x, current_pass[0][1][0], z, current_pass[0][1][1] + self.options.lathe_fine_cut_width, self.tool["passing feed"]))
+ gcode += ("G01 {} {:f} {} {:f} F {:f} \n".format(x, current_pass[0][1][0], z, current_pass[0][1][1], self.tool["fine feed"]))
+
+ gcode += self.generate_lathe_gcode(current_pass, layer, "fine feed")
+ gcode += ("G01 {} {:f} F {:f} \n".format(z, top_start[1], self.tool["passing feed"]))
+ gcode += ("G01 {} {:f} {} {:f} F {:f} \n".format(x, top_start[0], z, top_start[1], self.tool["passing feed"]))
+
+ self.export_gcode(gcode)
+
+ ################################################################################
+ #
+ # Lathe modify path
+ # Modifies path to fit current cutter. As for now straight rect cutter.
+ #
+ ################################################################################
+
+ def tab_lathe_modify_path(self):
+ self.get_info()
+ if self.selected_paths == {} and self.options.auto_select_paths:
+ paths = self.paths
+ self.error("No paths are selected! Trying to work on all available paths.")
+ else:
+ paths = self.selected_paths
+
+ for layer in self.layers:
+ if layer in paths:
+ width = self.options.lathe_rectangular_cutter_width
+ for path in paths[layer]:
+ csp = self.transform_csp(path.path.to_superpath(), layer)
+ new_csp = []
+ for subpath in csp:
+ orientation = subpath[-1][1][0] > subpath[0][1][0]
+ new_subpath = []
+
+ # Split segment at x' and y' == 0
+ for sp1, sp2 in zip(subpath[:], subpath[1:]):
+ ax, ay, bx, by, cx, cy, dx, dy = csp_parameterize(sp1, sp2)
+ roots = cubic_solver_real(0, 3 * ax, 2 * bx, cx)
+ roots += cubic_solver_real(0, 3 * ay, 2 * by, cy)
+ new_subpath = csp_concat_subpaths(new_subpath, csp_seg_split(sp1, sp2, roots))
+ subpath = new_subpath
+ new_subpath = []
+ first_seg = True
+ for sp1, sp2 in zip(subpath[:], subpath[1:]):
+ n = csp_normalized_normal(sp1, sp2, 0)
+ a = math.atan2(n[0], n[1])
+ if a == 0 or a == math.pi:
+ n = csp_normalized_normal(sp1, sp2, 1)
+ a = math.atan2(n[0], n[1])
+ if a != 0 and a != math.pi:
+ o = 0 if 0 < a <= math.pi / 2 or -math.pi < a < -math.pi / 2 else 1
+ if not orientation:
+ o = 1 - o
+
+ # Add first horizontal straight line if needed
+ if not first_seg and new_subpath == []:
+ new_subpath = [[[subpath[0][i][0] - width * o, subpath[0][i][1]] for i in range(3)]]
+
+ new_subpath = csp_concat_subpaths(
+ new_subpath,
+ [
+ [[sp1[i][0] - width * o, sp1[i][1]] for i in range(3)],
+ [[sp2[i][0] - width * o, sp2[i][1]] for i in range(3)]
+ ]
+ )
+ first_seg = False
+
+ # Add last horizontal straight line if needed
+ if a == 0 or a == math.pi:
+ new_subpath += [[[subpath[-1][i][0] - width * o, subpath[-1][i][1]] for i in range(3)]]
+
+ new_csp += [new_subpath]
+ self.draw_csp(new_csp, layer)
+
+ ################################################################################
+ # Graffiti function generates Gcode for graffiti drawer
+ ################################################################################
+ def tab_graffiti(self):
+ self.get_info_plus()
+ # Get reference points.
+
+ def get_gcode_coordinates(point, layer):
+ gcode = ''
+ pos = []
+ for ref_point in self.graffiti_reference_points[layer]:
+ c = math.sqrt((point[0] - ref_point[0][0]) ** 2 + (point[1] - ref_point[0][1]) ** 2)
+ gcode += " {} {:f}".format(ref_point[1], c)
+ pos += [c]
+ return pos, gcode
+
+ def graffiti_preview_draw_point(x1, y1, color, radius=.5):
+ self.graffiti_preview = self.graffiti_preview
+ r, g, b, a_ = color
+ for x in range(int(x1 - 1 - math.ceil(radius)), int(x1 + 1 + math.ceil(radius) + 1)):
+ for y in range(int(y1 - 1 - math.ceil(radius)), int(y1 + 1 + math.ceil(radius) + 1)):
+ if x >= 0 and y >= 0 and y < len(self.graffiti_preview) and x * 4 < len(self.graffiti_preview[0]):
+ d = math.sqrt((x1 - x) ** 2 + (y1 - y) ** 2)
+ a = float(a_) * (max(0, (1 - (d - radius))) if d > radius else 1) / 256
+ self.graffiti_preview[y][x * 4] = int(r * a + (1 - a) * self.graffiti_preview[y][x * 4])
+ self.graffiti_preview[y][x * 4 + 1] = int(g * a + (1 - a) * self.graffiti_preview[y][x * 4 + 1])
+ self.graffiti_preview[y][x * 4 + 2] = int(g * b + (1 - a) * self.graffiti_preview[y][x * 4 + 2])
+ self.graffiti_preview[y][x * 4 + 3] = min(255, int(self.graffiti_preview[y][x * 4 + 3] + a * 256))
+
+ def graffiti_preview_transform(x, y):
+ tr = self.graffiti_preview_transform
+ d = max(tr[2] - tr[0] + 2, tr[3] - tr[1] + 2)
+ return [(x - tr[0] + 1) * self.options.graffiti_preview_size / d, self.options.graffiti_preview_size - (y - tr[1] + 1) * self.options.graffiti_preview_size / d]
+
+ def draw_graffiti_segment(layer, start, end, feed, color=(0, 255, 0, 40), emmit=1000):
+ # Emit = dots per second
+ l = math.sqrt(sum([(start[i] - end[i]) ** 2 for i in range(len(start))]))
+ time_ = l / feed
+ c1 = self.graffiti_reference_points[layer][0][0]
+ c2 = self.graffiti_reference_points[layer][1][0]
+ d = math.sqrt((c1[0] - c2[0]) ** 2 + (c1[1] - c2[1]) ** 2)
+ if d == 0:
+ raise ValueError("Error! Reference points should not be the same!")
+ for i in range(int(time_ * emmit + 1)):
+ t = i / (time_ * emmit)
+ r1 = start[0] * (1 - t) + end[0] * t
+ r2 = start[1] * (1 - t) + end[1] * t
+ a = (r1 ** 2 - r2 ** 2 + d ** 2) / (2 * d)
+ h = math.sqrt(r1 ** 2 - a ** 2)
+ xa = c1[0] + a * (c2[0] - c1[0]) / d
+ ya = c1[1] + a * (c2[1] - c1[1]) / d
+
+ x1 = xa + h * (c2[1] - c1[1]) / d
+ x2 = xa - h * (c2[1] - c1[1]) / d
+ y1 = ya - h * (c2[0] - c1[0]) / d
+ y2 = ya + h * (c2[0] - c1[0]) / d
+
+ x = x1 if y1 < y2 else x2
+ y = min(y1, y2)
+ x, y = graffiti_preview_transform(x, y)
+ graffiti_preview_draw_point(x, y, color)
+
+ def create_connector(p1, p2, t1, t2):
+ P1 = P(p1)
+ P2 = P(p2)
+ N1 = P(rotate_ccw(t1))
+ N2 = P(rotate_ccw(t2))
+ r = self.options.graffiti_min_radius
+ C1 = P1 + N1 * r
+ C2 = P2 + N2 * r
+ # Get closest possible centers of arcs, also we define that arcs are both ccw or both not.
+ dc, N1, N2, m = (
+ (
+ (((P2 - N1 * r) - (P1 - N2 * r)).l2(), -N1, -N2, 1)
+ if vectors_ccw(t1, t2) else
+ (((P2 + N1 * r) - (P1 + N2 * r)).l2(), N1, N2, -1)
+ )
+ if vectors_ccw((P1 - C1).to_list(), t1) == vectors_ccw((P2 - C2).to_list(), t2) else
+ (
+ (((P2 + N1 * r) - (P1 - N2 * r)).l2(), N1, -N2, 1)
+ if vectors_ccw(t1, t2) else
+ (((P2 - N1 * r) - (P1 + N2 * r)).l2(), -N1, N2, 1)
+ )
+ )
+ dc = math.sqrt(dc)
+ C1 = P1 + N1 * r
+ C2 = P2 + N2 * r
+ Dc = C2 - C1
+
+ if dc == 0:
+ # can be joined by one arc
+ return csp_from_arc(p1, p2, C1.to_list(), r, t1)
+
+ cos = Dc.x / dc
+ sin = Dc.y / dc
+
+ p1_end = [C1.x - r * sin * m, C1.y + r * cos * m]
+ p2_st = [C2.x - r * sin * m, C2.y + r * cos * m]
+ if point_to_point_d2(p1, p1_end) < 0.0001 and point_to_point_d2(p2, p2_st) < 0.0001:
+ return [[p1, p1, p1], [p2, p2, p2]]
+
+ arc1 = csp_from_arc(p1, p1_end, C1.to_list(), r, t1)
+ arc2 = csp_from_arc(p2_st, p2, C2.to_list(), r, [cos, sin])
+ return csp_concat_subpaths(arc1, arc2)
+
+ if not self.check_dir():
+ return
+ if self.selected_paths == {} and self.options.auto_select_paths:
+ paths = self.paths
+ self.error("No paths are selected! Trying to work on all available paths.")
+ else:
+ paths = self.selected_paths
+ self.tool = []
+ gcode = """(Header)
+(Generated by gcodetools from Inkscape.)
+(Using graffiti extension.)
+(Header end.)"""
+
+ minx = float("inf")
+ miny = float("inf")
+ maxx = float("-inf")
+ maxy = float("-inf")
+ # Get all reference points and path's bounds to make preview
+
+ for layer in self.layers:
+ if layer in paths:
+ # Set reference points
+ if layer not in self.graffiti_reference_points:
+ reference_points = None
+ for i in range(self.layers.index(layer), -1, -1):
+ if self.layers[i] in self.graffiti_reference_points:
+ reference_points = self.graffiti_reference_points[self.layers[i]]
+ self.graffiti_reference_points[layer] = self.graffiti_reference_points[self.layers[i]]
+ break
+ if reference_points is None:
+ self.error('There are no graffiti reference points for layer {}'.format(layer), "error")
+
+ # Transform reference points
+ for i in range(len(self.graffiti_reference_points[layer])):
+ self.graffiti_reference_points[layer][i][0] = self.transform(self.graffiti_reference_points[layer][i][0], layer)
+ point = self.graffiti_reference_points[layer][i]
+ gcode += "(Reference point {:f};{:f} for {} axis)\n".format(point[0][0], point[0][1], point[1])
+
+ if self.options.graffiti_create_preview:
+ for point in self.graffiti_reference_points[layer]:
+ minx = min(minx, point[0][0])
+ miny = min(miny, point[0][1])
+ maxx = max(maxx, point[0][0])
+ maxy = max(maxy, point[0][1])
+ for path in paths[layer]:
+ csp = path.path.to_superpath()
+ csp = self.apply_transforms(path, csp)
+ csp = self.transform_csp(csp, layer)
+ bounds = csp_simple_bound(csp)
+ minx = min(minx, bounds[0])
+ miny = min(miny, bounds[1])
+ maxx = max(maxx, bounds[2])
+ maxy = max(maxy, bounds[3])
+
+ if self.options.graffiti_create_preview:
+ self.graffiti_preview = list([[255] * (4 * self.options.graffiti_preview_size) for _ in range(self.options.graffiti_preview_size)])
+ self.graffiti_preview_transform = [minx, miny, maxx, maxy]
+
+ for layer in self.layers:
+ if layer in paths:
+
+ r = re.match("\\s*\\(\\s*([0-9\\-,.]+)\\s*;\\s*([0-9\\-,.]+)\\s*\\)\\s*", self.options.graffiti_start_pos)
+ if r:
+ start_point = [float(r.group(1)), float(r.group(2))]
+ else:
+ start_point = [0., 0.]
+ last_sp1 = [[start_point[0], start_point[1] - 10] for _ in range(3)]
+ last_sp2 = [start_point for _ in range(3)]
+
+ self.set_tool(layer)
+ self.tool = self.tools[layer][0]
+ # Change tool every layer. (Probably layer = color so it'll be
+ # better to change it even if the tool has not been changed)
+ gcode += ("(Change tool to {})\n".format(re.sub("\"'\\(\\)\\\\", " ", self.tool["name"]))) + self.tool["tool change gcode"] + "\n"
+
+ subpaths = []
+ for path in paths[layer]:
+ # Rebuild the paths to polyline.
+ csp = path.path.to_superpath()
+ csp = self.apply_transforms(path, csp)
+ csp = self.transform_csp(csp, layer)
+ subpaths += csp
+ polylines = []
+ while len(subpaths) > 0:
+ i = min([(point_to_point_d2(last_sp2[1], subpaths[i][0][1]), i) for i in range(len(subpaths))])[1]
+ subpath = subpaths[i][:]
+ del subpaths[i]
+ polylines += [
+ ['connector', create_connector(
+ last_sp2[1],
+ subpath[0][1],
+ csp_normalized_slope(last_sp1, last_sp2, 1.),
+ csp_normalized_slope(subpath[0], subpath[1], 0.),
+ )]
+ ]
+ polyline = []
+ spl = None
+
+ # remove zerro length segments
+ i = 0
+ while i < len(subpath) - 1:
+ if cspseglength(subpath[i], subpath[i + 1]) < 0.00000001:
+ subpath[i][2] = subpath[i + 1][2]
+ del subpath[i + 1]
+ else:
+ i += 1
+
+ for sp1, sp2 in zip(subpath, subpath[1:]):
+ if spl is not None and abs(cross(csp_normalized_slope(spl, sp1, 1.), csp_normalized_slope(sp1, sp2, 0.))) > 0.1: # TODO add coefficient into inx
+ # We've got sharp angle at sp1.
+ polyline += [sp1]
+ polylines += [['draw', polyline[:]]]
+ polylines += [
+ ['connector', create_connector(
+ sp1[1],
+ sp1[1],
+ csp_normalized_slope(spl, sp1, 1.),
+ csp_normalized_slope(sp1, sp2, 0.),
+ )]
+ ]
+ polyline = []
+ # max_segment_length
+ polyline += [sp1]
+ print_(polyline)
+ print_(sp1)
+
+ spl = sp1
+ polyline += [sp2]
+ polylines += [['draw', polyline[:]]]
+
+ last_sp1 = sp1
+ last_sp2 = sp2
+
+ # Add return to start_point
+ if not polylines:
+ continue
+ polylines += [["connect1", [[polylines[-1][1][-1][1] for _ in range(3)], [start_point for _ in range(3)]]]]
+
+ # Make polylines from polylines. They are still csp.
+ for i in range(len(polylines)):
+ polyline = []
+ l = 0
+ print_("polylines", polylines)
+ print_(polylines[i])
+ for sp1, sp2 in zip(polylines[i][1], polylines[i][1][1:]):
+ print_(sp1, sp2)
+ l = cspseglength(sp1, sp2)
+ if l > 0.00000001:
+ polyline += [sp1[1]]
+ parts = int(math.ceil(l / self.options.graffiti_max_seg_length))
+ for j in range(1, parts):
+ polyline += [csp_at_length(sp1, sp2, float(j) / parts)]
+ if l > 0.00000001:
+ polyline += [sp2[1]]
+ print_(i)
+ polylines[i][1] = polyline
+
+ t = 0
+ last_state = None
+ for polyline_ in polylines:
+ polyline = polyline_[1]
+ # Draw linearization
+ if self.options.graffiti_create_linearization_preview:
+ t += 1
+ csp = [[polyline[i], polyline[i], polyline[i]] for i in range(len(polyline))]
+ draw_csp(self.transform_csp([csp], layer, reverse=True))
+
+ # Export polyline to gcode
+ # we are making transform from XYZA coordinates to R1...Rn
+ # where R1...Rn are radius vectors from graffiti reference points
+ # to current (x,y) point. Also we need to assign custom feed rate
+ # for each segment. And we'll use only G01 gcode.
+ last_real_pos, g = get_gcode_coordinates(polyline[0], layer)
+ last_pos = polyline[0]
+ if polyline_[0] == "draw" and last_state != "draw":
+ gcode += self.tool['gcode before path'] + "\n"
+ for point in polyline:
+ real_pos, g = get_gcode_coordinates(point, layer)
+ real_l = sum([(real_pos[i] - last_real_pos[i]) ** 2 for i in range(len(last_real_pos))])
+ l = (last_pos[0] - point[0]) ** 2 + (last_pos[1] - point[1]) ** 2
+ if l != 0:
+ feed = self.tool['feed'] * math.sqrt(real_l / l)
+ gcode += "G01 " + g + " F {:f}\n".format(feed)
+ if self.options.graffiti_create_preview:
+ draw_graffiti_segment(layer, real_pos, last_real_pos, feed, color=(0, 0, 255, 200) if polyline_[0] == "draw" else (255, 0, 0, 200), emmit=self.options.graffiti_preview_emmit)
+ last_real_pos = real_pos
+ last_pos = point[:]
+ if polyline_[0] == "draw" and last_state != "draw":
+ gcode += self.tool['gcode after path'] + "\n"
+ last_state = polyline_[0]
+ self.export_gcode(gcode, no_headers=True)
+ if self.options.graffiti_create_preview:
+ try:
+ # Draw reference points
+ for layer in self.graffiti_reference_points:
+ for point in self.graffiti_reference_points[layer]:
+ x, y = graffiti_preview_transform(point[0][0], point[0][1])
+ graffiti_preview_draw_point(x, y, (0, 255, 0, 255), radius=5)
+
+ import png
+ writer = png.Writer(width=self.options.graffiti_preview_size, height=self.options.graffiti_preview_size, size=None, greyscale=False, alpha=True, bitdepth=8, palette=None, transparent=None, background=None, gamma=None, compression=None, interlace=False, bytes_per_sample=None, planes=None, colormap=None, maxval=None, chunk_limit=1048576)
+ with open(os.path.join(self.options.directory, self.options.file + ".png"), 'wb') as f:
+ writer.write(f, self.graffiti_preview)
+
+ except:
+ self.error("Png module have not been found!")
+
+ def get_info_plus(self):
+ """Like get_info(), but checks some of the values"""
+ self.get_info()
+ if self.orientation_points == {}:
+ self.error("Orientation points have not been defined! A default set of orientation points has been automatically added.")
+ self.tab_orientation(self.layers[min(1, len(self.layers) - 1)])
+ self.get_info()
+ if self.tools == {}:
+ self.error("Cutting tool has not been defined! A default tool has been automatically added.")
+ self.options.tools_library_type = "default"
+ self.tab_tools_library(self.layers[min(1, len(self.layers) - 1)])
+ self.get_info()
+
+ ################################################################################
+ #
+ # Effect
+ #
+ # Main function of Gcodetools class
+ #
+ ################################################################################
+ def effect(self):
+ start_time = time.time()
+ global options
+ options = self.options
+ options.self = self
+ options.doc_root = self.document.getroot()
+
+ # define print_ function
+ global print_
+ if self.options.log_create_log:
+ try:
+ if os.path.isfile(self.options.log_filename):
+ os.remove(self.options.log_filename)
+ with open(self.options.log_filename, "a") as fhl:
+ fhl.write("""Gcodetools log file.
+Started at {}.
+{}
+""".format(time.strftime("%d.%m.%Y %H:%M:%S"), options.log_filename))
+ except:
+ print_ = lambda *x: None
+ else:
+ print_ = lambda *x: None
+
+ # This automatically calls any `tab_{tab_name_in_inx}` which in this
+ # extension is A LOT of different functions. So see all method prefixed
+ # with tab_ to find out what's supported here.
+ self.options.active_tab()
+
+ print_("------------------------------------------")
+ print_("Done in {:f} seconds".format(time.time() - start_time))
+ print_("End at {}.".format(time.strftime("%d.%m.%Y %H:%M:%S")))
+
+
+ def tab_offset(self):
+ self.get_info()
+ if self.options.offset_just_get_distance:
+ for layer in self.selected_paths:
+ if len(self.selected_paths[layer]) == 2:
+ csp1 = self.selected_paths[layer][0].path.to_superpath()
+ csp2 = self.selected_paths[layer][1].path.to_superpath()
+ dist = csp_to_csp_distance(csp1, csp2)
+ print_(dist)
+ draw_pointer(list(csp_at_t(csp1[dist[1]][dist[2] - 1], csp1[dist[1]][dist[2]], dist[3]))
+ + list(csp_at_t(csp2[dist[4]][dist[5] - 1], csp2[dist[4]][dist[5]], dist[6])), "red", "line", comment=math.sqrt(dist[0]))
+ return
+ if self.options.offset_step == 0:
+ self.options.offset_step = self.options.offset_radius
+ if self.options.offset_step * self.options.offset_radius < 0:
+ self.options.offset_step *= -1
+ time_ = time.time()
+ offsets_count = 0
+ for layer in self.selected_paths:
+ for path in self.selected_paths[layer]:
+
+ offset = self.options.offset_step / 2
+ while abs(offset) <= abs(self.options.offset_radius):
+ offset_ = csp_offset(path.path.to_superpath(), offset)
+ offsets_count += 1
+ if offset_:
+ for iii in offset_:
+ draw_csp([iii], width=1)
+ else:
+ print_("------------Reached empty offset at radius {}".format(offset))
+ break
+ offset += self.options.offset_step
+ print_()
+ print_("-----------------------------------------------------------------------------------")
+ print_("-----------------------------------------------------------------------------------")
+ print_("-----------------------------------------------------------------------------------")
+ print_()
+ print_("Done in {}".format(time.time() - time_))
+ print_("Total offsets count {}".format(offsets_count))
+
+
+if __name__ == '__main__':
+ Gcodetools().run()
diff --git a/share/extensions/other/gcodetools/gcodetools_about.inx b/share/extensions/other/gcodetools/gcodetools_about.inx
new file mode 100644
index 0000000..72f2b99
--- /dev/null
+++ b/share/extensions/other/gcodetools/gcodetools_about.inx
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
+ <name>About</name>
+ <id>ru.cnc-club.filter.gcodetools_about_no_options_no_preferences</id>
+ <param name='active-tab' type="notebook">
+
+ <page name='about' gui-text='About'>
+ <label xml:space="preserve">Gcodetools was developed to make simple Gcode from Inkscape's paths. Gcode is a special format which is used in most of CNC machines. So Gcodetools allows you to use Inkscape as CAM program.
+
+It can be used with a lot of machine types:
+ Mills
+ Lathes
+ Laser and Plasma cutters and engravers
+ Mill engravers
+ Plotters
+ etc.
+
+To get more info visit developers page at http://www.cnc-club.ru/gcodetools</label>
+ </page>
+
+ <page name='help' gui-text='Help'>
+ <label xml:space="preserve">
+Gcodetools plug-in:
+Converts paths to Gcode (using circular interpolation), makes offset paths and engraves sharp corners using cone cutters.
+This plug-in calculates Gcode for paths using circular interpolation or linear motion when needed.
+
+Tutorials, manuals and support can be found at
+English support forum:
+ http://www.cnc-club.ru/gcodetools
+
+and Russian support forum:
+ http://www.cnc-club.ru/gcodetoolsru
+
+Credits: Nick Drobchenko, Vladimir Kalyaev, John Brooker, Henry Nicolas, Chris Lusby Taylor.
+
+Gcodetools ver. 1.7
+</label>
+
+ </page>
+
+ </param>
+ <effect>
+ <object-type>path</object-type>
+ <effects-menu>
+ <submenu name="Gcodetools"/>
+ </effects-menu>
+ </effect>
+ <script>
+ <command location="inx" interpreter="python">gcodetools.py</command>
+ </script>
+</inkscape-extension>
diff --git a/share/extensions/other/gcodetools/gcodetools_area.inx b/share/extensions/other/gcodetools/gcodetools_area.inx
new file mode 100644
index 0000000..6a500e2
--- /dev/null
+++ b/share/extensions/other/gcodetools/gcodetools_area.inx
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
+ <name>Area</name>
+ <id>ru.cnc-club.filter.gcodetools_area_area_fill_area_artefacts_ptg</id>
+ <param name='active-tab' type="notebook">
+
+ <page name='area' gui-text='Area'>
+ <param name="max-area-curves" type="int" min="0" max="1000" gui-text="Maximum area cutting curves:">100</param>
+ <param name="area-inkscape-radius" type="float" min="-1000" max="1000" gui-text="Area width:">-10</param>
+ <param name="area-tool-overlap" type="float" min="0" max="1" gui-text="Area tool overlap (0..0.9):">0</param>
+
+ <label xml:space="preserve">
+"Create area offset": creates several Inkscape path offsets to fill original path's area up to "Area radius" value.
+
+Outlines start from "1/2 D" up to "Area width" total width with "D" steps where D is taken from the nearest tool definition ("Tool diameter" value).
+Only one offset will be created if the "Area width" is equal to "1/2 D".
+ </label>
+ </page>
+
+ <page name='area_fill' gui-text='Fill area'>
+ <param name="area-fill-angle" type="float" min="-360" max="360" gui-text="Area fill angle">0</param>
+ <param name="area-fill-shift" type="float" min="-1" max="1" gui-text="Area fill shift">0</param>
+ <param name="area-fill-method" type="float" min="-1" max="1" gui-text="Area fill shift">0</param>
+ <param name="area-fill-method" gui-text="Filling method" type="optiongroup" appearance="radio">
+ <option value="zig-zag">Zig zag</option>
+ <option value="spiral">Spiral</option>
+ </param>
+ </page>
+
+ <page name='area_artefacts' gui-text='Area artifacts'>
+ <param name="area-find-artefacts-diameter" type="float" min="0.01" max="1000" gui-text="Artifact diameter:">5.0</param>
+ <param name="area-find-artefacts-action" type="optiongroup" appearance="radio" gui-text="Action:">
+ <option value="mark with an arrow">mark with an arrow</option>
+ <option value="mark with style">mark with style</option>
+ <option value="delete">delete</option>
+ </param>
+ <label xml:space="preserve">
+Usage:
+1. Select all Area Offsets (gray outlines)
+2. Object/Ungroup (Shift+Ctrl+G)
+3. Press Apply
+
+Suspected small objects will be marked out by colored arrows.
+ </label>
+ </page>
+
+ <page name='path-to-gcode' gui-text='Path to Gcode'>
+ <param name="biarc-tolerance" type='float' precision="5" gui-text='Biarc interpolation tolerance:'>1</param>
+ <param name="biarc-max-split-depth" type="int" gui-text="Maximum splitting depth:">4</param>
+ <param name="path-to-gcode-order" gui-text="Cutting order:" type="optiongroup" appearance="combo">
+ <option value="subpath by subpath">Subpath by subpath</option>
+ <option value="path by path">Path by path</option>
+ <option value="pass by pass">Pass by Pass</option>
+ </param>
+
+ <param name="path-to-gcode-depth-function" type="string" gui-text="Depth function:">d</param>
+ <param name="path-to-gcode-sort-paths" type="bool" gui-text="Sort paths to reduce rapid distance">true</param>
+
+ <label xml:space="preserve">
+Biarc interpolation tolerance is the maximum distance between path and its approximation.
+The segment will be split into two segments if the distance between path's segment and its approximation exceeds biarc interpolation tolerance.
+For depth function c=color intensity from 0.0 (white) to 1.0 (black), d is the depth defined by orientation points, s - surface defined by orientation points.
+</label>
+ </page>
+
+ <page name='options' gui-text='Options'>
+ <param name="Zscale" type="float" precision="5" min="-100000" max="100000" gui-text="Scale along Z axis:">1</param>
+ <param name="Zoffset" type="float" precision="5" min="-100000" max="100000" gui-text="Offset along Z axis:">0.0</param>
+ <param name="auto_select_paths" type="bool" gui-text="Select all paths if nothing is selected">true</param>
+ <param name="min-arc-radius" type="float" precision="5" min="-1000" max="1000" gui-text="Minimum arc radius:">0.05</param>
+ <param name="comment-gcode" type="string" gui-text="Comment Gcode:"></param>
+ <param name="comment-gcode-from-properties" type="bool" gui-text="Get additional comments from object's properties">false</param>
+
+ </page>
+
+ <page name='preferences' gui-text='Preferences'>
+ <param name="filename" type="string" gui-text="File:">output.ngc</param>
+ <param name="add-numeric-suffix-to-filename" type="bool" gui-text="Add numeric suffix to filename">true</param>
+
+ <param name="directory" type="string" gui-text="Directory:">/home</param>
+
+ <param name="Zsafe" type="float" precision="5" min="-1000" max="1000" gui-text="Z safe height for G00 move over blank:">5</param>
+ <param name="unit" type="optiongroup" appearance="combo" gui-text="Units (mm or in):">
+ <option value="G21 (All units in mm)">mm</option>
+ <option value="G20 (All units in inches)">in</option>
+ </param>
+ <param name="postprocessor" type="optiongroup" appearance="combo" gui-text="Post-processor:">
+ <option context="GCode postprocessor" value=" ">None</option>
+ <option value="parameterize();">Parameterize Gcode</option>
+ <option value="flip(y);parameterize();">Flip y axis and parameterize Gcode</option>
+ <option value="round(4);">Round all values to 4 digits</option>
+ <option value='regex("G01 Z([0-9\.\-]+).*\(Penetrate\)", lambda match: "G00 Z%f (Fast pre-penetrate)\n%s" %(float(match.group(1))+5, match.group(0)));'>Fast pre-penetrate</option>
+ </param>
+ <param name="postprocessor-custom" type="string" gui-text="Additional post-processor:"></param>
+
+
+ <param name="create-log" type="bool" gui-text="Generate log file">false</param>
+ <param name="log-filename" type="string" gui-text="Full path to log file:"></param>
+
+ </page>
+
+ <page name='help' gui-text='Help'>
+ <label xml:space="preserve">
+Gcodetools plug-in:
+Converts paths to Gcode (using circular interpolation), makes offset paths and engraves sharp corners using cone cutters.
+This plug-in calculates Gcode for paths using circular interpolation or linear motion when needed.
+
+Tutorials, manuals and support can be found at
+English support forum:
+ http://www.cnc-club.ru/gcodetools
+
+and Russian support forum:
+ http://www.cnc-club.ru/gcodetoolsru
+
+Credits: Nick Drobchenko, Vladimir Kalyaev, John Brooker, Henry Nicolas, Chris Lusby Taylor.
+
+Gcodetools ver. 1.7
+</label>
+
+ </page>
+
+ </param>
+ <effect>
+ <object-type>path</object-type>
+ <effects-menu>
+ <submenu name="Gcodetools"/>
+ </effects-menu>
+ </effect>
+ <script>
+ <command location="inx" interpreter="python">gcodetools.py</command>
+ </script>
+</inkscape-extension>
diff --git a/share/extensions/other/gcodetools/gcodetools_dxf_points.inx b/share/extensions/other/gcodetools/gcodetools_dxf_points.inx
new file mode 100644
index 0000000..8cd782a
--- /dev/null
+++ b/share/extensions/other/gcodetools/gcodetools_dxf_points.inx
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
+ <name>DXF Points</name>
+ <id>ru.cnc-club.filter.gcodetools_dxfpoints_no_options</id>
+ <param name='active-tab' type="notebook">
+
+ <page name='dxfpoints' gui-text='DXF points'>
+ <label xml:space="preserve">
+
+Convert selected objects to drill points (as dxf_import plugin does). Also you can save original shape. Only the start point of each curve will be used.
+
+Also you can manually select object, open XML editor (Shift+Ctrl+X) and add or remove XML tag 'dxfpoint' with any value.
+ </label>
+ <param type='optiongroup' appearance="radio" name='dxfpoints-action' gui-text="Convert selection:">
+ <option value='save'>set as dxfpoint and save shape</option>
+ <option value='replace'>set as dxfpoint and draw arrow</option>
+ <option value='clear'>clear dxfpoint sign</option>
+ </param>
+
+ </page>
+
+ <page name='preferences' gui-text='Preferences'>
+ <param name="filename" type="string" gui-text="File:">output.ngc</param>
+ <param name="add-numeric-suffix-to-filename" type="bool" gui-text="Add numeric suffix to filename">true</param>
+
+ <param name="directory" type="string" gui-text="Directory:">/home</param>
+
+ <param name="Zsafe" type="float" precision="5" min="-1000" max="1000" gui-text="Z safe height for G00 move over blank:">5</param>
+ <param name="unit" type="optiongroup" appearance="combo" gui-text="Units (mm or in):">
+ <option value="G21 (All units in mm)">mm</option>
+ <option value="G20 (All units in inches)">in</option>
+ </param>
+ <param name="postprocessor" type="optiongroup" appearance="combo" gui-text="Post-processor:">
+ <option context="GCode postprocessor" value=" ">None</option>
+ <option value="parameterize();">Parameterize Gcode</option>
+ <option value="flip(y);parameterize();">Flip y axis and parameterize Gcode</option>
+ <option value="round(4);">Round all values to 4 digits</option>
+ <option value='regex("G01 Z([0-9\.\-]+).*\(Penetrate\)", lambda match: "G00 Z%f (Fast pre-penetrate)\n%s" %(float(match.group(1))+5, match.group(0)));'>Fast pre-penetrate</option>
+ </param>
+ <param name="postprocessor-custom" type="string" gui-text="Additional post-processor:"></param>
+
+
+ <param name="create-log" type="bool" gui-text="Generate log file">false</param>
+ <param name="log-filename" type="string" gui-text="Full path to log file:"></param>
+
+ </page>
+
+ <page name='help' gui-text='Help'>
+ <label xml:space="preserve">
+Gcodetools plug-in:
+Converts paths to Gcode (using circular interpolation), makes offset paths and engraves sharp corners using cone cutters.
+This plug-in calculates Gcode for paths using circular interpolation or linear motion when needed.
+
+Tutorials, manuals and support can be found at
+English support forum:
+ http://www.cnc-club.ru/gcodetools
+
+and Russian support forum:
+ http://www.cnc-club.ru/gcodetoolsru
+
+Credits: Nick Drobchenko, Vladimir Kalyaev, John Brooker, Henry Nicolas, Chris Lusby Taylor.
+
+Gcodetools ver. 1.7
+</label>
+
+ </page>
+
+ </param>
+ <effect>
+ <object-type>path</object-type>
+ <effects-menu>
+ <submenu name="Gcodetools"/>
+ </effects-menu>
+ </effect>
+ <script>
+ <command location="inx" interpreter="python">gcodetools.py</command>
+ </script>
+</inkscape-extension>
diff --git a/share/extensions/other/gcodetools/gcodetools_engraving.inx b/share/extensions/other/gcodetools/gcodetools_engraving.inx
new file mode 100644
index 0000000..daf2d4a
--- /dev/null
+++ b/share/extensions/other/gcodetools/gcodetools_engraving.inx
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
+ <name>Engraving</name>
+ <id>ru.cnc-club.filter.gcodetools_engraving</id>
+ <param name='active-tab' type="notebook">
+
+ <page name='engraving' gui-text='Engraving'>
+ <param name="engraving-sharp-angle-tollerance" type="float" precision="5" min="150" max="180" gui-text="Smooth convex corners between this value and 180 degrees:">175</param>
+ <param name="engraving-max-dist" type="float" precision="5" min="0" max="1000" gui-text="Maximum distance for engraving (mm/inch):">10</param>
+ <param name="engraving-newton-iterations" type="int" min="2" max="10" gui-text="Accuracy factor (2 low to 10 high):">4</param>
+ <param name="engraving-draw-calculation-paths" type="bool" gui-text="Draw additional graphics to see engraving path">false</param>
+
+ <label xml:space="preserve">
+This function creates path to engrave letters or any shape with sharp angles.
+Cutter's depth as a function of radius is defined by the tool.
+Depth may be any Python expression. For instance:
+
+cone....(45 degrees)......................: w
+cone....(height/diameter=10/3)..: 10*w/3
+sphere..(radius r)...........................: math.sqrt(max(0,r**2-w**2))
+ellipse.(minor axis r, major 4r).....: math.sqrt(max(0,r**2-w**2))*4</label>
+ </page>
+
+ <page name='options' gui-text='Options'>
+ <param name="Zscale" type="float" precision="5" min="-100000" max="100000" gui-text="Scale along Z axis:">1</param>
+ <param name="Zoffset" type="float" precision="5" min="-100000" max="100000" gui-text="Offset along Z axis:">0.0</param>
+ <param name="auto_select_paths" type="bool" gui-text="Select all paths if nothing is selected">true</param>
+ <param name="min-arc-radius" type="float" precision="5" min="-1000" max="1000" gui-text="Minimum arc radius:">0.05</param>
+ <param name="comment-gcode" type="string" gui-text="Comment Gcode:"></param>
+ <param name="comment-gcode-from-properties" type="bool" gui-text="Get additional comments from object's properties">false</param>
+
+ </page>
+
+ <page name='preferences' gui-text='Preferences'>
+ <param name="filename" type="string" gui-text="File:">output.ngc</param>
+ <param name="add-numeric-suffix-to-filename" type="bool" gui-text="Add numeric suffix to filename">true</param>
+
+ <param name="directory" type="string" gui-text="Directory:">/home</param>
+
+ <param name="Zsafe" type="float" precision="5" min="-1000" max="1000" gui-text="Z safe height for G00 move over blank:">5</param>
+ <param name="unit" type="optiongroup" appearance="combo" gui-text="Units (mm or in):">
+ <option value="G21 (All units in mm)">mm</option>
+ <option value="G20 (All units in inches)">in</option>
+ </param>
+ <param name="postprocessor" type="optiongroup" appearance="combo" gui-text="Post-processor:">
+ <option context="GCode postprocessor" value=" ">None</option>
+ <option value="parameterize();">Parameterize Gcode</option>
+ <option value="flip(y);parameterize();">Flip y axis and parameterize Gcode</option>
+ <option value="round(4);">Round all values to 4 digits</option>
+ <option value='regex("G01 Z([0-9\.\-]+).*\(Penetrate\)", lambda match: "G00 Z%f (Fast pre-penetrate)\n%s" %(float(match.group(1))+5, match.group(0)));'>Fast pre-penetrate</option>
+ </param>
+ <param name="postprocessor-custom" type="string" gui-text="Additional post-processor:"></param>
+
+
+ <param name="create-log" type="bool" gui-text="Generate log file">false</param>
+ <param name="log-filename" type="string" gui-text="Full path to log file:"></param>
+
+ </page>
+
+ <page name='help' gui-text='Help'>
+ <label xml:space="preserve">
+Gcodetools plug-in:
+Converts paths to Gcode (using circular interpolation), makes offset paths and engraves sharp corners using cone cutters.
+This plug-in calculates Gcode for paths using circular interpolation or linear motion when needed.
+
+Tutorials, manuals and support can be found at
+English support forum:
+ http://www.cnc-club.ru/gcodetools
+
+and Russian support forum:
+ http://www.cnc-club.ru/gcodetoolsru
+
+Credits: Nick Drobchenko, Vladimir Kalyaev, John Brooker, Henry Nicolas, Chris Lusby Taylor.
+
+Gcodetools ver. 1.7
+</label>
+
+ </page>
+
+ </param>
+ <effect>
+ <object-type>path</object-type>
+ <effects-menu>
+ <submenu name="Gcodetools"/>
+ </effects-menu>
+ </effect>
+ <script>
+ <command location="inx" interpreter="python">gcodetools.py</command>
+ </script>
+</inkscape-extension>
diff --git a/share/extensions/other/gcodetools/gcodetools_graffiti.inx b/share/extensions/other/gcodetools/gcodetools_graffiti.inx
new file mode 100644
index 0000000..ea428b7
--- /dev/null
+++ b/share/extensions/other/gcodetools/gcodetools_graffiti.inx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
+ <name>Graffiti</name>
+ <id>ru.cnc-club.filter.gcodetools_graffiti_orientation</id>
+ <param name='active-tab' type="notebook">
+
+ <page name='graffiti' gui-text='Graffiti'>
+ <param name="graffiti-max-seg-length" type="float" precision="5" min="0" max="1000" gui-text="Maximum segment length:">10</param>
+ <param name="graffiti-min-radius" type="float" precision="5" min="0" max="1000" gui-text="Minimal connector radius:">10</param>
+ <param name="graffiti-start-pos" type="string" gui-text="Start position (x;y):">(0.0;0.0)</param>
+ <param name="graffiti-create-preview" type="bool" gui-text="Create preview">true</param>
+ <param name="graffiti-create-linearization-preview" type="bool" gui-text="Create linearization preview">true</param>
+ <param name="graffiti-preview-size" type="int" min="100" max="10000" gui-text="Preview's size (px):">800</param>
+ <param name="graffiti-preview-emmit" type="int" min="100" max="10000" gui-text="Preview's paint emmit (pts/s):">1000</param>
+ </page>
+
+ <page name='orientation' gui-text='Orientation'>
+
+ <param name="orientation-points-count" type="optiongroup" appearance="radio" gui-text="Orientation type:">
+ <option value="2">2-points mode
+ (move and rotate,
+ maintained aspect ratio X/Y)
+ </option>
+ <option value="3">3-points mode
+ (move, rotate and mirror,
+ different X/Y scale)
+ </option>
+ <option value="graffiti">graffiti points</option>
+ <option value="in-out reference point">in-out reference point</option>
+
+ </param>
+ <param name="Zsurface" type="float" precision="5" min="-1000" max="1000" gui-text="Z surface:">0</param>
+ <param name="Zdepth" type="float" precision="5" min="-1000" max="1000" gui-text="Z depth:">-1</param>
+ <param name="unit" type="optiongroup" appearance="combo" gui-text="Units (mm or in):">
+ <option value="G21 (All units in mm)">mm</option>
+ <option value="G20 (All units in inches)">in</option>
+ </param>
+
+ <label xml:space="preserve">
+Orientation points are used to calculate transformation (offset,scale,mirror,rotation in XY plane) of the path.
+3-points mode only: do not put all three into one line (use 2-points mode instead).
+
+You can modify Z surface, Z depth values later using text tool (3rd coordinates).
+
+If there are no orientation points inside current layer they are taken from the upper layer.
+
+Do not ungroup orientation points! You can select them using double click to enter the group or by Ctrl+Click.
+
+Now press apply to create control points (independent set for each layer).
+ </label>
+ </page>
+
+ <page name='options' gui-text='Options'>
+ <param name="Zscale" type="float" precision="5" min="-100000" max="100000" gui-text="Scale along Z axis:">1</param>
+ <param name="Zoffset" type="float" precision="5" min="-100000" max="100000" gui-text="Offset along Z axis:">0.0</param>
+ <param name="auto_select_paths" type="bool" gui-text="Select all paths if nothing is selected">true</param>
+ <param name="min-arc-radius" type="float" precision="5" min="-1000" max="1000" gui-text="Minimum arc radius:">0.05</param>
+ <param name="comment-gcode" type="string" gui-text="Comment Gcode:"></param>
+ <param name="comment-gcode-from-properties" type="bool" gui-text="Get additional comments from object's properties">false</param>
+
+ </page>
+
+ <page name='preferences' gui-text='Preferences'>
+ <param name="filename" type="string" gui-text="File:">output.ngc</param>
+ <param name="add-numeric-suffix-to-filename" type="bool" gui-text="Add numeric suffix to filename">true</param>
+
+ <param name="directory" type="string" gui-text="Directory:">/home</param>
+
+ <param name="Zsafe" type="float" precision="5" min="-1000" max="1000" gui-text="Z safe height for G00 move over blank:">5</param>
+ <param name="unit" type="optiongroup" appearance="combo" gui-text="Units (mm or in):">
+ <option value="G21 (All units in mm)">mm</option>
+ <option value="G20 (All units in inches)">in</option>
+ </param>
+ <param name="postprocessor" type="optiongroup" appearance="combo" gui-text="Post-processor:">
+ <option context="GCode postprocessor" value=" ">None</option>
+ <option value="parameterize();">Parameterize Gcode</option>
+ <option value="flip(y);parameterize();">Flip y axis and parameterize Gcode</option>
+ <option value="round(4);">Round all values to 4 digits</option>
+ <option value='regex("G01 Z([0-9\.\-]+).*\(Penetrate\)", lambda match: "G00 Z%f (Fast pre-penetrate)\n%s" %(float(match.group(1))+5, match.group(0)));'>Fast pre-penetrate</option>
+ </param>
+ <param name="postprocessor-custom" type="string" gui-text="Additional post-processor:"></param>
+
+
+ <param name="create-log" type="bool" gui-text="Generate log file">false</param>
+ <param name="log-filename" type="string" gui-text="Full path to log file:"></param>
+
+ </page>
+
+ <page name='help' gui-text='Help'>
+ <label xml:space="preserve">
+Gcodetools plug-in:
+Converts paths to Gcode (using circular interpolation), makes offset paths and engraves sharp corners using cone cutters.
+This plug-in calculates Gcode for paths using circular interpolation or linear motion when needed.
+
+Tutorials, manuals and support can be found at
+English support forum:
+ http://www.cnc-club.ru/gcodetools
+
+and Russian support forum:
+ http://www.cnc-club.ru/gcodetoolsru
+
+Credits: Nick Drobchenko, Vladimir Kalyaev, John Brooker, Henry Nicolas, Chris Lusby Taylor.
+
+Gcodetools ver. 1.7
+</label>
+
+ </page>
+
+ </param>
+ <effect>
+ <object-type>path</object-type>
+ <effects-menu>
+ <submenu name="Gcodetools"/>
+ </effects-menu>
+ </effect>
+ <script>
+ <command location="inx" interpreter="python">gcodetools.py</command>
+ </script>
+</inkscape-extension>
diff --git a/share/extensions/other/gcodetools/gcodetools_lathe.inx b/share/extensions/other/gcodetools/gcodetools_lathe.inx
new file mode 100644
index 0000000..ac486bb
--- /dev/null
+++ b/share/extensions/other/gcodetools/gcodetools_lathe.inx
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
+ <name>Lathe</name>
+ <id>ru.cnc-club.filter.gcodetools_lathe_lathe_modify_path_ptg</id>
+ <param name='active-tab' type="notebook">
+
+ <page name='lathe' gui-text='Lathe'>
+ <param name="lathe-width" type="float" precision="5" min="0" max="1000" gui-text="Lathe width:">10</param>
+ <param name="lathe-fine-cut-width" type="float" precision="5" min="0" max="1000" gui-text="Fine cut width:">1</param>
+ <param name="lathe-fine-cut-count" type="int" min="0" max="1000" gui-text="Fine cut count:">1</param>
+ <param name="lathe-create-fine-cut-using" gui-text="Create fine cut using:" type="optiongroup" appearance="combo">
+ <option value="Move path">Move path</option>
+ <option value="Offset path">Offset path</option>
+ </param>
+ <param name="lathe-x-axis-remap" type="string" gui-text="Lathe X axis remap:">X</param>
+ <param name="lathe-z-axis-remap" type="string" gui-text="Lathe Z axis remap:">Z</param>
+ </page>
+
+ <page name='lathe_modify_path' gui-text='Lathe modify path'>
+ <label xml:space="preserve">
+ This function modifies path so it will be possible to be cut it with a rectangular cutter.
+ </label>
+ <param name="lathe-rectangular-cutter-width" type="float" precision="5" min="0" max="1000" gui-text="Lathe width:">4</param>
+ </page>
+
+
+ <page name='path-to-gcode' gui-text='Path to Gcode'>
+ <param name="biarc-tolerance" type='float' precision="5" gui-text='Biarc interpolation tolerance:'>1</param>
+ <param name="biarc-max-split-depth" type="int" gui-text="Maximum splitting depth:">4</param>
+ <param name="path-to-gcode-order" gui-text="Cutting order:" type="optiongroup" appearance="combo">
+ <option value="subpath by subpath">Subpath by subpath</option>
+ <option value="path by path">Path by path</option>
+ <option value="pass by pass">Pass by Pass</option>
+ </param>
+
+ <param name="path-to-gcode-depth-function" type="string" gui-text="Depth function:">d</param>
+ <param name="path-to-gcode-sort-paths" type="bool" gui-text="Sort paths to reduce rapid distance">true</param>
+
+ <label xml:space="preserve">
+Biarc interpolation tolerance is the maximum distance between path and its approximation.
+The segment will be split into two segments if the distance between path's segment and its approximation exceeds biarc interpolation tolerance.
+For depth function c=color intensity from 0.0 (white) to 1.0 (black), d is the depth defined by orientation points, s - surface defined by orientation points.
+</label>
+ </page>
+
+ <page name='options' gui-text='Options'>
+ <param name="Zscale" type="float" precision="5" min="-100000" max="100000" gui-text="Scale along Z axis:">1</param>
+ <param name="Zoffset" type="float" precision="5" min="-100000" max="100000" gui-text="Offset along Z axis:">0.0</param>
+ <param name="auto_select_paths" type="bool" gui-text="Select all paths if nothing is selected">true</param>
+ <param name="min-arc-radius" type="float" precision="5" min="-1000" max="1000" gui-text="Minimum arc radius:">0.05</param>
+ <param name="comment-gcode" type="string" gui-text="Comment Gcode:"></param>
+ <param name="comment-gcode-from-properties" type="bool" gui-text="Get additional comments from object's properties">false</param>
+
+ </page>
+
+ <page name='preferences' gui-text='Preferences'>
+ <param name="filename" type="string" gui-text="File:">output.ngc</param>
+ <param name="add-numeric-suffix-to-filename" type="bool" gui-text="Add numeric suffix to filename">true</param>
+
+ <param name="directory" type="string" gui-text="Directory:">/home</param>
+
+ <param name="Zsafe" type="float" precision="5" min="-1000" max="1000" gui-text="Z safe height for G00 move over blank:">5</param>
+ <param name="unit" type="optiongroup" appearance="combo" gui-text="Units (mm or in):">
+ <option value="G21 (All units in mm)">mm</option>
+ <option value="G20 (All units in inches)">in</option>
+ </param>
+ <param name="postprocessor" type="optiongroup" appearance="combo" gui-text="Post-processor:">
+ <option context="GCode postprocessor" value=" ">None</option>
+ <option value="parameterize();">Parameterize Gcode</option>
+ <option value="flip(y);parameterize();">Flip y axis and parameterize Gcode</option>
+ <option value="round(4);">Round all values to 4 digits</option>
+ <option value='regex("G01 Z([0-9\.\-]+).*\(Penetrate\)", lambda match: "G00 Z%f (Fast pre-penetrate)\n%s" %(float(match.group(1))+5, match.group(0)));'>Fast pre-penetrate</option>
+ </param>
+ <param name="postprocessor-custom" type="string" gui-text="Additional post-processor:"></param>
+
+
+ <param name="create-log" type="bool" gui-text="Generate log file">false</param>
+ <param name="log-filename" type="string" gui-text="Full path to log file:"></param>
+
+ </page>
+
+ <page name='help' gui-text='Help'>
+ <label xml:space="preserve">
+Gcodetools plug-in:
+Converts paths to Gcode (using circular interpolation), makes offset paths and engraves sharp corners using cone cutters.
+This plug-in calculates Gcode for paths using circular interpolation or linear motion when needed.
+
+Tutorials, manuals and support can be found at
+English support forum:
+ http://www.cnc-club.ru/gcodetools
+
+and Russian support forum:
+ http://www.cnc-club.ru/gcodetoolsru
+
+Credits: Nick Drobchenko, Vladimir Kalyaev, John Brooker, Henry Nicolas, Chris Lusby Taylor.
+
+Gcodetools ver. 1.7
+</label>
+
+ </page>
+
+ </param>
+ <effect>
+ <object-type>path</object-type>
+ <effects-menu>
+ <submenu name="Gcodetools"/>
+ </effects-menu>
+ </effect>
+ <script>
+ <command location="inx" interpreter="python">gcodetools.py</command>
+ </script>
+</inkscape-extension>
diff --git a/share/extensions/other/gcodetools/gcodetools_orientation_points.inx b/share/extensions/other/gcodetools/gcodetools_orientation_points.inx
new file mode 100644
index 0000000..41aeeb6
--- /dev/null
+++ b/share/extensions/other/gcodetools/gcodetools_orientation_points.inx
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
+ <name>Orientation points</name>
+ <id>ru.cnc-club.filter.gcodetools_orientation_no_options_no_preferences</id>
+ <param name='active-tab' type="notebook">
+
+ <page name='orientation' gui-text='Orientation'>
+ <param name="orientation-points-count" type="optiongroup" appearance="radio" gui-text="Orientation type:">
+ <option value="2">2-points mode (move and rotate, maintained aspect ratio X/Y)</option>
+ <option value="3">3-points mode (move, rotate and mirror, different X/Y scale)</option>
+ <option value="graffiti">graffiti points</option>
+ <option value="in-out reference point">in-out reference point</option>
+ </param>
+ <param name="Zsurface" type="float" precision="5" min="-1000" max="1000" gui-text="Z surface:">0</param>
+ <param name="Zdepth" type="float" precision="5" min="-1000" max="1000" gui-text="Z depth:">-1</param>
+ <param name="unit" type="optiongroup" appearance="combo" gui-text="Units (mm or in):">
+ <option value="G21 (All units in mm)">mm</option>
+ <option value="G20 (All units in inches)">in</option>
+ </param>
+ </page>
+
+ <page name='help' gui-text='Help'>
+ <label xml:space="preserve">
+Orientation points are used to calculate transformation (offset,scale,mirror,rotation in XY plane) of the path.
+3-points mode only: do not put all three into one line (use 2-points mode instead).
+You can modify Z surface, Z depth values later using text tool (3rd coordinates).
+If there are no orientation points inside current layer, they are taken from the upper layer.
+Do not ungroup orientation points!
+You can select them using double click to enter the group or by Ctrl+Click. Now press apply to create control points (independent set for each layer).
+ </label>
+ </page>
+
+ <page name='about' gui-text='About'>
+ <label xml:space="preserve">
+Gcodetools plug-in:
+Converts paths to Gcode (using circular interpolation), makes offset paths and engraves sharp corners using cone cutters. This plug-in calculates Gcode for paths using circular interpolation or linear motion when needed.
+
+Tutorials, manuals and support can be found at English support forum: http://www.cnc-club.ru/gcodetools and Russian support forum: http://www.cnc-club.ru/gcodetoolsru
+
+Credits: Nick Drobchenko, Vladimir Kalyaev, John Brooker, Henry Nicolas, Chris Lusby Taylor.
+
+Gcodetools ver. 1.7
+ </label>
+ </page>
+
+ </param>
+ <effect>
+ <object-type>path</object-type>
+ <effects-menu>
+ <submenu name="Gcodetools"/>
+ </effects-menu>
+ </effect>
+ <script>
+ <command location="inx" interpreter="python">gcodetools.py</command>
+ </script>
+</inkscape-extension>
diff --git a/share/extensions/other/gcodetools/gcodetools_path_to_gcode.inx b/share/extensions/other/gcodetools/gcodetools_path_to_gcode.inx
new file mode 100644
index 0000000..9c6365c
--- /dev/null
+++ b/share/extensions/other/gcodetools/gcodetools_path_to_gcode.inx
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
+ <name>Path to Gcode</name>
+ <id>ru.cnc-club.filter.gcodetools_ptg</id>
+ <param name='active-tab' type="notebook">
+
+ <page name='path-to-gcode' gui-text='Path to Gcode'>
+ <param name="biarc-tolerance" type='float' precision="5" gui-text='Biarc interpolation tolerance:'>1</param>
+ <param name="biarc-max-split-depth" type="int" gui-text="Maximum splitting depth:">4</param>
+ <param name="path-to-gcode-order" gui-text="Cutting order:" type="optiongroup" appearance="combo">
+ <option value="subpath by subpath">Subpath by subpath</option>
+ <option value="path by path">Path by path</option>
+ <option value="pass by pass">Pass by Pass</option>
+ </param>
+
+ <param name="path-to-gcode-depth-function" type="string" gui-text="Depth function:">d</param>
+ <param name="path-to-gcode-sort-paths" type="bool" gui-text="Sort paths to reduce rapid distance">true</param>
+
+ <label xml:space="preserve">
+Biarc interpolation tolerance is the maximum distance between path and its approximation.
+The segment will be split into two segments if the distance between path's segment and its approximation exceeds biarc interpolation tolerance.
+For depth function c=color intensity from 0.0 (white) to 1.0 (black), d is the depth defined by orientation points, s - surface defined by orientation points.
+</label>
+ </page>
+
+ <page name='options' gui-text='Options'>
+ <param name="Zscale" type="float" precision="5" min="-100000" max="100000" gui-text="Scale along Z axis:">1</param>
+ <param name="Zoffset" type="float" precision="5" min="-100000" max="100000" gui-text="Offset along Z axis:">0.0</param>
+ <param name="auto_select_paths" type="bool" gui-text="Select all paths if nothing is selected">true</param>
+ <param name="min-arc-radius" type="float" precision="5" min="-1000" max="1000" gui-text="Minimum arc radius:">0.05</param>
+ <param name="comment-gcode" type="string" gui-text="Comment Gcode:"></param>
+ <param name="comment-gcode-from-properties" type="bool" gui-text="Get additional comments from object's properties">false</param>
+
+ </page>
+
+ <page name='preferences' gui-text='Preferences'>
+ <param name="filename" type="string" gui-text="File:">output.ngc</param>
+ <param name="add-numeric-suffix-to-filename" type="bool" gui-text="Add numeric suffix to filename">true</param>
+
+ <param name="directory" type="string" gui-text="Directory:">/home</param>
+
+ <param name="Zsafe" type="float" precision="5" min="-1000" max="1000" gui-text="Z safe height for G00 move over blank:">5</param>
+ <param name="unit" type="optiongroup" appearance="combo" gui-text="Units (mm or in):">
+ <option value="G21 (All units in mm)">mm</option>
+ <option value="G20 (All units in inches)">in</option>
+ </param>
+ <param name="postprocessor" type="optiongroup" appearance="combo" gui-text="Post-processor:">
+ <option context="GCode postprocessor" value=" ">None</option>
+ <option value="parameterize();">Parameterize Gcode</option>
+ <option value="flip(y);parameterize();">Flip y axis and parameterize Gcode</option>
+ <option value="round(4);">Round all values to 4 digits</option>
+ <option value='regex("G01 Z([0-9\.\-]+).*\(Penetrate\)", lambda match: "G00 Z%f (Fast pre-penetrate)\n%s" %(float(match.group(1))+5, match.group(0)));'>Fast pre-penetrate</option>
+ </param>
+ <param name="postprocessor-custom" type="string" gui-text="Additional post-processor:"></param>
+
+
+ <param name="create-log" type="bool" gui-text="Generate log file">false</param>
+ <param name="log-filename" type="string" gui-text="Full path to log file:"></param>
+
+ </page>
+
+ <page name='help' gui-text='Help'>
+ <label xml:space="preserve">
+Gcodetools plug-in:
+Converts paths to Gcode (using circular interpolation), makes offset paths and engraves sharp corners using cone cutters.
+This plug-in calculates Gcode for paths using circular interpolation or linear motion when needed.
+
+Tutorials, manuals and support can be found at
+English support forum:
+ http://www.cnc-club.ru/gcodetools
+
+and Russian support forum:
+ http://www.cnc-club.ru/gcodetoolsru
+
+Credits: Nick Drobchenko, Vladimir Kalyaev, John Brooker, Henry Nicolas, Chris Lusby Taylor.
+
+Gcodetools ver. 1.7
+</label>
+
+ </page>
+
+ </param>
+ <effect>
+ <object-type>path</object-type>
+ <effects-menu>
+ <submenu name="Gcodetools"/>
+ </effects-menu>
+ </effect>
+ <script>
+ <command location="inx" interpreter="python">gcodetools.py</command>
+ </script>
+</inkscape-extension>
diff --git a/share/extensions/other/gcodetools/gcodetools_prepare_path_for_plasma.inx b/share/extensions/other/gcodetools/gcodetools_prepare_path_for_plasma.inx
new file mode 100644
index 0000000..53e6035
--- /dev/null
+++ b/share/extensions/other/gcodetools/gcodetools_prepare_path_for_plasma.inx
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
+ <name>Prepare path for plasma</name>
+ <id>ru.cnc-club.filter.gcodetools_plasma-prepare-path_no_options_no_preferences</id>
+ <param name='active-tab' type="notebook">
+
+ <page name='plasma-prepare-path' gui-text='Prepare path for plasma or laser cutters'>
+ <param name='in-out-path' type="bool" gui-text="Create in-out paths">true</param>
+ <param name='in-out-path-len' type="float" precision="5" min="0" max="1000000" gui-text='In-out path length:'>10</param>
+ <param name='in-out-path-point-max-dist' type="float" precision="5" min="0" max="1000000" gui-text='In-out path max distance to reference point:'>10</param>
+ <param name="in-out-path-type" gui-text="In-out path type:" type="optiongroup" appearance="combo">
+ <option value="Round">Round</option>
+ <option value="Perpendicular">Perpendicular</option>
+ <option value="Tangent">Tangent</option>
+ </param>
+ <param name='in-out-path-radius' type="float" precision="5" min="0" max="1000000" gui-text='In-out path radius for round path:'>10</param>
+ <param name='in-out-path-replace-original-path' type="bool" gui-text="Replace original path">false</param>
+ <param name='in-out-path-do-not-add-reference-point' type="bool" gui-text="Do not add in-out reference points">false</param>
+
+ <label>-------------------------------------------------</label>
+ <param name='plasma-prepare-corners' type="bool" gui-text="Prepare corners">true</param>
+ <param name='plasma-prepare-corners-distance' type="float" precision="5" min="0" max="1000000" gui-text='Stepout distance for corners:'>10</param>
+ <param name='plasma-prepare-corners-tolerance' type="float" precision="5" min="0" max="180" gui-text='Maximum angle for corner (0-180 deg):'>140</param>
+
+
+ </page>
+
+ <page name='help' gui-text='Help'>
+ <label xml:space="preserve">
+Gcodetools plug-in:
+Converts paths to Gcode (using circular interpolation), makes offset paths and engraves sharp corners using cone cutters.
+This plug-in calculates Gcode for paths using circular interpolation or linear motion when needed.
+
+Tutorials, manuals and support can be found at
+English support forum:
+ http://www.cnc-club.ru/gcodetools
+
+and Russian support forum:
+ http://www.cnc-club.ru/gcodetoolsru
+
+Credits: Nick Drobchenko, Vladimir Kalyaev, John Brooker, Henry Nicolas, Chris Lusby Taylor.
+
+Gcodetools ver. 1.7
+</label>
+
+ </page>
+
+ </param>
+ <effect>
+ <object-type>path</object-type>
+ <effects-menu>
+ <submenu name="Gcodetools"/>
+ </effects-menu>
+ </effect>
+ <script>
+ <command location="inx" interpreter="python">gcodetools.py</command>
+ </script>
+</inkscape-extension>
diff --git a/share/extensions/other/gcodetools/gcodetools_tools_library.inx b/share/extensions/other/gcodetools/gcodetools_tools_library.inx
new file mode 100644
index 0000000..ca78a0c
--- /dev/null
+++ b/share/extensions/other/gcodetools/gcodetools_tools_library.inx
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
+ <name>Tools library</name>
+ <id>ru.cnc-club.filter.gcodetools_tools_library_no_options_no_preferences</id>
+ <param name='active-tab' type="notebook">
+
+ <page name='tools_library' gui-text='Tools library'>
+
+ <param type='optiongroup' appearance="radio" name='tools-library-type' gui-text="Tools type:">
+ <option value='default tool'>default</option>
+ <option value='cylinder cutter'>cylinder</option>
+ <option value='cone cutter'>cone</option>
+ <option value='plasma cutter'>plasma</option>
+ <option value='tangent knife'>tangent knife</option>
+ <option value='lathe cutter'>lathe cutter</option>
+ <option value='graffiti'>graffiti</option>
+
+
+ <option value='check'>Just check tools</option>
+
+ </param>
+
+ <label xml:space="preserve">
+Selected tool type fills appropriate default values. You can change these values using the Text tool later on.
+
+The topmost (z order) tool in the active layer is used. If there is no tool inside the current layer it is taken from the upper layer.
+
+Press Apply to create new tool.
+ </label>
+ </page>
+
+ <page name='help' gui-text='Help'>
+ <label xml:space="preserve">
+Gcodetools plug-in: converts paths to Gcode (using circular interpolation), makes offset paths and engraves sharp corners using cone cutters.
+This plug-in calculates Gcode for paths using circular interpolation or linear motion when needed.
+
+Tutorials, manuals and support can be found at
+English support forum:
+ http://www.cnc-club.ru/gcodetools
+
+and Russian support forum:
+ http://www.cnc-club.ru/gcodetoolsru
+
+Credits: Nick Drobchenko, Vladimir Kalyaev, John Brooker, Henry Nicolas, Chris Lusby Taylor.
+
+Gcodetools ver. 1.7
+</label>
+
+ </page>
+
+ </param>
+ <effect>
+ <object-type>path</object-type>
+ <effects-menu>
+ <submenu name="Gcodetools"/>
+ </effects-menu>
+ </effect>
+ <script>
+ <command location="inx" interpreter="python">gcodetools.py</command>
+ </script>
+</inkscape-extension>
diff --git a/share/extensions/other/gcodetools/genpofiles.sh b/share/extensions/other/gcodetools/genpofiles.sh
new file mode 100755
index 0000000..5106c52
--- /dev/null
+++ b/share/extensions/other/gcodetools/genpofiles.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+OLDPATH=`pwd`
+
+cd ../..
+find share/extensions -name "*.inx" | sort | xargs -n 1 printf "[type: gettext/xml] %s\n"
+cd ${OLDPATH}
diff --git a/share/extensions/other/gcodetools/setup.cfg b/share/extensions/other/gcodetools/setup.cfg
new file mode 100644
index 0000000..b7e4789
--- /dev/null
+++ b/share/extensions/other/gcodetools/setup.cfg
@@ -0,0 +1,2 @@
+[aliases]
+test=pytest
diff --git a/share/extensions/other/gcodetools/tests/data/refs/gcodetools__--active-tab__orientation__--Zsurface__0__00000000000001e-5__--Zdepth__-9__71445146547012e-17__--orientation-points-count__3.out b/share/extensions/other/gcodetools/tests/data/refs/gcodetools__--active-tab__orientation__--Zsurface__0__00000000000001e-5__--Zdepth__-9__71445146547012e-17__--orientation-points-count__3.out
new file mode 100644
index 0000000..61a62cc
--- /dev/null
+++ b/share/extensions/other/gcodetools/tests/data/refs/gcodetools__--active-tab__orientation__--Zsurface__0__00000000000001e-5__--Zdepth__-9__71445146547012e-17__--orientation-points-count__3.out
@@ -0,0 +1,41 @@
+<!-- Created with Inkscape (http://www.inkscape.org/) --><svg xmlns:ns1="https://launchpad.net/jessyink" 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="1000" height="1000" viewBox="0 0 1000 1000" version="1.1" id="svg8" inkscape:version="0.92.4 5da689c313, 2019-01-14" sodipodi:docname="test.svg">
+ <defs id="defs33">
+ <marker inkscape:stockid="Arrow2Lstart" orient="auto" refY="0.0" refX="0.0" id="Arrow2Lstart" style="overflow:visible" inkscape:isstock="true">
+ <path id="path859" style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1" d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z " transform="scale(1.1) translate(1,0)"/>
+ </marker>
+ </defs>
+ <sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="1920" inkscape:window-height="1017" id="base" showgrid="true" inkscape:snap-text-baseline="true" inkscape:zoom="0.6675088" inkscape:cx="202.7349" inkscape:cy="481.16986" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="webslicer-layer">
+ <inkscape:grid type="xygrid" id="grid27" spacingx="10" spacingy="10" empspacing="10" color="#8080ff" opacity="0.25098039" empcolor="#0000ff" empopacity="0.25098039"/>
+ </sodipodi:namedview>
+ <g inkscape:groupmode="layer" id="webslicer-layer" inkscape:label="Slide3" style="display:inline">
+ <rect height="201.49811" width="248.69112" y="353.92661" x="651.3089" id="slicerect1" style="opacity:0.5;fill:#ff0000;stroke-width:1.11927199">
+ <desc id="desc51">format: png
+dpi: 96
+layout-disposition: bg-el-norepeat
+layout-position-anchor: tl</desc>
+ </rect>
+ <svg:g gcodetools="Gcodetools orientation group"><g gcodetools="Gcodetools orientation point (3 points)"><svg:path style="stroke:none;fill:#000000;" gcodetools="Gcodetools orientation point arrow" d="m 0 1000 l 2.9375 -6.34375 l 0.8125 1.90625 l 6.84375 -6.84375 l 0 0 l 0.6875 0.6875 l -6.84375 6.84375 l 1.90625 0.8125 z"/><svg:text x="10.0" y="990.0" style="font-family:DejaVu Sans;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:DejaVu Sans;fill:#000000;fill-opacity:1;stroke:none;font-size:10.000000px;" gcodetools="Gcodetools orientation point text" xml:space="preserve"><tspan x="10.0" y="990.0" sodipodi:role="line">(0.0; 0.0; 0.00000)</tspan></svg:text></g><g gcodetools="Gcodetools orientation point (3 points)"><svg:path style="stroke:none;fill:#000000;" gcodetools="Gcodetools orientation point arrow" d="m 100 1000 l 2.9375 -6.34375 l 0.8125 1.90625 l 6.84375 -6.84375 l 0 0 l 0.6875 0.6875 l -6.84375 6.84375 l 1.90625 0.8125 z"/><svg:text x="110.0" y="990.0" style="font-family:DejaVu Sans;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:DejaVu Sans;fill:#000000;fill-opacity:1;stroke:none;font-size:10.000000px;" gcodetools="Gcodetools orientation point text" xml:space="preserve"><tspan x="110.0" y="990.0" sodipodi:role="line">(100.0; 0.0; -0.00000)</tspan></svg:text></g><g gcodetools="Gcodetools orientation point (3 points)"><svg:path style="stroke:none;fill:#000000;" gcodetools="Gcodetools orientation point arrow" d="m 0 900 l 2.9375 -6.34375 l 0.8125 1.90625 l 6.84375 -6.84375 l 0 0 l 0.6875 0.6875 l -6.84375 6.84375 l 1.90625 0.8125 z"/><svg:text x="10.0" y="890.0" style="font-family:DejaVu Sans;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:DejaVu Sans;fill:#000000;fill-opacity:1;stroke:none;font-size:10.000000px;" gcodetools="Gcodetools orientation point text" xml:space="preserve"><tspan x="10.0" y="890.0" sodipodi:role="line">(0.0; 100.0; 0.0)</tspan></svg:text></g></svg:g></g>
+ <g inkscape:groupmode="layer" id="layer2" inkscape:label="Slide2" style="display:inline">
+ <circle style="display:inline;fill:#000080;stroke:none" id="c1" cx="150" cy="450" r="50" inkscape:label="#path3736"/>
+ <ellipse style="display:inline;fill:none;stroke:#ff0000;stroke-width:16" id="c2" cx="400" cy="450" rx="100" ry="50" inkscape:label="#path3738"/>
+ <path style="display:inline;fill:#ffff00;stroke:#008000;stroke-width:16" id="c3" sodipodi:type="arc" sodipodi:cx="700" sodipodi:cy="450" sodipodi:rx="100" sodipodi:ry="50" sodipodi:start="0.59013865" sodipodi:end="5.6484511" d="m 783.08635,477.82381 a 100,50 0 0 1 -111.09848,20.17442 100,50 0 0 1 -71.96301,-46.88343 100,50 0 0 1 67.71127,-48.44091 100,50 0 0 1 112.7868,17.67793 L 700,450 Z" inkscape:label="#path3740"/>
+ <path style="display:inline;fill:none;stroke:#000000;stroke-width:10;marker-start:url(#Arrow2Lstart)" d="M 100,600 200,700 300,600 400,700" id="p1" inkscape:connector-curvature="0" inkscape:label="#path3746"/>
+ <path style="display:inline;fill:none;stroke:#000000;stroke-width:10" d="m 500,600 c 0,0 0,100 100,100 100,0 0,-100 100,-100 100,0 100,100 100,100" id="p2" inkscape:connector-curvature="0" inkscape:label="#path3748"/>
+ <path sodipodi:type="star" style="display:inline;fill:#ffff00;stroke:#008000;stroke-width:10" id="s1" sodipodi:sides="5" sodipodi:cx="189.03001" sodipodi:cy="847.93945" sodipodi:r1="69.364868" sodipodi:r2="34.682434" sodipodi:arg1="0.63598373" sodipodi:arg2="1.2643023" inkscape:flatsided="false" inkscape:rounded="0" inkscape:randomized="0" d="m 244.8332,889.14005 -45.33887,-8.13446 -32.40428,32.73753 -6.27415,-45.63352 -41.14872,-20.70184 41.46124,-20.06861 6.97297,-45.53197 31.89861,33.23044 45.45824,-7.43847 -21.74681,40.60615 z" inkscape:transform-center-x="6.4673011" inkscape:transform-center-y="-0.16430137"/>
+ <use style="display:inline" x="0" y="0" xlink:href="#s1" inkscape:transform-center-x="6.4673011" inkscape:transform-center-y="-0.16430137" id="u1" transform="translate(200,2.9962152)" width="100%" height="100%" inkscape:label="#use3808"/>
+ </g>
+ <g inkscape:label="Slide1" inkscape:groupmode="layer" id="layer1" style="display:inline">
+ <text xml:space="preserve" style="font-size:14.66666698px;line-height:1.25;font-family:sans-serif;fill:#000000;stroke:none" x="100" y="100" id="t1" inkscape:label="#text12"><tspan sodipodi:role="line" id="tspan10" x="100" y="100">Hello World</tspan></text>
+ <flowRoot xml:space="preserve" id="t4" style="font-size:40px;line-height:1.25;font-family:sans-serif;fill:#000000;stroke:none" transform="matrix(0.26458333,0,0,0.26458333,372.02961,28.904505)" inkscape:label="#flowRoot14"><flowRegion id="flowRegion16"><rect id="rect18" width="264.5675" height="262.16187" x="105.71429" y="219.66254"/></flowRegion><flowPara id="flowPara20" style="font-size:55.43307114px">flow text which wraps</flowPara></flowRoot> <text xml:space="preserve" style="font-size:14.66666698px;line-height:1.25;font-family:sans-serif;fill:#000000;stroke:none" x="200" y="100" id="t2" inkscape:label="#text3727"><tspan sodipodi:role="line" id="tspan3725" x="200" y="100" style="font-size:14.66666698px">UPPER</tspan></text>
+ <text xml:space="preserve" style="font-size:10.58333302px;line-height:1.25;font-family:sans-serif;fill:#000000;stroke:none" x="300" y="100" id="t3" inkscape:label="#text3735"><tspan sodipodi:role="line" id="tspan3733" x="300" y="100" style="font-size:14.66666698px">Multi line</tspan><tspan sodipodi:role="line" x="300" y="118.33334" id="tspan3737" style="font-size:14.66666698px">text</tspan><tspan sodipodi:role="line" x="300" y="136.66667" id="tspan3739" style="font-size:14.66666698px">FOO</tspan></text>
+ <g id="t5" transform="translate(445.71038,-129.64807)" inkscape:label="#g3772">
+ <text id="text3762" y="229.64807" x="54.289616" style="font-size:10.58333302px;line-height:1.25;font-family:sans-serif;fill:#000000;stroke:none" xml:space="preserve"><tspan y="229.64807" x="54.289616" id="tspan3760" sodipodi:role="line" style="font-size:14.66666698px">Grouped</tspan></text>
+ <text id="text3766" y="259.64807" x="54.289619" style="font-size:14.66666698px;line-height:1.25;font-family:sans-serif;fill:#000000;stroke:none" xml:space="preserve"><tspan y="259.64807" x="54.289619" id="tspan3764" sodipodi:role="line" style="font-size:14.66666698px">text</tspan></text>
+ </g>
+ <rect style="fill:#000080;stroke:none" id="r1" width="100" height="100" x="100" y="200" inkscape:label="#rect3732"/>
+ <rect style="fill:none;stroke:#ff0000;stroke-width:16" id="r2" width="200" height="100" x="300" y="200" inkscape:label="#rect3734"/>
+ <rect style="fill:#ffff00;stroke:#008000;stroke-width:16" id="r3" width="200" height="100" x="600" y="200" ry="38.950798" rx="44.943226" inkscape:label="#rect3744"/>
+ </g>
+ <script ns1:version="1.5.5" id="JessyInk">// dummy
+</script>
+</svg> \ No newline at end of file
diff --git a/share/extensions/other/gcodetools/tests/data/refs/gcodetools__06eec9617e749f35cb949d850415f68d.out b/share/extensions/other/gcodetools/tests/data/refs/gcodetools__06eec9617e749f35cb949d850415f68d.out
new file mode 100644
index 0000000..e2ae9a3
--- /dev/null
+++ b/share/extensions/other/gcodetools/tests/data/refs/gcodetools__06eec9617e749f35cb949d850415f68d.out
@@ -0,0 +1,30 @@
+%
+(Header)
+(Generated by gcodetools from Inkscape.)
+(Using default header. To add your own header create file "header" in the output dir.)
+M3
+(Header end.)
+G21 (All units in mm)
+
+(Start cutting path id: p1)
+(Change tool to Default tool)
+
+G00 Z5.000000
+G00 X100.000000 Y400.000000
+
+G01 Z-0.125000 F100.0(Penetrate)
+G01 X200.000000 Y300.000000 Z-0.125000 F400.000000
+G01 X300.000000 Y400.000000 Z-0.125000
+G01 X400.000000 Y300.000000 Z-0.125000
+G00 Z5.000000
+
+(End cutting path id: p1)
+
+
+(Footer)
+M5
+G00 X0.0000 Y0.0000
+M2
+(Using default footer. To add your own footer create file "footer" in the output dir.)
+(end)
+% \ No newline at end of file
diff --git a/share/extensions/other/gcodetools/tests/data/refs/gcodetools__2bf3b298fa730dafb8c6fd51921078f0.out b/share/extensions/other/gcodetools/tests/data/refs/gcodetools__2bf3b298fa730dafb8c6fd51921078f0.out
new file mode 100644
index 0000000..8694e43
--- /dev/null
+++ b/share/extensions/other/gcodetools/tests/data/refs/gcodetools__2bf3b298fa730dafb8c6fd51921078f0.out
@@ -0,0 +1,40 @@
+%
+(Header)
+(Generated by gcodetools from Inkscape.)
+(Using default header. To add your own header create file "header" in the output dir.)
+M3
+(Header end.)
+G21 (All units in mm)
+(Change tool to Default tool)
+
+G01 Z 16.000000 F 800.000000
+G01 X 100.000000 Z 16.000000 F 800.000000
+G01 X 100.000000 Z 16.000000 F 800.000000
+G01 X 100.000000 Z 401.000000 F 800.000000
+G01 X 200.000000 Z 301.000000 F 800.000000
+G01 X 300.000000 Z 401.000000 F 800.000000
+G01 X 400.000000 Z 301.000000 F 800.000000
+G01 X 400.000000 Z 16.000000 F 800.000000
+G01 X 100.000000 Z 16.000000 F 800.000000
+
+(Fine cutting start)
+(Calculating fine cut using Move path)
+
+(Fine cut 1-th cicle start)
+G01 X 100.000000 Z 16.000000 F 800.000000
+G01 X 100.000000 Z 401.000000 F 800.000000
+G01 X 100.000000 Z 400.000000 F 800.000000
+G01 X 100.000000 Z 400.000000 F 800.000000
+G01 X 200.000000 Z 300.000000 F 800.000000
+G01 X 300.000000 Z 400.000000 F 800.000000
+G01 X 400.000000 Z 300.000000 F 800.000000
+G01 Z 16.000000 F 800.000000
+G01 X 100.000000 Z 16.000000 F 800.000000
+
+(Footer)
+M5
+G00 X0.0000 Y0.0000
+M2
+(Using default footer. To add your own footer create file "footer" in the output dir.)
+(end)
+% \ No newline at end of file
diff --git a/share/extensions/other/gcodetools/tests/data/refs/gcodetools__4a9fb751baf0533eadd4d394957c966d.out b/share/extensions/other/gcodetools/tests/data/refs/gcodetools__4a9fb751baf0533eadd4d394957c966d.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/share/extensions/other/gcodetools/tests/data/refs/gcodetools__4a9fb751baf0533eadd4d394957c966d.out
diff --git a/share/extensions/other/gcodetools/tests/data/svg/default-inkscape-SVG.svg b/share/extensions/other/gcodetools/tests/data/svg/default-inkscape-SVG.svg
new file mode 100644
index 0000000..259e13c
--- /dev/null
+++ b/share/extensions/other/gcodetools/tests/data/svg/default-inkscape-SVG.svg
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<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"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ width="793.7007874"
+ height="1122.519685">
+ <defs />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.35"
+ inkscape:cx="375"
+ inkscape:cy="520"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1" />
+ <metadata>
+ <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 inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" />
+</svg>
diff --git a/share/extensions/other/gcodetools/tests/data/svg/shapes.svg b/share/extensions/other/gcodetools/tests/data/svg/shapes.svg
new file mode 100644
index 0000000..eb9caed
--- /dev/null
+++ b/share/extensions/other/gcodetools/tests/data/svg/shapes.svg
@@ -0,0 +1,284 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:ns1="https://launchpad.net/jessyink"
+ 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="1000"
+ height="1000"
+ viewBox="0 0 1000 1000"
+ version="1.1"
+ id="svg8"
+ inkscape:version="0.92.4 5da689c313, 2019-01-14"
+ sodipodi:docname="test.svg">
+ <defs
+ id="defs33">
+ <marker
+ inkscape:stockid="Arrow2Lstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Lstart"
+ style="overflow:visible"
+ inkscape:isstock="true">
+ <path
+ id="path859"
+ style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) translate(1,0)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1017"
+ id="base"
+ showgrid="true"
+ inkscape:snap-text-baseline="true"
+ inkscape:zoom="0.6675088"
+ inkscape:cx="202.7349"
+ inkscape:cy="481.16986"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="webslicer-layer">
+ <inkscape:grid
+ type="xygrid"
+ id="grid27"
+ spacingx="10"
+ spacingy="10"
+ empspacing="10"
+ color="#8080ff"
+ opacity="0.25098039"
+ empcolor="#0000ff"
+ empopacity="0.25098039" />
+ </sodipodi:namedview>
+ <g
+ inkscape:groupmode="layer"
+ id="webslicer-layer"
+ inkscape:label="Slide3"
+ style="display:inline">
+ <rect
+ height="201.49811"
+ width="248.69112"
+ y="353.92661"
+ x="651.3089"
+ id="slicerect1"
+ style="opacity:0.5;fill:#ff0000;stroke-width:1.11927199">
+ <desc
+ id="desc51">format: png
+dpi: 96
+layout-disposition: bg-el-norepeat
+layout-position-anchor: tl</desc>
+ </rect>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="Slide2"
+ style="display:inline">
+ <circle
+ style="display:inline;fill:#000080;stroke:none"
+ id="c1"
+ cx="150"
+ cy="450"
+ r="50"
+ inkscape:label="#path3736" />
+ <ellipse
+ style="display:inline;fill:none;stroke:#ff0000;stroke-width:16"
+ id="c2"
+ cx="400"
+ cy="450"
+ rx="100"
+ ry="50"
+ inkscape:label="#path3738" />
+ <path
+ style="display:inline;fill:#ffff00;stroke:#008000;stroke-width:16"
+ id="c3"
+ sodipodi:type="arc"
+ sodipodi:cx="700"
+ sodipodi:cy="450"
+ sodipodi:rx="100"
+ sodipodi:ry="50"
+ sodipodi:start="0.59013865"
+ sodipodi:end="5.6484511"
+ d="m 783.08635,477.82381 a 100,50 0 0 1 -111.09848,20.17442 100,50 0 0 1 -71.96301,-46.88343 100,50 0 0 1 67.71127,-48.44091 100,50 0 0 1 112.7868,17.67793 L 700,450 Z"
+ inkscape:label="#path3740" />
+ <path
+ style="display:inline;fill:none;stroke:#000000;stroke-width:10;marker-start:url(#Arrow2Lstart)"
+ d="M 100,600 200,700 300,600 400,700"
+ id="p1"
+ inkscape:connector-curvature="0"
+ inkscape:label="#path3746" />
+ <path
+ style="display:inline;fill:none;stroke:#000000;stroke-width:10"
+ d="m 500,600 c 0,0 0,100 100,100 100,0 0,-100 100,-100 100,0 100,100 100,100"
+ id="p2"
+ inkscape:connector-curvature="0"
+ inkscape:label="#path3748" />
+ <path
+ sodipodi:type="star"
+ style="display:inline;fill:#ffff00;stroke:#008000;stroke-width:10"
+ id="s1"
+ sodipodi:sides="5"
+ sodipodi:cx="189.03001"
+ sodipodi:cy="847.93945"
+ sodipodi:r1="69.364868"
+ sodipodi:r2="34.682434"
+ sodipodi:arg1="0.63598373"
+ sodipodi:arg2="1.2643023"
+ inkscape:flatsided="false"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="m 244.8332,889.14005 -45.33887,-8.13446 -32.40428,32.73753 -6.27415,-45.63352 -41.14872,-20.70184 41.46124,-20.06861 6.97297,-45.53197 31.89861,33.23044 45.45824,-7.43847 -21.74681,40.60615 z"
+ inkscape:transform-center-x="6.4673011"
+ inkscape:transform-center-y="-0.16430137" />
+ <use
+ style="display:inline"
+ x="0"
+ y="0"
+ xlink:href="#s1"
+ inkscape:transform-center-x="6.4673011"
+ inkscape:transform-center-y="-0.16430137"
+ id="u1"
+ transform="translate(200,2.9962152)"
+ width="100%"
+ height="100%"
+ inkscape:label="#use3808" />
+ </g>
+ <g
+ inkscape:label="Slide1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ style="display:inline">
+ <text
+ xml:space="preserve"
+ style="font-size:14.66666698px;line-height:1.25;font-family:sans-serif;fill:#000000;stroke:none"
+ x="100"
+ y="100"
+ id="t1"
+ inkscape:label="#text12"><tspan
+ sodipodi:role="line"
+ id="tspan10"
+ x="100"
+ y="100">Hello World</tspan></text>
+ <flowRoot
+ xml:space="preserve"
+ id="t4"
+ style="font-size:40px;line-height:1.25;font-family:sans-serif;fill:#000000;stroke:none"
+ transform="matrix(0.26458333,0,0,0.26458333,372.02961,28.904505)"
+ inkscape:label="#flowRoot14"><flowRegion
+ id="flowRegion16"><rect
+ id="rect18"
+ width="264.5675"
+ height="262.16187"
+ x="105.71429"
+ y="219.66254" /></flowRegion><flowPara
+ id="flowPara20"
+ style="font-size:55.43307114px">flow text which wraps</flowPara></flowRoot> <text
+ xml:space="preserve"
+ style="font-size:14.66666698px;line-height:1.25;font-family:sans-serif;fill:#000000;stroke:none"
+ x="200"
+ y="100"
+ id="t2"
+ inkscape:label="#text3727"><tspan
+ sodipodi:role="line"
+ id="tspan3725"
+ x="200"
+ y="100"
+ style="font-size:14.66666698px">UPPER</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:10.58333302px;line-height:1.25;font-family:sans-serif;fill:#000000;stroke:none"
+ x="300"
+ y="100"
+ id="t3"
+ inkscape:label="#text3735"><tspan
+ sodipodi:role="line"
+ id="tspan3733"
+ x="300"
+ y="100"
+ style="font-size:14.66666698px">Multi line</tspan><tspan
+ sodipodi:role="line"
+ x="300"
+ y="118.33334"
+ id="tspan3737"
+ style="font-size:14.66666698px">text</tspan><tspan
+ sodipodi:role="line"
+ x="300"
+ y="136.66667"
+ id="tspan3739"
+ style="font-size:14.66666698px">FOO</tspan></text>
+ <g
+ id="t5"
+ transform="translate(445.71038,-129.64807)"
+ inkscape:label="#g3772">
+ <text
+ id="text3762"
+ y="229.64807"
+ x="54.289616"
+ style="font-size:10.58333302px;line-height:1.25;font-family:sans-serif;fill:#000000;stroke:none"
+ xml:space="preserve"><tspan
+ y="229.64807"
+ x="54.289616"
+ id="tspan3760"
+ sodipodi:role="line"
+ style="font-size:14.66666698px">Grouped</tspan></text>
+ <text
+ id="text3766"
+ y="259.64807"
+ x="54.289619"
+ style="font-size:14.66666698px;line-height:1.25;font-family:sans-serif;fill:#000000;stroke:none"
+ xml:space="preserve"><tspan
+ y="259.64807"
+ x="54.289619"
+ id="tspan3764"
+ sodipodi:role="line"
+ style="font-size:14.66666698px">text</tspan></text>
+ </g>
+ <rect
+ style="fill:#000080;stroke:none"
+ id="r1"
+ width="100"
+ height="100"
+ x="100"
+ y="200"
+ inkscape:label="#rect3732" />
+ <rect
+ style="fill:none;stroke:#ff0000;stroke-width:16"
+ id="r2"
+ width="200"
+ height="100"
+ x="300"
+ y="200"
+ inkscape:label="#rect3734" />
+ <rect
+ style="fill:#ffff00;stroke:#008000;stroke-width:16"
+ id="r3"
+ width="200"
+ height="100"
+ x="600"
+ y="200"
+ ry="38.950798"
+ rx="44.943226"
+ inkscape:label="#rect3744" />
+ </g>
+ <script
+ ns1:version="1.5.5"
+ id="JessyInk">// dummy
+</script>
+</svg>
diff --git a/share/extensions/other/gcodetools/tests/dev_requirements.txt b/share/extensions/other/gcodetools/tests/dev_requirements.txt
new file mode 100644
index 0000000..0e358d9
--- /dev/null
+++ b/share/extensions/other/gcodetools/tests/dev_requirements.txt
@@ -0,0 +1,11 @@
+# Dev Requirements
+pytest
+pytest-cov
+
+# Code requirements
+typing
+lxml
+numpy
+scour
+pyserial
+cssselect \ No newline at end of file
diff --git a/share/extensions/other/gcodetools/tests/test_gcodetools.py b/share/extensions/other/gcodetools/tests/test_gcodetools.py
new file mode 100644
index 0000000..0575729
--- /dev/null
+++ b/share/extensions/other/gcodetools/tests/test_gcodetools.py
@@ -0,0 +1,65 @@
+# coding=utf-8
+
+import sys
+import os
+
+from gcodetools import Gcodetools
+from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase
+from inkex.tester.filters import CompareOrderIndependentBytes
+
+SETTINGS = (
+ '--id=p1', '--max-area-curves=100',
+ '--area-inkscape-radius=-10', '--area-tool-overlap=0',
+ '--area-fill-angle=0', '--area-fill-shift=0', '--area-fill-method=0',
+ '--area-fill-method=0', '--area-find-artefacts-diameter=5',
+ '--area-find-artefacts-action=mark with an arrow',
+ '--biarc-tolerance=1', '--biarc-max-split-depth=4',
+ '--path-to-gcode-order=subpath by subpath',
+ '--path-to-gcode-depth-function=d',
+ '--path-to-gcode-sort-paths=false', '--Zscale=1', '--Zoffset=0',
+ '--auto_select_paths=true', '--min-arc-radius=0.05000000074505806',
+ '--comment-gcode-from-properties=false', '--create-log=false',
+ '--add-numeric-suffix-to-filename=false', '--Zsafe=5',
+ '--unit=G21 (All units in mm)', '--postprocessor= ',
+)
+FILESET = SETTINGS + ('--directory=/home', '--filename=output.ngc',)
+
+class TestGcodetoolsBasic(ComparisonMixin, InkscapeExtensionTestMixin, TestCase):
+ stderr_protect = False
+ effect_class = Gcodetools
+ comparisons = [
+ FILESET + ('--active-tab="area_fill"',),
+ FILESET + ('--active-tab="area"',),
+ FILESET + ('--active-tab="area_artefacts"',),
+ FILESET + ('--active-tab="dxfpoints"',),
+ FILESET + ('--active-tab="orientation"',),
+ FILESET + ('--active-tab="tools_library"',),
+ FILESET + ('--active-tab="lathe_modify_path"',),
+ FILESET + ('--active-tab="offset"',),
+ FILESET + ('--active-tab="plasma-prepare-path"',),
+ ]
+ compare_filters = [CompareOrderIndependentBytes()]
+ compare_file_extension = 'dxf'
+
+ def test_all_comparisons(self):
+ """
+ gcodetools tries to write to a folder and filename specified
+ on the command line, this needs to be handled carefully.
+ """
+ for tab in (
+ ('--active-tab="path-to-gcode"',),
+ #('--active-tab="engraving"',),
+ #('--active-tab="graffiti"',),
+ ('--active-tab="lathe"',),
+ ):
+ args = SETTINGS + tab + (
+ '--directory={}'.format(self.tempdir),
+ '--filename=output.ngc',
+ )
+ outfile = os.path.join(self.tempdir, 'output.ngc')
+ self.assertCompare(self.compare_file, None, args, 'output.ngc')
+
+class TestGcodeToolsOrientationScientific(ComparisonMixin, TestCase):
+ effect_class = Gcodetools
+ compare_file = "svg/shapes.svg"
+ comparisons = [("--active-tab=orientation", "--Zsurface=0.00000000000001e-5", "--Zdepth=-9.71445146547012e-17", "--orientation-points-count=3")]
diff --git a/share/extensions/other/gcodetools/tests/test_inkex_inx.py b/share/extensions/other/gcodetools/tests/test_inkex_inx.py
new file mode 100644
index 0000000..211b746
--- /dev/null
+++ b/share/extensions/other/gcodetools/tests/test_inkex_inx.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+# coding=utf-8
+"""
+Test elements extra logic from svg xml lxml custom classes.
+"""
+
+import os
+from glob import glob
+
+from inkex.utils import PY3
+from inkex.tester import TestCase
+from inkex.tester.inx import InxMixin
+from inkex.inx import InxFile
+
+class InxTestCase(InxMixin, TestCase):
+ """Test INX files"""
+ def test_inx_effect(self):
+ inx = InxFile("""
+<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
+ <name>TestOne</name>
+ <id>org.inkscape.test.inx_one</id>
+ <effect needs-live-preview="false">
+ <object-type>all</object-type>
+ <effects-menu>
+ <submenu name="Banana">
+ <submenu name="Ice Cream"/>
+ </submenu>
+ </effects-menu>
+ </effect>
+ <script>
+ <command location="inx" interpreter="python">inx_test.py</command>
+ </script>
+</inkscape-extension>""")
+ self.assertEqual(inx.name, 'TestOne')
+ self.assertEqual(inx.ident, 'org.inkscape.test.inx_one')
+ self.assertEqual(inx.slug, 'InxOne')
+ self.assertEqual(inx.metadata, {'type': 'effect', 'preview': False, 'objects': 'all'})
+ self.assertEqual(inx.menu, ['Banana', 'Ice Cream', 'TestOne'])
+ self.assertEqual(inx.warnings, [])
+
+ def test_inx_output(self):
+ inx = InxFile("""
+<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
+ <_name>TestTwo</_name>
+ <id>org.inkscape.test.inx_two</id>
+ <output>
+ <extension>.inx</extension>
+ <mimetype>text/xml+inx</mimetype>
+ <filetypename>Extension (*.inx)</filetypename>
+ <_filetypetooltip>The extension extension repention suspension.</_filetypetooltip>
+ <dataloss>true</dataloss>
+ </output>
+</inkscape-extension>""")
+ self.assertEqual(inx.name, 'TestTwo')
+ self.assertEqual(inx.ident, 'org.inkscape.test.inx_two')
+ self.assertEqual(inx.metadata, {
+ 'dataloss': True,
+ 'extension': '.inx',
+ 'mimetype': 'text/xml+inx',
+ 'name': 'Extension (*.inx)',
+ 'tooltip': 'The extension extension repention suspension.',
+ 'type': 'output'})
+ self.assertEqual(inx.warnings, [
+ 'Use of old translation scheme: <_filetypetooltip...>',
+ 'Use of old translation scheme: <_name...>'])
+
+ def test_inx_input(self):
+ inx = InxFile("""<inkscape-extension>
+ <name>TestThree</name>
+ <id>org.inkscape.test.inx_three</id>
+ <input>
+ <extension>.inx</extension>
+ <mimetype>text/xml+inx</mimetype>
+ <filetypename>Extension (*.inx)</filetypename>
+ <filetypetooltip>The extension extension repention suspension.</filetypetooltip>
+ </input>
+</inkscape-extension>""")
+ self.assertEqual(inx.name, 'TestThree')
+ self.assertEqual(inx.metadata, {
+ 'extension': '.inx',
+ 'mimetype': 'text/xml+inx',
+ 'name': 'Extension (*.inx)',
+ 'tooltip': 'The extension extension repention suspension.',
+ 'type': 'input'})
+ self.assertEqual(inx.warnings, ['No inx xml prefix.'])
+
+ def test_inx_template(self):
+ inx = InxFile("""<inkscape-extension xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
+ <name>TestFour</name>
+ <id>org.inkscape.test.inx_four</id>
+ <effect needs-live-preview="false">
+ <object-type>all</object-type>
+ <effects-menu hidden="true" />
+ </effect>
+ <inkscape:templateinfo>
+ <inkscape:name>Magic Number</inkscape:name>
+ <inkscape:author>Donky Oaty</inkscape:author>
+ <inkscape:shortdesc>Something might happen.</inkscape:shortdesc>
+ <inkscape:date>2070-01-01</inkscape:date>
+ <inkscape:keywords>word food strawberry</inkscape:keywords>
+ </inkscape:templateinfo>
+</inkscape-extension>""")
+ self.assertEqual(inx.name, 'TestFour')
+ self.assertEqual(inx.metadata, {'author': 'Donky Oaty', 'desc': 'Something might happen.', 'type': 'template'})
+ self.assertEqual(inx.warnings, ['No inx xml prefix.'])
+
+
+ def test_inx_files(self):
+ """Get all inx files and test each of them"""
+ if not PY3:
+ self.skipTest("No INX testing in python2")
+ return
+ for inx_file in glob(os.path.join(self._testdir(), '..', '*.inx')):
+ self.assertInxIsGood(inx_file)
diff --git a/share/extensions/other/gcodetools/tox.ini b/share/extensions/other/gcodetools/tox.ini
new file mode 100644
index 0000000..a554a8b
--- /dev/null
+++ b/share/extensions/other/gcodetools/tox.ini
@@ -0,0 +1,14 @@
+[tox]
+envlist = py{36,37,38,39,310}-normal
+skipsdist = True
+
+
+
+[testenv]
+setenv = COVERAGE_FILE=.coverage-{env:TOX_ENV_NAME}
+
+commands =
+ pytest --cov=. --cov-report html --cov-report term {posargs}
+
+deps =
+ -rtests/dev_requirements.txt
diff --git a/share/extensions/other/inkman/MANIFEST.in b/share/extensions/other/inkman/MANIFEST.in
new file mode 100644
index 0000000..cffd671
--- /dev/null
+++ b/share/extensions/other/inkman/MANIFEST.in
@@ -0,0 +1,6 @@
+include inkman/data/*.glade
+include inkman/data/*.ui
+include inkman/data/pixmaps/*.svg
+include inkman/data/pixmaps/*.png
+include manage-extensions.inx
+include manage-extensions.py
diff --git a/share/extensions/other/inkman/inkman/__init__.py b/share/extensions/other/inkman/inkman/__init__.py
new file mode 100644
index 0000000..04089ba
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/__init__.py
@@ -0,0 +1,5 @@
+__pkgname__ = "inkscape-extension-manager"
+__version__ = "1.0"
+__issues__ = "https://gitlab.com/inkscape/extras/extension-manager/-/issues"
+__state__ = f"({__version__})"
+__inkscape__ = ["1.2"]
diff --git a/share/extensions/other/inkman/inkman/archive.py b/share/extensions/other/inkman/inkman/archive.py
new file mode 100644
index 0000000..abc1758
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/archive.py
@@ -0,0 +1,120 @@
+#
+# Copyright (c) Gary Wilson Jr. <gary@thegarywilson.com> and contributors.
+#
+# MIT License, see https://github.com/gdub/python-archive/blob/master/LICENSE.txt
+#
+"""
+Compatability for zip and tar files, taken from upstream and stripped down
+to provide list and read interface, removed PY2 support.
+"""
+
+import os
+import sys
+import tarfile
+import zipfile
+
+
+class ArchiveException(Exception):
+ """Base exception class for all archive errors."""
+
+
+class UnrecognizedArchiveFormat(ArchiveException):
+ """Error raised when passed file is not a recognized archive format."""
+
+
+class Archive(object):
+ """
+ The external API class that encapsulates an archive implementation.
+ """
+
+ def __init__(self, filename, ext=""):
+ """
+ Arguments:
+ * 'file' can be a string path to a file or a file-like object.
+ * Optional 'ext' argument can be given to override the file-type
+ guess that is normally performed using the file extension of the
+ given 'file'. Should start with a dot, e.g. '.tar.gz'.
+ """
+ cls = self._archive_cls(filename, ext=ext)
+ self._archive = cls(filename)
+
+ def __enter__(self):
+ return self._archive
+
+ def __exit__(self, exc, value, traceback):
+ pass
+
+ @staticmethod
+ def _archive_cls(filename, ext=""):
+ """
+ Return the proper Archive implementation class, based on the file type.
+ """
+ cls = None
+ if not isinstance(filename, str):
+ try:
+ filename = filename.name
+ except AttributeError:
+ raise UnrecognizedArchiveFormat(
+ "File object not a recognized archive format."
+ )
+ lookup_filename = filename + ext
+ base, tail_ext = os.path.splitext(lookup_filename.lower())
+ cls = extension_map.get(tail_ext)
+ if not cls:
+ base, ext = os.path.splitext(base)
+ cls = extension_map.get(ext)
+ if not cls:
+ raise UnrecognizedArchiveFormat(
+ "Path not a recognized archive format: %s" % filename
+ )
+ return cls
+
+
+class BaseArchive(object):
+ def __del__(self):
+ if hasattr(self, "_archive"):
+ self._archive.close()
+
+ def list(self):
+ raise NotImplementedError()
+
+ def filenames(self):
+ raise NotImplementedError()
+
+
+class TarArchive(BaseArchive):
+ def __init__(self, filename):
+ # tarfile's open uses different parameters for file path vs. file obj.
+ if isinstance(filename, str):
+ self._archive = tarfile.open(name=filename)
+ else:
+ self._archive = tarfile.open(fileobj=filename)
+
+ def filenames(self):
+ return self._archive.getnames()
+
+ def read(self, name):
+ return self._archive.extractfile(name).read()
+
+
+class ZipArchive(BaseArchive):
+ def __init__(self, file):
+ # ZipFile's 'file' parameter can be path (string) or file-like obj.
+ self._archive = zipfile.ZipFile(file)
+
+ def filenames(self):
+ return self._archive.namelist()
+
+ def read(self, name):
+ return self._archive.read(name)
+
+
+extension_map = {
+ ".egg": ZipArchive,
+ ".zip": ZipArchive,
+ ".tar": TarArchive,
+ ".tar.bz2": TarArchive,
+ ".tar.gz": TarArchive,
+ ".tgz": TarArchive,
+ ".tz2": TarArchive,
+}
diff --git a/share/extensions/other/inkman/inkman/backfoot.py b/share/extensions/other/inkman/inkman/backfoot.py
new file mode 100644
index 0000000..42a7e69
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/backfoot.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2021 Martin Owens <doctormo@gmail.com>
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>
+#
+"""
+When the extension manager fails, this allows us to upgrade automatically.
+"""
+
+import os
+import sys
+import traceback
+
+# Note: All imports are being done as late as possible in this module.
+# If any of the imports caused the error, then we'll still message the user.
+
+
+def update_pip_package(package):
+ """
+ Update the package using the pip update.
+ """
+ from inkex.utils import get_user_directory
+ from inkex.command import ProgramRunError, call
+
+ try:
+ pip = os.path.join(get_user_directory(), "bin", "pip")
+ log = call(pip, "install", "--upgrade", package).decode("utf8")
+ logs = [line for line in log.split("\n") if "skip" not in line]
+ return "\n".join(logs)
+ except ProgramRunError as err:
+ raise IOError(f"Failed to update the package {package}")
+
+
+def attempt_to_recover():
+ """
+ Messages the user, provides a traceback and attepts a self-update
+ """
+ info = sys.exc_info()
+ sys.stderr.write("An error occured with the extensions manager!\n")
+ sys.stderr.write("Trying to self-update the package... ")
+ sys.stderr.flush()
+
+ from inkman import __pkgname__, __version__, __file__, __issues__
+
+ location = os.path.dirname(__file__)
+ update_log = "Not done"
+
+ try:
+ update_log = update_pip_package(__pkgname__)
+ sys.stderr.write("Updated!\n\nPlease try and reload the program again.\n\n")
+ except Exception:
+ sys.stderr.write(
+ "Failed to update!\n\nPlease delete the package manually! (see location below)\n\n"
+ )
+
+ sys.stderr.write(
+ f"""
+Please report this error
+------------------------
+
+Report URL: {__issues__}
+Location: {location}
+{__pkgname__}: {__version__}
+
+{update_log}
+"""
+ )
+
+ traceback.print_exception(*info)
+ del info
+ sys.exit(2)
diff --git a/share/extensions/other/inkman/inkman/data/__init__.py b/share/extensions/other/inkman/inkman/data/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/data/__init__.py
diff --git a/share/extensions/other/inkman/inkman/data/gui.ui b/share/extensions/other/inkman/inkman/data/gui.ui
new file mode 100644
index 0000000..3462d25
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/data/gui.ui
@@ -0,0 +1,736 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.2
+
+Copyright (C) Martin Owens
+
+This file is part of Inkscape Extensions Manager.
+
+Inkscape Extensions Manager 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 3 of the License, or
+(at your option) any later version.
+
+Inkscape Extensions Manager 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 Inkscape Extensions Manager. If not, see <http://www.gnu.org/licenses/>.
+
+-->
+<interface domain="inkscape-extensions-manager">
+ <requires lib="gtk+" version="3.18"/>
+ <!-- interface-license-type gplv3 -->
+ <!-- interface-name Inkscape Extensions Manager -->
+ <!-- interface-description Download and manage inkscape extensions -->
+ <!-- interface-copyright Martin Owens -->
+ <object class="GtkDialog" id="dialog">
+ <property name="can_focus">False</property>
+ <property name="type_hint">dialog</property>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton">
+ <property name="label">gtk-close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ <property name="always_show_image">True</property>
+ <signal name="activate" handler="close_dialog" swapped="no"/>
+ <signal name="clicked" handler="close_dialog" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">20</property>
+ <property name="margin_right">15</property>
+ <property name="margin_top">10</property>
+ <property name="margin_bottom">10</property>
+ <property name="stock">gtk-dialog-error</property>
+ <property name="icon_size">6</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="dialog_msg">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">$message</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <object class="GtkFileFilter" id="filter-for-extensions">
+ <mime-types>
+ <mime-type>application/x-bzip</mime-type>
+ <mime-type>application/x-bzip2</mime-type>
+ <mime-type>application/zip</mime-type>
+ </mime-types>
+ <patterns>
+ <pattern>*.zip</pattern>
+ <pattern>*.tar.bz2</pattern>
+ <pattern>*.tar.gz</pattern>
+ </patterns>
+ </object>
+ <object class="GtkImage" id="img_info">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-info</property>
+ </object>
+ <object class="GtkImage" id="img_install">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-add</property>
+ </object>
+ <object class="GtkImage" id="img_install1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-add</property>
+ </object>
+ <object class="GtkImage" id="img_install_zip">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-open</property>
+ </object>
+ <object class="GtkImage" id="img_uninstall">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-delete</property>
+ </object>
+ <object class="GtkImage" id="img_update">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-save</property>
+ </object>
+ <object class="GtkWindow" id="gui">
+ <property name="can_focus">False</property>
+ <property name="title" translatable="yes">Inkscape Extensions</property>
+ <property name="window_position">center</property>
+ <property name="default_width">600</property>
+ <property name="default_height">400</property>
+ <property name="icon">pixmaps/icon.svg</property>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="main_notebook">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child>
+ <object class="GtkBox" id="box_installed">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">3</property>
+ <child>
+ <object class="GtkBox" id="box_installed_padding">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="local_extensions">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection"/>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="padding">4</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="padding">4</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="buttons_installed">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkButton" id="local_uninstall">
+ <property name="label">_Uninstall Package</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">img_uninstall</property>
+ <property name="use_underline">True</property>
+ <property name="always_show_image">True</property>
+ <signal name="activate" handler="local_uninstall" swapped="no"/>
+ <signal name="clicked" handler="local_uninstall" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">4</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="update_all">
+ <property name="label">Update All</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">img_update</property>
+ <property name="use_underline">True</property>
+ <property name="always_show_image">True</property>
+ <signal name="activate" handler="update_all" swapped="no"/>
+ <signal name="clicked" handler="update_all" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinner" id="loading">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="local_information">
+ <property name="label">_Details</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ <property name="always_show_image">True</property>
+ <signal name="activate" handler="local_information" swapped="no"/>
+ <signal name="clicked" handler="local_information" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">4</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="tab_expand">True</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Active Packages</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">4</property>
+ <property name="margin_right">4</property>
+ <child>
+ <object class="GtkSearchEntry" id="dl-search">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="primary_icon_name">edit-find-symbolic</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">False</property>
+ <signal name="activate" handler="remote_search" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinner" id="dl-searching">
+ <property name="name">searcher</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="events"/>
+ <property name="margin_left">4</property>
+ <property name="margin_right">4</property>
+ <property name="margin_top">4</property>
+ <property name="margin_bottom">4</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">6</property>
+ <property name="pack_type">end</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="remote_getlist">
+ <property name="label">gtk-refresh</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ <property name="always_show_image">True</property>
+ <signal name="activate" handler="remote_getlist" swapped="no"/>
+ <signal name="clicked" handler="remote_getlist" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">4</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkButton" id="remote_info">
+ <property name="label">Details and Comments</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">img_info</property>
+ <property name="use_underline">True</property>
+ <property name="always_show_image">True</property>
+ <signal name="activate" handler="remote_info" swapped="no"/>
+ <signal name="clicked" handler="remote_info" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">4</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="remote_install">
+ <property name="label">_Install Package</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ <property name="always_show_image">True</property>
+ <signal name="activate" handler="remote_install" swapped="no"/>
+ <signal name="clicked" handler="remote_install" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">4</property>
+ <property name="pack_type">end</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="local_install">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">img_install_zip</property>
+ <property name="always_show_image">True</property>
+ <signal name="activate" handler="local_install" swapped="no"/>
+ <signal name="clicked" handler="local_install" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">4</property>
+ <property name="pack_type">end</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">4</property>
+ <property name="pack_type">end</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkInfoBar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="message_type">error</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
+ <property name="layout_style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child internal-child="content_area">
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <property name="spacing">16</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">10</property>
+ <property name="stock">gtk-dialog-warning</property>
+ <property name="icon_size">3</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">&lt;b&gt;Online content!&lt;/b&gt; All packages are peer-reviewed by volunteers in the Inkscape community, but this does not mean these packages are safe. &lt;i&gt;Only download and use extensions if you trust the author or peers and understand the risks of running this software.&lt;/i&gt;</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkScrolledWindow" id="results_found">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="margin_left">4</property>
+ <property name="margin_right">4</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="remote_extensions">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection"/>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="no_results">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="yalign">1</property>
+ <property name="pixbuf">pixmaps/not-found.png</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">4</property>
+ <property name="margin_right">4</property>
+ <property name="margin_top">4</property>
+ <property name="margin_bottom">4</property>
+ <property name="label" translatable="yes">No results found</property>
+ <property name="yalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ <attribute name="scale" value="2"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_expand">True</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Install Packages</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">end</property>
+ <property name="pixbuf">pixmaps/docs.png</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child type="center">
+ <object class="GtkLinkButton">
+ <property name="label" translatable="yes">Find out how to create and upload Extensions</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="receives_default">True</property>
+ <property name="valign">start</property>
+ <property name="relief">none</property>
+ <property name="uri">https://inkscape.org/develop/extensions/</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ <property name="tab_expand">True</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Create Package</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <object class="GtkFileChooserDialog" id="choose-extension">
+ <property name="can_focus">False</property>
+ <property name="type">popup</property>
+ <property name="title" translatable="yes">Choose Extensions Package File</property>
+ <property name="type_hint">dialog</property>
+ <property name="gravity">center</property>
+ <property name="transient_for">gui</property>
+ <property name="filter">filter-for-extensions</property>
+ <property name="local_only">False</property>
+ <property name="preview_widget_active">False</property>
+ <property name="use_preview_label">False</property>
+ <child internal-child="vbox">
+ <object class="GtkBox">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/share/extensions/other/inkman/inkman/data/info.ui b/share/extensions/other/inkman/inkman/data/info.ui
new file mode 100644
index 0000000..ace3436
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/data/info.ui
@@ -0,0 +1,338 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.2
+
+Copyright (C) Martin Owens
+
+This file is part of Inkscape Extensions Manager.
+
+Inkscape Extensions Manager 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 3 of the License, or
+(at your option) any later version.
+
+Inkscape Extensions Manager 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 Inkscape Extensions Manager. If not, see <http://www.gnu.org/licenses/>.
+
+-->
+<interface domain="inkscape-extensions-manager">
+ <requires lib="gtk+" version="3.18"/>
+ <!-- interface-license-type gplv3 -->
+ <!-- interface-name Inkscape Extensions Manager -->
+ <!-- interface-description Download and manage inkscape extensions -->
+ <!-- interface-copyright Martin Owens -->
+ <object class="GtkWindow" id="info">
+ <property name="can_focus">False</property>
+ <property name="title" translatable="yes">Package Information</property>
+ <property name="modal">True</property>
+ <property name="window_position">center-always</property>
+ <property name="default_width">500</property>
+ <property name="default_height">350</property>
+ <property name="icon_name">gtk-about</property>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="info_name">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">7</property>
+ <property name="margin_bottom">7</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Package Name</property>
+ <property name="xalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ <attribute name="scale" value="1.5"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="info_image">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">5</property>
+ <property name="margin_right">5</property>
+ <property name="margin_top">5</property>
+ <property name="margin_bottom">5</property>
+ <property name="stock">gtk-about</property>
+ <property name="icon_size">6</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="height">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="info_desc">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">6</property>
+ <property name="margin_right">6</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label" translatable="yes">Package Description</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <attributes>
+ <attribute name="style" value="italic"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">2</property>
+ <property name="height">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">4</property>
+ <property name="margin_right">8</property>
+ <property name="row_homogeneous">True</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">2</property>
+ <property name="margin_right">6</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label" translatable="yes">License:</property>
+ <property name="xalign">1</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">2</property>
+ <property name="margin_right">6</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label" translatable="yes">Author:</property>
+ <property name="xalign">1</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">2</property>
+ <property name="margin_right">6</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label" translatable="yes">Version:</property>
+ <property name="xalign">1</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">2</property>
+ <property name="margin_right">6</property>
+ <property name="margin_top">2</property>
+ <property name="margin_bottom">2</property>
+ <property name="label" translatable="yes">Website:</property>
+ <property name="xalign">1</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAccelLabel" id="info_author">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">label</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAccelLabel" id="info_license">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">label</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAccelLabel" id="info_version">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">label</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLinkButton" id="info_website">
+ <property name="label" translatable="yes">button</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="focus_on_click">False</property>
+ <property name="receives_default">True</property>
+ <property name="hexpand">True</property>
+ <property name="relief">none</property>
+ <property name="xalign">0</property>
+ <property name="uri">https://inkscape.org</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ <property name="width">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box_inx_padding">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="inx">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection"/>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="padding">4</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="padding">4</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="buttons_installed1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkButton" id="info_close">
+ <property name="label">gtk-close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ <property name="always_show_image">True</property>
+ <signal name="activate" handler="destroy" swapped="no"/>
+ <signal name="clicked" handler="destroy" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">4</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">4</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/share/extensions/other/inkman/inkman/data/package.json b/share/extensions/other/inkman/inkman/data/package.json
new file mode 100644
index 0000000..e064c7e
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/data/package.json
@@ -0,0 +1,20 @@
+{
+ "author" : "doctormo",
+ "dates" : {
+ "created" : "2021-04-22T15:08:20",
+ "edited" : "2021-04-22T15:08:20"
+ },
+ "files" : [],
+ "icon" : "inkman/data/pixmaps/icon.svg",
+ "id" : "org.inkscape.extension.inkman",
+ "license" : "GPLv3",
+ "links" : {
+ "file": "https://media.inkscape.org/static/extensions-manager-fallback.zip"
+ },
+ "name" : "Inkscape Extensions Manager",
+ "summary" : "Manage extensions from inside another extension",
+ "tags" : [
+ "infrastructure"
+ ],
+ "verified" : true
+}
diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/__init__.py b/share/extensions/other/inkman/inkman/data/pixmaps/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/data/pixmaps/__init__.py
diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/core_icon.svg b/share/extensions/other/inkman/inkman/data/pixmaps/core_icon.svg
new file mode 100644
index 0000000..427aa3d
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/data/pixmaps/core_icon.svg
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<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"
+ inkscape:export-ydpi="131.66"
+ inkscape:export-xdpi="131.66"
+ inkscape:export-filename="/home/doctormo/Desktop/mountain.png"
+ sodipodi:docname="inkscape_extensions_icon.svg"
+ inkscape:version="1.0alpha (2b290efb96, 2019-03-26, custom)"
+ version="1.1"
+ id="svg4197"
+ viewBox="0 0 64 64"
+ height="64"
+ width="64">
+ <style
+ id="style4677"></style>
+ <defs
+ id="defs4199" />
+ <sodipodi:namedview
+ inkscape:document-rotation="0"
+ units="px"
+ borderlayer="true"
+ inkscape:pagecheckerboard="true"
+ fit-margin-bottom="0"
+ fit-margin-right="0"
+ fit-margin-left="0"
+ fit-margin-top="0"
+ inkscape:snap-global="false"
+ inkscape:guide-bbox="true"
+ inkscape:window-maximized="1"
+ inkscape:window-y="24"
+ inkscape:window-x="65"
+ inkscape:window-height="1056"
+ inkscape:window-width="1855"
+ showguides="false"
+ showgrid="false"
+ inkscape:current-layer="layer1"
+ inkscape:document-units="px"
+ inkscape:cy="27.110789"
+ inkscape:cx="34.527038"
+ inkscape:zoom="1"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base">
+ <sodipodi:guide
+ inkscape:locked="false"
+ id="guide4855"
+ orientation="0,1"
+ position="213.44347,-263.83675" />
+ <sodipodi:guide
+ inkscape:locked="false"
+ id="guide4857"
+ orientation="0,1"
+ position="161.15542,-119.0723" />
+ <sodipodi:guide
+ inkscape:locked="false"
+ id="guide4859"
+ orientation="0,1"
+ position="123.12774,-219.32709" />
+ <sodipodi:guide
+ inkscape:locked="false"
+ id="guide4861"
+ orientation="0,1"
+ position="198.75096,-19.681776" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata4202">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ transform="translate(-178.06873,-129.03359)"
+ id="layer1"
+ inkscape:groupmode="layer"
+ inkscape:label="Layer 1">
+ <path
+ id="path5071"
+ d="M 209.5405,129.4285 C 207.34998,129.42552 205.1775,130.23263 203.57606,131.87175 L 180.73787,155.24089 180.70575,155.28174 C 178.69019,157.77778 177.82335,159.75839 178.12831,161.55689 178.43326,163.3554 179.93035,164.45862 181.56636,165.15248 184.54546,166.41593 188.47711,166.93408 191.00679,167.90934 190.53854,168.20881 189.88311,168.55956 189.07698,168.93331 188.12313,169.37555 187.1407,169.80609 186.36388,170.40947 185.97547,170.71117 185.58188,171.06598 185.40409,171.68726 185.22629,172.30853 185.49865,173.08033 185.9292,173.52079 186.69583,174.30441 187.76672,174.76695 189.06969,175.28139 190.37267,175.79583 191.89253,176.29082 193.39752,176.78089 194.90252,177.27095 196.39192,177.7572 197.59554,178.23225 198.79916,178.70731 199.73154,179.24185 199.96148,179.47649 200.07286,179.59083 200.05024,179.59563 200.049,179.58443 200.04751,179.57307 200.05699,179.60937 199.99209,179.7405 199.91316,179.89994 199.59031,180.23549 199.33715,180.52234 L 199.11836,180.23061 C 198.37134,179.23804 197.20263,178.83569 196.08289,178.75007 194.96315,178.66446 193.82247,178.87338 192.81987,179.28978 191.81728,179.70618 190.89774,180.31007 190.44372,181.33773 190.21671,181.85157 190.15642,182.49001 190.33724,183.07791 190.51806,183.6658 190.90063,184.17841 191.41519,184.62409 L 191.41668,184.62558 C 192.81687,185.83634 194.72197,185.66624 196.13251,184.89106 196.53857,184.6679 196.85949,184.32058 197.21484,184.01732 197.2126,184.11177 197.15293,184.17908 197.16375,184.27696 197.22208,184.80377 197.49413,185.3136 197.87704,185.70499 199.29802,187.15748 201.22888,187.09479 202.56954,187.41453 203.23986,187.5744 203.76326,187.78361 204.1478,188.12052 204.53235,188.45743 204.85208,188.94085 205.03321,189.9278 205.26463,191.19231 206.31437,192.07739 207.43853,192.40168 208.5627,192.72598 209.82857,192.6867 211.16394,192.46875 213.83468,192.03289 216.77863,190.83884 218.85106,189.32242 L 218.92545,189.26843 218.99109,189.20278 C 219.33189,188.85413 219.60986,188.46483 219.70438,187.95417 219.79889,187.44352 219.60927,186.88523 219.35138,186.5524 218.8356,185.88673 218.24632,185.70061 217.7702,185.47008 217.48913,185.33399 217.44505,185.29804 217.30489,185.21043 219.52047,183.01064 221.49737,182.63752 223.47354,182.17788 224.48172,181.9434 225.5102,181.69612 226.46379,181.07076 227.41739,180.44541 228.20663,179.42814 228.6897,177.98133 228.88529,177.39536 228.8047,176.73308 228.5628,176.24116 228.32089,175.74922 227.9685,175.38884 227.58987,175.07277 226.83261,174.44062 225.91377,173.96692 225.07807,173.51493 224.34155,173.11658 223.77119,172.75489 223.43708,172.48803 224.7278,171.82142 226.649,171.11902 228.93767,170.37152 231.45028,169.55089 234.20492,168.66561 236.55186,167.54902 238.8988,166.43242 240.93825,165.10887 241.75489,163.04615 242.16321,162.0148 242.18237,160.81543 241.7578,159.63289 241.33431,158.45334 240.5111,157.27502 239.26496,156.02709 L 239.25764,156.01835 215.62011,131.85862 215.60698,131.84548 C 213.93873,130.24384 211.73095,129.43155 209.54042,129.42849 Z M 234.714,173.71915 C 232.5042,173.79523 230.15738,174.9607 229.48763,177.32058 L 229.44533,177.47082 V 177.6269 C 229.44533,178.04315 229.64611,178.3869 229.83333,178.59252 230.02056,178.79815 230.20857,178.91889 230.39638,179.02137 230.77199,179.22632 231.1717,179.35388 231.62748,179.46772 232.53904,179.69538 233.65791,179.83206 234.79714,179.86447 235.93637,179.89689 237.07554,179.83102 238.05724,179.56253 238.54809,179.42829 239.0106,179.25051 239.42838,178.91635 239.84616,178.58218 240.21459,177.98998 240.21459,177.35267 V 177.1645 L 240.15333,176.98654 C 239.34785,174.6556 236.9238,173.64305 234.714,173.71915 Z M 229.16819,178.79382 228.74809,179.17015 C 227.9503,179.88577 227.45985,180.71346 227.36966,181.58423 227.27948,182.455 227.63563,183.29405 228.20839,183.84806 229.3539,184.95607 231.26015,185.14361 232.92277,184.16605 L 233.04967,184.09166 233.15324,183.98519 C 233.59318,183.53871 233.70115,182.97178 233.66668,182.46234 233.63222,181.95292 233.45188,181.45508 233.14302,180.98619 232.52532,180.04838 231.379,179.24613 229.72102,178.9076 Z"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.8125;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ d="M 204.3716,132.65025 181.5716,155.98146 C 173.86808,165.52135 186.81421,164.41139 192.36401,167.15913 194.35481,169.19406 184.73346,170.69607 186.72426,172.73269 188.71506,174.76762 198.7624,176.65319 200.75659,178.68812 202.74739,180.72304 196.68165,182.88186 198.67245,184.91679 200.66325,186.95171 205.26771,185.02371 206.12988,189.72152 206.74427,193.07856 214.42743,191.16413 218.185,188.41469 220.1758,186.37807 214.37651,186.56985 216.36731,184.53492 221.318,179.47222 225.92756,182.69517 227.62135,177.62228 228.45806,175.11554 220.33363,173.75779 222.32783,171.72286 228.05583,168.37771 247.8535,166.20022 238.45958,156.8063 L 214.82627,132.65025 C 211.93596,129.87535 207.11255,129.8448 204.3716,132.65025 Z M 230.56088,177.62228 C 230.56088,178.77976 239.08924,179.53841 239.08924,177.34904 237.87405,173.83247 231.56901,174.07007 230.56088,177.62228 Z M 192.14337,183.77289 C 194.16303,185.51929 197.28245,183.33841 198.2176,180.90125 196.26075,178.30116 188.93569,180.99459 192.14337,183.77289 Z M 229.49165,180.00004 C 226.88817,182.33537 229.78357,184.70464 232.34971,183.19584 232.92166,182.6154 232.33444,180.58048 229.49165,180.00004 Z"
+ id="path2313"
+ inkscape:connector-curvature="0"
+ style="opacity:1;fill:#292929;fill-opacity:1;stroke-width:0.436606;stop-opacity:1" />
+ <path
+ d="M 198.91515,168.42184 C 199.52444,168.80031 208.74016,170.67231 210.99232,171.04569 211.77303,171.21031 211.21975,172.01478 210.14373,172.55788 207.71675,173.20281 195.94507,168.42184 198.91515,168.42184 Z"
+ id="path2315"
+ style="opacity:1;fill:#ffffff;stroke-width:0.436606;stop-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ transform="translate(178.06873,129.03359)"
+ d="M 31.679688 3.7441406 C 30.537215 3.7380972 29.393387 4.090031 28.464844 4.8027344 C 28.39423 4.8361426 28.29204 4.8663172 28.25 4.9023438 L 26.128906 7.0703125 C 24.095858 9.0926283 21.577521 11.575345 19.125 14.222656 C 19.118823 14.228833 19.115505 14.235994 19.109375 14.242188 L 16.302734 17.109375 C 15.581634 17.727295 15.567684 18.734057 16.271484 19.367188 L 19.919922 24.447266 C 20.070432 23.674156 20.494753 22.962973 21.132812 22.414062 C 22.810133 20.976713 25.495743 21.005826 27.132812 22.478516 C 28.769883 23.951206 28.737867 26.308734 27.060547 27.746094 C 26.420257 28.292904 25.600597 28.650132 24.716797 28.763672 L 30.363281 33.841797 C 31.067031 34.474897 32.214467 34.487051 32.935547 33.869141 L 38.712891 28.919922 C 38.845461 29.689672 39.248787 30.403017 39.867188 30.960938 C 41.504257 32.433637 44.191811 32.462751 45.869141 31.025391 C 47.546461 29.588041 47.578476 27.228559 45.941406 25.755859 C 45.320616 25.199729 44.516148 24.827829 43.642578 24.693359 L 47.421875 19.742188 C 48.142965 19.124277 48.156895 18.115532 47.453125 17.482422 L 34.859375 4.6699219 C 34.765175 4.5851804 34.580964 4.5192514 34.347656 4.4648438 C 33.539452 3.9959559 32.612718 3.7490762 31.679688 3.7441406 z "
+ style="opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.66165;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-opacity:1"
+ id="rect4513" />
+ </g>
+</svg>
diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/default.svg b/share/extensions/other/inkman/inkman/data/pixmaps/default.svg
new file mode 100644
index 0000000..4595b57
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/data/pixmaps/default.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<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"
+ sodipodi:docname="default.svg"
+ inkscape:version="1.0alpha (2b290efb96, 2019-03-26, custom)"
+ id="svg8"
+ version="1.1"
+ viewBox="0 0 16.93333316 16.93333345"
+ height="64"
+ width="64">
+ <defs
+ id="defs2" />
+ <sodipodi:namedview
+ inkscape:document-rotation="0"
+ inkscape:window-maximized="1"
+ inkscape:window-y="41"
+ inkscape:window-x="140"
+ inkscape:window-height="1685"
+ inkscape:window-width="3060"
+ units="px"
+ showgrid="false"
+ inkscape:current-layer="layer1"
+ inkscape:document-units="mm"
+ inkscape:cy="33.563305"
+ inkscape:cx="31.124255"
+ inkscape:zoom="6.466344"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base" />
+ <metadata
+ id="metadata5">
+ <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 />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ transform="translate(-104.6139974,-111.3056386)"
+ id="layer1"
+ inkscape:groupmode="layer"
+ inkscape:label="Layer 1">
+ <rect
+ y="112.3309021"
+ x="105.7384796"
+ height="14.96549511"
+ width="14.84974003"
+ id="rect835"
+ style="fill:none;fill-rule:evenodd;stroke:#d3d7cf;stroke-width:0.2645833176;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:1.5874999054,1.5874999054;stroke-dashoffset:0" />
+ <g
+ transform="translate(-0.49307671,2.7778151)"
+ style="font-size:10.5833px;line-height:1.25;font-family:sans-serif;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;stroke-width:0.264583;fill:#204a87"
+ id="text11"
+ aria-label="X">
+ <path
+ inkscape:connector-curvature="0"
+ id="path13"
+ style="stroke-width:0.264583;fill:#204a87"
+ d="M 110.82334,113.5657 H 111.94472 L 113.86191,116.43373 115.78943,113.5657 H 116.91081 L 114.43035,117.27089 117.07617,121.28097 H 115.9548 L 113.78439,117.99952 111.59849,121.28097 H 110.47194 L 113.22629,117.16237 Z" />
+ </g>
+ </g>
+</svg>
diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/default_icon.svg b/share/extensions/other/inkman/inkman/data/pixmaps/default_icon.svg
new file mode 100644
index 0000000..a760f78
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/data/pixmaps/default_icon.svg
@@ -0,0 +1,71 @@
+<?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="64"
+ height="64"
+ viewBox="0 0 16.93333316 16.93333345"
+ version="1.1"
+ id="svg8"
+ inkscape:version="0.92.3 (unknown)"
+ sodipodi:docname="default.svg">
+ <defs
+ id="defs2" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="15.99999997"
+ inkscape:cx="29.02735304"
+ inkscape:cy="33.63202807"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ units="px"
+ inkscape:window-width="3060"
+ inkscape:window-height="1685"
+ inkscape:window-x="140"
+ inkscape:window-y="41"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-104.6139974,-111.3056386)">
+ <path
+ style="fill:#eeeeec;fill-rule:evenodd;stroke:#babdb6;stroke-width:0.2386619151;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 108.2894698,113.4403262 c -0.7182845,0.506619 -0.8898933,1.4995894 -0.3833046,2.2178952 0.2866841,0.405192 0.7459924,0.6534367 1.2420265,0.6712842 0.4163061,0.010708 0.7906509,0.2198627 0.5335476,0.9022922 l -2.7910571,1.9683322 5.1978275,7.3704189 7.3704189,-5.1978275 -1.6793944,-2.3813488 c -0.6258858,-0.3783537 -0.8100563,0.06791 -0.8959132,0.4218985 -0.04696,0.4568329 -0.2889598,0.8711156 -0.6638235,1.1364054 -0.7183453,0.5066164 -1.7113753,0.3349578 -2.2179663,-0.3834054 -0.5065329,-0.7183452 -0.3348473,-1.7113024 0.3834765,-2.2178656 0.4060691,-0.2854401 0.9220589,-0.3650913 1.3952995,-0.2153867 0.3640113,0.203938 0.9966101,-0.036635 0.6685328,-0.6281194 l -2.1880389,-3.1025969 -2.7646504,1.9497095 c -1.0190194,0.075719 -0.8191806,-0.502389 -0.7451992,-0.8349773 0.1091227,-0.446087 0.020238,-0.9175675 -0.2438155,-1.293303 -0.5065909,-0.7183632 -1.4996209,-0.8900218 -2.2179662,-0.3834055 z"
+ id="rect815"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccccccccc" />
+ <rect
+ style="fill:none;fill-rule:evenodd;stroke:#d3d7cf;stroke-width:0.2645833176;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:1.5874999054,1.5874999054;stroke-dashoffset:0"
+ id="rect835"
+ width="14.84974003"
+ height="14.96549511"
+ x="105.7384796"
+ y="112.3309021" />
+ </g>
+</svg>
diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/docs.png b/share/extensions/other/inkman/inkman/data/pixmaps/docs.png
new file mode 100644
index 0000000..4613579
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/data/pixmaps/docs.png
Binary files differ
diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/icon.svg b/share/extensions/other/inkman/inkman/data/pixmaps/icon.svg
new file mode 100644
index 0000000..88531a5
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/data/pixmaps/icon.svg
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<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"
+ version="1.1"
+ id="svg4197"
+ viewBox="0 0 64 64"
+ height="64"
+ width="64"
+ sodipodi:docname="icon.svg"
+ inkscape:version="1.0alpha (2b290efb96, 2019-03-26, custom)"
+ inkscape:export-filename="/home/doctormo/Projects/inkscape/extension-manager-icon.png"
+ inkscape:export-xdpi="450"
+ inkscape:export-ydpi="450">
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ inkscape:document-rotation="0"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview11"
+ showgrid="false"
+ inkscape:zoom="7.5328968"
+ inkscape:cx="36.791894"
+ inkscape:cy="23.577671"
+ inkscape:current-layer="svg4197" />
+ <style
+ id="style4677"></style>
+ <defs
+ id="defs4199" />
+ <metadata
+ id="metadata4202">
+ <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 />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <circle
+ r="32"
+ cy="32"
+ cx="32"
+ id="path834"
+ style="vector-effect:none;fill:#ffffff;stroke-width:3.26454;paint-order:stroke fill markers;stop-color:#000000" />
+ <path
+ d="M 7.6191406 52.724609 A 32 32 0 0 0 7.703125 52.826172 A 32 32 0 0 0 8.015625 53.183594 A 32 32 0 0 0 8.3339844 53.539062 A 32 32 0 0 0 8.65625 53.886719 A 32 32 0 0 0 8.984375 54.232422 A 32 32 0 0 0 9.3164062 54.572266 A 32 32 0 0 0 9.6542969 54.90625 A 32 32 0 0 0 9.9863281 55.226562 C 16.105243 54.967467 24.037299 58.544938 32.347656 58.544922 C 40.350548 58.544828 47.993984 55.240607 54.015625 55.222656 A 32 32 0 0 0 54.232422 55.015625 A 32 32 0 0 0 54.572266 54.683594 A 32 32 0 0 0 54.90625 54.345703 A 32 32 0 0 0 55.236328 54.001953 A 32 32 0 0 0 55.560547 53.654297 A 32 32 0 0 0 55.880859 53.300781 A 32 32 0 0 0 56.193359 52.943359 A 32 32 0 0 0 56.501953 52.582031 A 32 32 0 0 0 56.791016 52.232422 C 53.316864 45.16434 43.634403 38.271377 32.347656 38.271484 L 32.296875 38.271484 C 20.765791 38.285588 10.866821 45.496644 7.6191406 52.724609 z "
+ style="vector-effect:none;fill:#292929;fill-opacity:1;stroke-width:2.21703;paint-order:stroke fill markers;stop-color:#000000"
+ id="path839" />
+ <path
+ inkscape:connector-curvature="0"
+ id="rect4513"
+ style="opacity:1;vector-effect:none;fill:#292929;fill-opacity:1;stroke:none;stroke-width:1.99127;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-opacity:1"
+ d="M 19.303148,12.112056 18.542504,27.990548 C 18.541959,28.001003 18.544746,28.01004 18.544258,28.020473 L 18.344944,32.824472 C 18.1985,33.953027 18.993569,34.860619 20.128032,34.859853 L 27.451088,36.456782 C 26.965015,35.647699 26.772409,34.674141 26.900262,33.673637 27.240872,31.048526 29.655443,28.920414 32.294253,28.918636 34.933064,28.916856 36.795449,31.041636 36.454848,33.666756 36.323322,34.667181 35.880031,35.642669 35.184178,36.452628 L 44.284693,36.445255 C 45.419087,36.444503 46.450493,35.535007 46.596926,34.406478 L 47.771375,25.365976 C 48.506804,25.945018 49.438066,26.256673 50.436167,26.257439 53.074986,26.255669 55.491287,24.125999 55.831898,21.500871 56.172505,18.875762 54.308553,16.749243 51.669734,16.751013 50.670942,16.753758 49.656369,17.06786 48.770704,17.64879 L 48.164563,10.209114 C 48.311005,9.080576 47.514329,8.171235 46.379909,8.171995 L 24.270089,7.092808 C 21.243419,6.945075 19.456256,8.915898 19.303148,12.112056 Z"
+ sodipodi:nodetypes="sccccccsccccccsccccss" />
+ <path
+ inkscape:connector-curvature="0"
+ style="opacity:1;fill:#ffffff;fill-opacity:1;stroke-width:0.413415;stop-opacity:1"
+ id="path2315"
+ d="M 33.926341,14.807412 C 34.596959,14.914846 43.329875,13.175638 45.433255,12.677163 46.175275,12.535096 45.986647,13.440152 45.24585,14.308346 43.362617,15.760055 31.332738,15.894772 33.926341,14.807412 Z" />
+ <path
+ id="path847"
+ style="vector-effect:none;fill:#ffffff;fill-opacity:1;stroke-width:2.09548;paint-order:stroke fill markers;stop-color:#000000"
+ d="M 39.369141 17.474609 A 3.4422221 3.4422221 0 0 0 35.927734 20.917969 A 3.4422221 3.4422221 0 0 0 39.369141 24.359375 A 3.4422221 3.4422221 0 0 0 42.035156 23.095703 A 2.2169242 2.2169242 0 0 1 41.234375 23.246094 A 2.2169242 2.2169242 0 0 1 39.017578 21.029297 A 2.2169242 2.2169242 0 0 1 41.234375 18.8125 A 2.2169242 2.2169242 0 0 1 42.273438 19.070312 A 3.4422221 3.4422221 0 0 0 39.369141 17.474609 z " />
+</svg>
diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/module_icon.svg b/share/extensions/other/inkman/inkman/data/pixmaps/module_icon.svg
new file mode 100644
index 0000000..ec65871
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/data/pixmaps/module_icon.svg
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<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"
+ inkscape:export-ydpi="450"
+ inkscape:export-xdpi="450"
+ inkscape:export-filename="/home/doctormo/Projects/inkscape/extension-manager-icon.png"
+ inkscape:version="1.0alpha (2b290efb96, 2019-03-26, custom)"
+ sodipodi:docname="module_icon.svg"
+ width="64"
+ height="64"
+ viewBox="0 0 64 64"
+ id="svg4197"
+ version="1.1">
+ <sodipodi:namedview
+ inkscape:current-layer="svg4197"
+ inkscape:cy="38.727324"
+ inkscape:cx="54.205688"
+ inkscape:zoom="2.5592283"
+ showgrid="false"
+ id="namedview11"
+ inkscape:window-height="480"
+ inkscape:window-width="640"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ guidetolerance="10"
+ gridtolerance="10"
+ objecttolerance="10"
+ borderopacity="1"
+ inkscape:document-rotation="0"
+ bordercolor="#666666"
+ pagecolor="#ffffff" />
+ <style
+ id="style4677" />
+ <defs
+ id="defs4199" />
+ <metadata
+ id="metadata4202">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <circle
+ style="vector-effect:none;fill:#ffffff;stroke-width:3.26454;paint-order:stroke fill markers;stop-color:#000000"
+ id="path834"
+ cx="32"
+ cy="32"
+ r="32" />
+ <g
+ style="stroke-width:0.869886"
+ transform="matrix(1.1495756,0,0,1.1495756,-3.0475334,-5.4195001)"
+ id="g242">
+ <rect
+ style="vector-effect:none;fill:#eeeeec;stroke-width:2.63021;paint-order:stroke fill markers;stop-color:#000000"
+ id="rect237"
+ width="31.052795"
+ height="32.093048"
+ x="15.564622"
+ y="16.079668" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path2995"
+ d="M 14.625549,42.099718 C 13.503629,41.895725 12.39879,41.21575 11.618065,40.248754 10.139271,38.417143 9.392752,35.363536 9.486467,31.529552 9.544868,29.14036 9.902051,27.366796 10.628668,25.858038 11.565272,23.913262 12.964687,22.75995 14.853848,22.375902 15.267645,22.291781 15.288387,22.291563 22.576421,22.294473 26.595635,22.296073 29.913564,22.286078 29.949594,22.272252 30.006771,22.25031 30.015105,22.161407 30.015105,21.573288 30.015105,21.202686 30.010613,20.895154 30.005139,20.889884 29.999649,20.884615 27.769431,20.871152 25.049086,20.859967 L 20.103004,20.839633 20.09273,18.268997 C 20.081487,15.453473 20.079227,15.486121 20.320279,14.969047 21.15591,13.176522 23.617496,12.087429 27.562008,11.765052 27.847204,11.741745 28.619033,11.71212 29.27718,11.699221 33.644211,11.613636 36.847655,12.412177 38.531531,14.006105 38.718075,14.182684 38.961181,14.446253 39.071768,14.591813 39.323225,14.922794 39.636229,15.5547 39.756079,15.973327 L 39.847435,16.292429 V 21.5975 C 39.847435,26.549469 39.842636,26.927793 39.775284,27.281505 39.688376,27.737937 39.479626,28.379249 39.305646,28.724304 38.703301,29.918941 37.593484,30.7796 36.122299,31.192977 35.167006,31.461397 35.600881,31.443762 29.27718,31.4712 22.997208,31.498447 23.376661,31.483823 22.496263,31.732635 20.786238,32.215922 19.529987,33.547819 19.019642,35.418608 18.790219,36.259608 18.795311,36.181036 18.770188,39.267775 L 18.746814,42.139694 16.832202,42.146255 C 15.386863,42.151216 14.846009,42.139811 14.625549,42.099717 Z M 25.080494,18.237304 C 25.806386,17.896282 26.243527,17.096908 26.112111,16.350848 25.990888,15.662656 25.518343,15.113424 24.877046,14.915347 23.852127,14.598782 22.782711,15.252026 22.593611,16.310165 22.439817,17.170741 22.937534,18.008531 23.77931,18.306007 23.967428,18.372489 24.088398,18.385964 24.410875,18.376368 24.762209,18.365918 24.842023,18.349337 25.080494,18.237304 Z"
+ style="opacity:1;fill:#888a85;stroke-width:0.869885;stop-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path2997"
+ style="opacity:1;fill:#d3d7cf;stroke-width:0.869885;stop-opacity:1"
+ d="M 42.380859,22.976562 42.357422,25.828125 C 42.332264,28.89593 42.34023,28.802437 42.107422,29.675781 41.79745,30.838593 41.102041,31.920288 40.261719,32.552734 39.558289,33.08215 38.810132,33.377284 37.667969,33.574219 37.473024,33.607832 35.778076,33.628381 31.691406,33.646484 L 25.988281,33.671875 25.529297,33.775391 C 23.454805,34.246931 22.127347,35.329879 21.566406,37.007812 21.258997,37.927379 21.254942,38.043388 21.269531,43.818359 L 21.28125,48.863281 21.373047,49.164062 C 22.155194,51.73786 25.228562,53.210137 30.195312,53.390625 31.156468,53.425551 32.429989,53.407933 33.328125,53.347656 35.997484,53.1685 38.021231,52.631561 39.349609,51.75 39.78695,51.459765 40.432318,50.812464 40.644531,50.451172 40.850602,50.100336 40.994463,49.698872 41.035156,49.359375 41.051976,49.219016 41.055886,48.008156 41.044922,46.669922 L 41.025391,44.236328 36.080078,44.216797 31.132812,44.197266 V 43.519531 42.841797 L 38.591797,42.820312 C 46.870993,42.796644 46.166286,42.820836 47.007812,42.535156 48.480937,42.035062 49.647445,40.959439 50.4375,39.371094 50.829249,38.583507 51.090743,37.819199 51.291016,36.878906 51.494779,35.922238 51.496534,35.894972 51.496094,32.978516 51.495632,29.981723 51.492366,29.938408 51.238281,28.763672 50.57768,25.709456 49.025839,23.68471 46.888672,23.087891 L 46.490234,22.976562 H 44.435547 Z M 36.613281,46.707031 C 36.753866,46.69394 36.89875,46.698435 37.044922,46.722656 37.810922,46.849586 38.405501,47.446414 38.535156,48.216797 38.692341,49.150769 38.010003,50.083722 37.056641,50.238281 36.914043,50.261393 36.771188,50.277784 36.738281,50.275391 35.851362,50.210736 35.170897,49.614574 35.019531,48.767578 34.837451,47.748719 35.629189,46.798672 36.613281,46.707031 Z" />
+ </g>
+</svg>
diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/not-found.png b/share/extensions/other/inkman/inkman/data/pixmaps/not-found.png
new file mode 100644
index 0000000..40d6dec
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/data/pixmaps/not-found.png
Binary files differ
diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/orphan_icon.svg b/share/extensions/other/inkman/inkman/data/pixmaps/orphan_icon.svg
new file mode 100644
index 0000000..ed05621
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/data/pixmaps/orphan_icon.svg
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ width="64"
+ height="64"
+ viewBox="0 0 16.93333316 16.93333345"
+ version="1.1"
+ id="svg8"
+ inkscape:version="1.1-dev (b07433122b, 2020-08-20, custom)"
+ sodipodi:docname="orphan_icon.svg"
+ 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/">
+ <defs
+ id="defs2" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="5.5291091"
+ inkscape:cx="28.576032"
+ inkscape:cy="40.965008"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ units="px"
+ inkscape:window-width="1534"
+ inkscape:window-height="843"
+ inkscape:window-x="66"
+ inkscape:window-y="20"
+ inkscape:window-maximized="1"
+ inkscape:snap-global="false" />
+ <metadata
+ id="metadata5">
+ <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 />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-104.6139974,-111.3056386)">
+ <g
+ aria-label="?"
+ id="text853"
+ style="font-size:7.55014px;line-height:1.25;font-family:sans-serif;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;stroke-width:0.56626">
+ <path
+ d="m 111.37404,118.63979 c 0.2567,-0.302 0.65686,-0.61911 0.98152,-0.61911 0.26425,0 0.55871,0.0679 0.55871,0.35486 0,0.41526 -1.20048,0.80786 -1.20048,1.50248 v 0.60401 h 1.40433 v -0.41526 c 0,-0.45301 1.20047,-0.69461 1.20047,-1.67613 0,-1.01927 -0.79276,-1.54778 -1.79693,-1.54778 -0.75501,0 -1.43453,0.36241 -1.96304,0.97397 z m 0.14345,2.83131 c 0,0.3926 0.36996,0.77766 0.86072,0.77766 0.55116,0 0.89846,-0.35486 0.89846,-0.77766 0,-0.43036 -0.3624,-0.80032 -0.89846,-0.80032 -0.54361,0 -0.86072,0.42281 -0.86072,0.80032 z"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:ChunkFive;-inkscape-font-specification:ChunkFive;stroke-width:0.56626"
+ id="path855" />
+ </g>
+ <rect
+ style="fill:none;fill-rule:evenodd;stroke:#d3d7cf;stroke-width:0.2645833176;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:1.5874999054,1.5874999054;stroke-dashoffset:0"
+ id="rect835"
+ width="14.84974003"
+ height="14.96549511"
+ x="105.7384796"
+ y="112.3309021" />
+ <g
+ transform="matrix(0.68391582,0,0,0.68391582,-90.169298,-291.32001)"
+ inkscape:label="00125"
+ id="zoom">
+ <path
+ inkscape:connector-curvature="0"
+ id="rect14085"
+ d="m 285,589.36218 h 24 v 24 h -24 z"
+ style="opacity:0;fill:none" />
+ <path
+ id="path14089"
+ d="m 296.4611,591.3622 c -5.2682,0 -9.5389,4.1724 -9.5389,9.299 0,5.1268 4.2707,9.26 9.5389,9.26 1.8739,0 3.6132,-0.5373 5.0874,-1.4455 L 305,612.3622 c 0.6588,0.6397 1.6958,0.6101 2.345,-0.039 l 0.3179,-0.3126 c 0.6492,-0.6492 0.6588,-1.7046 0,-2.3442 l -3.372,-3.7695 c 1.0675,-1.499 1.7091,-3.2737 1.7091,-5.2357 0,-5.1267 -4.2707,-9.2989 -9.5389,-9.2989 z m 0,2.5006 c 3.8633,0 6.9952,3.0787 6.9952,6.8766 0,3.7978 -3.1319,6.8766 -6.9952,6.8766 -3.8633,0 -6.9952,-3.0788 -6.9952,-6.8766 0,-3.7979 3.1319,-6.8766 6.9952,-6.8766 z"
+ style="opacity:1"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+</svg>
diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/star-lots.svg b/share/extensions/other/inkman/inkman/data/pixmaps/star-lots.svg
new file mode 100644
index 0000000..a73f3a9
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/data/pixmaps/star-lots.svg
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ id="svg1"
+ width="16"
+ height="16"
+ version="1.1"
+ sodipodi:docname="star-lots.svg"
+ viewBox="0 0 16 16"
+ inkscape:version="1.1-dev (7d577b7e42, 2020-12-31)"
+ 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/">
+ <metadata
+ id="metadata20">
+ <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>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1534"
+ inkscape:window-height="843"
+ id="namedview18"
+ showgrid="false"
+ inkscape:pagecheckerboard="0"
+ inkscape:zoom="11.582833"
+ inkscape:cx="-3.8418924"
+ inkscape:cy="13.856713"
+ inkscape:window-x="66"
+ inkscape:window-y="20"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg1" />
+ <defs
+ id="defs3" />
+ <g
+ id="star_angled"
+ style="display:inline;opacity:1"
+ transform="translate(-1296,-562)">
+ <rect
+ height="16"
+ id="rect11798"
+ style="display:inline;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:1.5;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ width="16"
+ x="1296"
+ y="562" />
+ <path
+ d="m 109.11231,194.24583 -3.48759,2.20705 -0.0186,4.12722 -3.17675,-2.63488 -3.930991,1.25764 1.524251,-3.83549 -2.410831,-3.34996 4.118791,0.26442 2.44101,-3.32803 1.0213,3.99891 z"
+ id="path8412"
+ inkscape:flatsided="false"
+ inkscape:randomized="0"
+ inkscape:rounded="0"
+ sodipodi:arg1="-0.122765"
+ sodipodi:arg2="0.5055535"
+ sodipodi:cx="103"
+ sodipodi:cy="195"
+ sodipodi:r1="6.158659"
+ sodipodi:r2="3"
+ sodipodi:sides="5"
+ sodipodi:type="star"
+ style="display:inline;overflow:visible;visibility:visible;fill:#babdb6;fill-opacity:1;fill-rule:evenodd;stroke:#555753;stroke-width:0.78099883;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"
+ transform="matrix(1.281336,-0.0360118,0.0342919,1.278526,1164.898,324.7687)" />
+ <path
+ d="m 108.97917,194.25051 -3.43374,2.00094 0.015,4.20347 -2.96409,-2.64736 -3.99309,1.31326 1.60183,-3.6371 -2.482907,-3.39184 3.954077,0.39951 2.45857,-3.40952 0.84192,3.884 z"
+ id="path8414"
+ inkscape:flatsided="false"
+ inkscape:randomized="0"
+ inkscape:rounded="3.469447e-18"
+ sodipodi:arg1="-0.1246996"
+ sodipodi:arg2="0.4569409"
+ sodipodi:cx="103"
+ sodipodi:cy="195"
+ sodipodi:r1="6.025959"
+ sodipodi:r2="2.8364279"
+ sodipodi:sides="5"
+ sodipodi:type="star"
+ style="display:inline;overflow:visible;visibility:visible;fill:#edd400;fill-opacity:1;fill-rule:evenodd;stroke:#c4a000;stroke-width:1.02712524;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"
+ transform="matrix(0.9659898,-0.0226454,0.0246692,0.9806753,1199.236,381.5034)" />
+ </g>
+</svg>
diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/star-none.svg b/share/extensions/other/inkman/inkman/data/pixmaps/star-none.svg
new file mode 100644
index 0000000..1b30ff0
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/data/pixmaps/star-none.svg
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ id="svg1"
+ width="16"
+ height="16"
+ version="1.1"
+ sodipodi:docname="star-none.svg"
+ viewBox="0 0 16 16"
+ inkscape:version="1.1-dev (7d577b7e42, 2020-12-31)"
+ 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/">
+ <metadata
+ id="metadata20">
+ <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>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1534"
+ inkscape:window-height="843"
+ id="namedview18"
+ showgrid="false"
+ inkscape:pagecheckerboard="0"
+ inkscape:zoom="11.582833"
+ inkscape:cx="-3.8418924"
+ inkscape:cy="13.856713"
+ inkscape:window-x="66"
+ inkscape:window-y="20"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg1" />
+ <defs
+ id="defs3" />
+ <g
+ id="star_angled"
+ style="display:inline;opacity:0.2"
+ transform="translate(-1296,-562)">
+ <rect
+ height="16"
+ id="rect11798"
+ style="display:inline;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:1.5;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ width="16"
+ x="1296"
+ y="562" />
+ <path
+ d="m 109.11231,194.24583 -3.48759,2.20705 -0.0186,4.12722 -3.17675,-2.63488 -3.930991,1.25764 1.524251,-3.83549 -2.410831,-3.34996 4.118791,0.26442 2.44101,-3.32803 1.0213,3.99891 z"
+ id="path8412"
+ inkscape:flatsided="false"
+ inkscape:randomized="0"
+ inkscape:rounded="0"
+ sodipodi:arg1="-0.122765"
+ sodipodi:arg2="0.5055535"
+ sodipodi:cx="103"
+ sodipodi:cy="195"
+ sodipodi:r1="6.158659"
+ sodipodi:r2="3"
+ sodipodi:sides="5"
+ sodipodi:type="star"
+ style="display:inline;overflow:visible;visibility:visible;fill:#babdb6;fill-opacity:1;fill-rule:evenodd;stroke:#555753;stroke-width:0.78099883;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"
+ transform="matrix(1.281336,-0.0360118,0.0342919,1.278526,1164.898,324.7687)" />
+ <path
+ d="m 108.97917,194.25051 -3.43374,2.00094 0.015,4.20347 -2.96409,-2.64736 -3.99309,1.31326 1.60183,-3.6371 -2.482907,-3.39184 3.954077,0.39951 2.45857,-3.40952 0.84192,3.884 z"
+ id="path8414"
+ inkscape:flatsided="false"
+ inkscape:randomized="0"
+ inkscape:rounded="3.469447e-18"
+ sodipodi:arg1="-0.1246996"
+ sodipodi:arg2="0.4569409"
+ sodipodi:cx="103"
+ sodipodi:cy="195"
+ sodipodi:r1="6.025959"
+ sodipodi:r2="2.8364279"
+ sodipodi:sides="5"
+ sodipodi:type="star"
+ style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#eeeeec;stroke-width:1.02712524;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"
+ transform="matrix(0.9659898,-0.0226454,0.0246692,0.9806753,1199.236,381.5034)" />
+ </g>
+</svg>
diff --git a/share/extensions/other/inkman/inkman/data/pixmaps/star-some.svg b/share/extensions/other/inkman/inkman/data/pixmaps/star-some.svg
new file mode 100644
index 0000000..da99cd7
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/data/pixmaps/star-some.svg
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ id="svg1"
+ width="16"
+ height="16"
+ version="1.1"
+ sodipodi:docname="star-some.svg"
+ viewBox="0 0 16 16"
+ inkscape:version="1.1-dev (7d577b7e42, 2020-12-31)"
+ 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/">
+ <metadata
+ id="metadata20">
+ <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>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1534"
+ inkscape:window-height="843"
+ id="namedview18"
+ showgrid="false"
+ inkscape:pagecheckerboard="0"
+ inkscape:zoom="11.582833"
+ inkscape:cx="-3.8418924"
+ inkscape:cy="13.856713"
+ inkscape:window-x="66"
+ inkscape:window-y="20"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg1" />
+ <defs
+ id="defs3" />
+ <g
+ id="star_angled"
+ style="display:inline;opacity:1"
+ transform="translate(-1296,-562)">
+ <rect
+ height="16"
+ id="rect11798"
+ style="display:inline;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:1.5;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ width="16"
+ x="1296"
+ y="562" />
+ <path
+ d="m 109.11231,194.24583 -3.48759,2.20705 -0.0186,4.12722 -3.17675,-2.63488 -3.930991,1.25764 1.524251,-3.83549 -2.410831,-3.34996 4.118791,0.26442 2.44101,-3.32803 1.0213,3.99891 z"
+ id="path8412"
+ inkscape:flatsided="false"
+ inkscape:randomized="0"
+ inkscape:rounded="0"
+ sodipodi:arg1="-0.122765"
+ sodipodi:arg2="0.5055535"
+ sodipodi:cx="103"
+ sodipodi:cy="195"
+ sodipodi:r1="6.158659"
+ sodipodi:r2="3"
+ sodipodi:sides="5"
+ sodipodi:type="star"
+ style="display:inline;overflow:visible;visibility:visible;fill:#babdb6;fill-opacity:1;fill-rule:evenodd;stroke:#555753;stroke-width:0.78099883;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"
+ transform="matrix(1.281336,-0.0360118,0.0342919,1.278526,1164.898,324.7687)" />
+ <path
+ d="m 108.97917,194.25051 -3.43374,2.00094 0.015,4.20347 -2.96409,-2.64736 -3.99309,1.31326 1.60183,-3.6371 -2.482907,-3.39184 3.954077,0.39951 2.45857,-3.40952 0.84192,3.884 z"
+ id="path8414"
+ inkscape:flatsided="false"
+ inkscape:randomized="0"
+ inkscape:rounded="3.469447e-18"
+ sodipodi:arg1="-0.1246996"
+ sodipodi:arg2="0.4569409"
+ sodipodi:cx="103"
+ sodipodi:cy="195"
+ sodipodi:r1="6.025959"
+ sodipodi:r2="2.8364279"
+ sodipodi:sides="5"
+ sodipodi:type="star"
+ style="display:inline;overflow:visible;visibility:visible;fill:#edd400;fill-opacity:1;fill-rule:evenodd;stroke:#eeeeec;stroke-width:1.02712524;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"
+ transform="matrix(0.9659898,-0.0226454,0.0246692,0.9806753,1199.236,381.5034)" />
+ </g>
+</svg>
diff --git a/share/extensions/other/inkman/inkman/factory.py b/share/extensions/other/inkman/inkman/factory.py
new file mode 100644
index 0000000..51aa77a
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/factory.py
@@ -0,0 +1,199 @@
+#
+# Copyright 2020 Martin Owens <doctormo@gmail.com>
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>
+#
+"""
+Extract information from an inx file and follow all the files.
+"""
+
+import os
+import sys
+
+from datetime import datetime
+from modulefinder import ModuleFinder
+from collections import defaultdict
+
+from inkex.inx import InxFile
+
+from inkman import __pkgname__, __version__
+from inkman.utils import DATA_DIR
+
+MODULES = (
+ (
+ "Depricated",
+ "Using depricated modules {names}",
+ "Critical",
+ (
+ "bezmisc",
+ "cubicsuperpath",
+ "simplestyle",
+ "cspsubdiv",
+ "ffgeom",
+ "simplepath",
+ "simpletransform",
+ ),
+ ),
+ ("Unusual", "Unusual modules being used {names}", "Warning", ("argparse",)),
+ ("Ignored", None, None, ("os", "sys", "lxml")),
+)
+
+
+class PackageInxFile(InxFile):
+ def __init__(self, filename):
+ super().__init__(filename)
+ self.inx_file = filename
+
+ def get_file_root(self):
+ return os.path.dirname(self.inx_file)
+
+ def get_script(self):
+ """Return the file the INX points to"""
+ if self.script.get("location", None) in ("inx", None):
+ return os.path.join(self.get_file_root(), self.script["script"])
+ raise IOError("Can't find script filename")
+
+
+class IncludeFile(object):
+ """A file to include in the package"""
+
+ def __init__(self, root, filepath, target=None):
+ self.root = root
+ self.filepath = filepath
+ self.name = os.path.basename(filepath)
+ self.target = target or os.path.dirname(filepath)
+
+ def __repr__(self):
+ return f"<File name='{self.name}'>"
+
+ def file_icon(self):
+ """Return a filename type"""
+ ext = self.filepath.rsplit(".", 1)[-1]
+ if ext in ("inx", "py", "txt", "svg", "png"):
+ return ext
+ return "default"
+
+ def detect_deps(self, modules=False):
+ if not self.filepath.endswith(".py"):
+ return [], []
+ # We want to find all modules imported by the script directly
+ # So we set the location to nowhere and collect the badmodules
+ finder = ModuleFinder("never-land")
+ finder.run_script(self.filepath)
+ # TODO: split out local modules, system modules and genuine deps
+
+ deps, mods = [], []
+ for key, locs in finder.badmodules.items():
+ if "__main__" not in locs:
+ continue
+ try:
+ mod_path = finder.find_module("inkman", path=sys.path)[1]
+ if "/python" in mod_path:
+ if "site-packages" in mod_path:
+ deps.append(key.split(".")[0])
+ elif mod_path.startswith(self.root):
+ mods.append(mod_path)
+ except ImportError:
+ continue
+ return mods, deps
+
+
+class GeneratePackage(object):
+ """A generated package based on data"""
+
+ def __init__(self, inx_files, template=os.path.join(DATA_DIR, "setup.template")):
+ with open(template, "r") as fhl:
+ self._template = fhl.read()
+ self.files = []
+ self.requires = set()
+ self.warnings = defaultdict(list)
+ self.name = ""
+ self.ident = ""
+
+ for x, inx_file in enumerate(inx_files):
+ try:
+ inx = PackageInxFile(inx_file)
+ except Exception as err:
+ self.add_warning(f"Can't add file {inx_file}: {err}", 5)
+ continue
+ self._add_file(inx.get_file_root(), inx.inx_file)
+ self._add_file(inx.get_file_root(), inx.get_script())
+ if not x:
+ self.name = inx.name or ""
+ self.ident = inx.ident.replace(".", "-")
+
+ def _add_file(self, root, fname):
+ included = IncludeFile(root, fname)
+ self.files.append(included)
+ (mods, deps) = included.detect_deps()
+ for dep in deps:
+ self._add_dep(dep)
+ for fname in mods:
+ self._add_file(root, fname)
+ print(f"DEP: {self.requires}")
+
+ def _add_dep(self, name):
+ """Try and find the package associated with this name"""
+ for (list_name, warning, level, mod_list) in MODULES:
+ if name in mod_list:
+ self.warnings[list_name].append(name)
+ return
+ self.requires.add(name)
+
+ def generate_setup(self, target):
+ """Generates a setup.py file contents"""
+ args = {
+ "__pkgname__": __pkgname__,
+ "__version__": __version__,
+ "year": datetime.now().year,
+ "readme": self.generate_readme(target),
+ "ident": self.generate_ident(),
+ "version": self.generate_version(),
+ "description": self.widget("entry_name").get_text(),
+ "author": self.widget("entry_author").get_text(),
+ "author_email": self.widget("entry_email").get_text(),
+ "url": self.widget("entry_url").get_text(),
+ "license": self.widget("licenses").get_active_id(),
+ "datafiles": self.generate_datafiles(),
+ "requires": self.generate_requires(),
+ "classifiers": "", # TODO
+ }
+ return self_template.format(**args)
+
+ def generate_ident(self):
+ """Generate the ident from the text entry"""
+ ident = self.widget("entry_ident").get_text()
+ ident = ident.replace(" ", "-").lower()
+ self.widget("entry_ident").set_text(ident)
+ return "inx-" + ident
+
+ def generate_datafiles(self):
+ """Generate a list of datafile and their install location"""
+ result = ""
+ template = " ('{target}', ['{file}']),\n"
+ # 2. Loop through all the file objects in the list
+ # 3. Add them to the final result
+ return result.strip()
+
+ def generate_requires(self):
+ """Generate a list of required modules"""
+ # TODO: Version keeping
+ result = ""
+ # 1. Loop through all the dep objects in the list
+ # 2. Append them to the result
+ return result
+
+
+if __name__ == "__main__":
+ gen = GeneratePackage(sys.argv[1:])
diff --git a/share/extensions/other/inkman/inkman/gui/__init__.py b/share/extensions/other/inkman/inkman/gui/__init__.py
new file mode 100644
index 0000000..042956e
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/gui/__init__.py
@@ -0,0 +1,32 @@
+#
+# Copyright 2018-2022 Martin Owens <doctormo@gmail.com>
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>
+#
+"""All graphical interfaces bound into a GtkApp"""
+
+import os
+
+from inkex.gui import GtkApp
+
+from .main import ExtensionManagerWindow
+from .info import MoreInformation
+
+
+class ManagerApp(GtkApp):
+ """Load the inkscape extensions glade file and attach to window"""
+
+ ui_dir = os.path.join(os.path.dirname(__file__), "..", "data")
+ app_name = "inkscape-extensions-manager"
+ windows = [ExtensionManagerWindow, MoreInformation]
diff --git a/share/extensions/other/inkman/inkman/gui/info.py b/share/extensions/other/inkman/inkman/gui/info.py
new file mode 100644
index 0000000..5e17923
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/gui/info.py
@@ -0,0 +1,105 @@
+#
+# Copyright 2018-2022 Martin Owens <doctormo@gmail.com>
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>
+#
+"""Information about a package"""
+
+import os
+import sys
+
+from inkex.gui import ChildWindow, TreeView
+
+
+class ExtensionTreeItem(object):
+ """Shows the name of the item in the extensions tree"""
+
+ def __init__(self, name, kind="debug", parent=None):
+ self.kind = kind
+ self.name = str(name)
+
+
+class ExtensionTreeView(TreeView):
+ """A list of extensions (inx file based)"""
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.parents = {}
+ self.menus = {}
+
+ def setup(self, *args, **kwargs):
+ self.ViewColumn("Name", expand=True, text="name")
+ self.ViewSort(data=lambda item: item.name, ascending=True)
+
+ def get_menu(self, parent, *remain):
+ menu_id = "::".join([str(r) for r in remain])
+ if menu_id in self.menus:
+ return self.menus[menu_id]
+
+ if remain[:-1]:
+ parent = self.get_menu(parent, *remain[:-1])
+
+ menu = self._add_item([ExtensionTreeItem(remain[-1])], parent=parent)
+ self.menus[menu_id] = menu
+ return menu
+
+ def add_item(self, item, parent=None):
+ if not item or not item.name:
+ return None
+ if item.kind not in self.parents:
+ tree_item = ExtensionTreeItem(item.kind.title())
+ self.parents[item.kind] = self._add_item([tree_item], parent=None)
+ parent = self.parents[item.kind]
+ if item.kind == "effect" and len(item.menu) > 1:
+ parent = self.get_menu(parent, *item.menu[:-1])
+ return self._add_item([item], parent)
+
+
+class MoreInformation(ChildWindow):
+ """Show further information for an installed package"""
+
+ name = "info"
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.inx = ExtensionTreeView(self.widget("inx"), selected=self.select_inx)
+
+ def load_widgets(self, pixmaps, item):
+ """Initialise the information"""
+ try:
+ self.widget("info_website").show()
+ self.widget("info_website").set_uri(item.link)
+ self.widget("info_website").set_label(item.link)
+ except Exception:
+ self.widget("info_website").hide()
+
+ self.pixmaps = pixmaps
+ self.window.set_title(item.name)
+ self.widget("info_name").set_label(item.name)
+ self.widget("info_desc").set_label(item.summary)
+ self.widget("info_version").set_label(item.version)
+ self.widget("info_license").set_label(item.license)
+ self.widget("info_author").set_label(f"{item.author}")
+ try:
+ self.widget("info_image").set_from_pixbuf(pixmaps.get(item.get_icon()))
+ except Exception:
+ pass
+
+ self.inx.clear()
+ if hasattr(item, "get_files"):
+ for fn in item.get_files(filters=("*.inx",)):
+ self.inx.add([ExtensionTreeItem(fn, kind="lost-and-found")])
+
+ def select_inx(self, item):
+ pass
diff --git a/share/extensions/other/inkman/inkman/gui/main.py b/share/extensions/other/inkman/inkman/gui/main.py
new file mode 100644
index 0000000..9ff8065
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/gui/main.py
@@ -0,0 +1,371 @@
+#
+# Copyright 2018 Martin Owens <doctormo@gmail.com>
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>
+#
+"""Gtk 3+ Inkscape 1.0 Extensions Manager GUI."""
+
+import os
+import sys
+import webbrowser
+
+from inkex.gui import Window, ChildWindow, TreeView, asyncme
+from inkex.gui.pixmap import PixmapManager
+from inkex.gui.app import Gtk
+
+from ..utils import DATA_DIR, INKSCAPE_PROFILE
+from ..remote import RemoteArchive, SearchError
+from .. import __state__
+
+
+def tag(name, color="#EFEFEF", fgcolor="#333333"):
+ return f"<span size='small' font_family='monospace' style='italic' background='{color}' foreground='{fgcolor}'> {name} </span> "
+
+
+class LocalTreeView(TreeView):
+ """A List of locally installed packages"""
+
+ def __init__(self, target, widget, *args, **kwargs):
+ self._target = target
+ self._pixmaps = kwargs["pixmaps"]
+ self._version = kwargs.pop("version", None)
+
+ style = widget.get_style_context()
+ self._fg_color = style.get_color(Gtk.StateFlags.NORMAL)
+ # self._bg_color = style.get_property('background-color', Gtk.StateFlags.NORMAL)
+
+ super().__init__(widget, *args, **kwargs)
+
+ def get_name(self, item):
+ # color = self._style.get_property('color', Gtk.StateFlags.NORMAL)
+ return f"<big><b>{item.name}</b></big>\n<i>{item.summary}</i>"
+
+ def get_icon(self, item):
+ try:
+ return self._pixmaps.get(item.get_icon(), "")
+ except Exception:
+ return ""
+
+ def setup(self, *args, **kwargs):
+ """Setup the treeview with one or many columns manually"""
+
+ col = self.create_column("Extensions Package", expand=True)
+
+ img = col.add_image_renderer(self.get_icon, pad=0, pixmaps=self._pixmaps)
+ img.set_property("ypad", 2)
+
+ txt = col.add_text_renderer(self.get_name)
+ txt.set_property("foreground-rgba", self._fg_color)
+ # This is detected as black for remote treeview, we're not sure why
+ # txt.set_property("background-rgba", self._bg_color)
+ txt.set_property("xpad", 8)
+
+ col = self.create_column("Version", expand=False)
+ txt = col.add_text_renderer("version", template=f"<i>{0}</i>")
+ txt.set_property("foreground-rgba", self._fg_color)
+
+ col = self.create_column("Author", expand=False)
+ txt = col.add_text_renderer("author")
+ txt.set_property("foreground-rgba", self._fg_color)
+
+ if self._target.version_specific:
+ col = self.create_column("Inkscape", expand=False)
+ txt = col.add_text_renderer("target")
+ txt.set_property("foreground-rgba", self._fg_color)
+
+ self.create_sort(data=lambda item: item.name, ascending=True, contains="name")
+
+ super().setup(*args, **kwargs)
+
+
+class RemoteTreeView(LocalTreeView):
+ """A List of remote packages for installation"""
+
+ def get_installed(self, item):
+ if item.installed is None:
+ item.set_installed(False)
+ for installed_item in self._target.list_installed():
+ if item.ident == installed_item.ident:
+ item.set_installed(True)
+ return bool(item.installed)
+
+ def setup(self, *args, **kwargs):
+ def get_star(item):
+ star = "star-none.svg"
+ if item.stars > 10:
+ star = "star-lots.svg"
+ elif item.stars > 1:
+ star = "star-some.svg"
+ return self._pixmaps.get(star)
+
+ def get_sort(item):
+ if not item.verified:
+ return -100 + item.stars
+ if self._version not in item.targets:
+ return -20 + item.stars
+ return item.stars + (1000 * int(item.recommended))
+
+ super().setup(*args, **kwargs)
+
+ col = self.create_column("Stars", expand=True)
+ img = col.add_image_renderer(get_star, pad=0, size=16, pixmaps=self._pixmaps)
+ img.set_property("ypad", 2)
+ txt = col.add_text_renderer("stars")
+ txt.set_property("foreground-rgba", self._fg_color)
+
+ self.create_sort(data=get_sort, ascending=True)
+
+ def get_name(self, item):
+ summary = item.summary
+ if self.get_installed(item):
+ summary = tag("Installed", "#37943e", "white") + summary.strip()
+ elif not item.verified:
+ summary = tag("Unverified", "#CB0000", "white") + summary.strip()
+ elif self._version not in item.targets:
+ targets = item.targets or ["No Inkscape Versions"]
+ summary = (
+ "".join([tag(t, "#00CB00", "white") for t in targets]) + summary.strip()
+ )
+ else:
+ summary = (
+ tag("Verified", "#37943e", "white")
+ + tag(self._version, "#37943e", "white")
+ + summary.strip()
+ )
+
+ return f"<big><b>{item.name}</b></big>\n<i>{summary}</i>\n" + "".join(
+ tag(t) for t in item.tags
+ )
+
+
+class LocalPixmaps(PixmapManager):
+ """Load local pictures"""
+
+ pixmap_dir = DATA_DIR
+
+
+class ExtensionManagerWindow(Window):
+ name = "gui"
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.target = self.gapp.kwargs["target"]
+ self._version = self.gapp.kwargs["version"]
+
+ self.pixmaps = LocalPixmaps("pixmaps", size=48, load_size=(96, 96))
+ self.searching = self.widget("dl-searching")
+ self.searchbox = self.searching.get_parent()
+ self.searchbox.remove(self.searching)
+
+ self.local = LocalTreeView(
+ self.target,
+ self.widget("local_extensions"),
+ version=self._version,
+ pixmaps=self.pixmaps,
+ selected=self.select_local,
+ )
+
+ self.remote = RemoteTreeView(
+ self.target,
+ self.widget("remote_extensions"),
+ version=self._version,
+ pixmaps=self.pixmaps,
+ selected=self.select_remote,
+ )
+
+ self.widget("loading").start()
+ self.window.show_all()
+ self.window.present()
+ # self.window.set_keep_above(True)
+
+ self.refresh_local()
+ self.widget("remote_install").set_sensitive(False)
+ self.widget("remote_info").set_sensitive(False)
+ self.widget("local_install").set_sensitive(True)
+ self.window.set_title(self.target.label + f" ({self._version}) - {__state__}")
+
+ if not self.target.is_search:
+ self.widget("remote_getlist").show()
+ self.widget("dl-search").hide()
+ else:
+ self.widget("dl-search").show()
+ self.widget("remote_getlist").hide()
+ self.widget("no_results").hide()
+
+ # Get a tasting of items from the server
+ self._remote_search(None)
+
+ def remote_getlist(self, widget):
+ self._remote_search("")
+
+ @asyncme.run_or_none
+ def refresh_local(self):
+ """Searches for locally installed extensions and adds them"""
+ self.local.clear()
+ self.widget("local_uninstall").set_sensitive(False)
+ self.widget("local_information").set_sensitive(False)
+
+ all_packages = []
+ for item in self.target.list_installed(cached=False):
+ self.local.add_item(item)
+ self.widget("loading").stop()
+
+ def select_local(self, item):
+ """Select an installed extension"""
+ self.widget("local_uninstall").set_sensitive(item.is_uninstallable())
+ self.widget("local_information").set_sensitive(bool(item))
+
+ def local_information(self, widget):
+ """Show the more information window"""
+ if self.local.selected:
+ self.load_window("info", pixmaps=self.pixmaps, item=self.local.selected)
+
+ def local_uninstall(self, widget):
+ """Uninstall selected extection package"""
+ item = self.local.selected
+ if item.is_uninstallable():
+ if item.uninstall():
+ self.local.remove_item(item)
+ self.remote.refresh()
+
+ def change_remote_all(self, widget, unk):
+ """When the source switch button is clicked"""
+ self.remote_search(self.widget("dl-search"))
+
+ def remote_search(self, widget):
+ """Remote search activation"""
+ query = widget.get_text()
+ if len(query) > 2:
+ self._remote_search(query)
+
+ def _remote_search(self, query):
+ filtered = False # self.widget('remote_target').get_active()
+ self.remote.clear()
+ self.widget("no_results").hide()
+ self.widget("results_found").show()
+ self.widget("remote_install").set_sensitive(False)
+ self.widget("remote_info").set_sensitive(False)
+ self.widget("dl-search").set_sensitive(False)
+ self.searchbox.add(self.searching)
+ self.widget("dl-searching").start()
+ self.async_search(query, filtered)
+
+ def remote_info(self, widget):
+ """Show the remote information"""
+ if self.remote.selected and self.remote.selected.link:
+ webbrowser.open(self.remote.selected.link)
+
+ @asyncme.run_or_none
+ def async_search(self, query, filtered):
+ """Asyncronous searching in PyPI"""
+ try:
+ for package in self.target.search(query, filtered):
+ self.add_search_result(package)
+ except SearchError as err:
+ # Ignore taster request
+ if query is not None:
+ self.dialog(str(err))
+ self.search_finished()
+
+ @asyncme.mainloop_only
+ def add_search_result(self, package):
+ """Adding things to Gtk must be done in mainloop"""
+ self.remote.add_item(package)
+
+ @asyncme.mainloop_only
+ def search_finished(self):
+ """After everything, finish the search"""
+ self.searchbox.remove(self.searching)
+ self.widget("dl-search").set_sensitive(True)
+ self.replace(self.searching, self.remote._list)
+ if not self.remote._model.iter_n_children():
+ self.widget("no_results").show()
+ self.widget("results_found").hide()
+
+ def select_remote(self, item):
+ """Select an installed extension"""
+ # Do we have a place to install packages to?
+ active = (
+ self.remote.selected
+ and self.remote.selected.is_installable(self._version)
+ and not self.remote.selected.installed
+ )
+ self.widget("remote_install").set_sensitive(active)
+ if self.remote.selected.link:
+ self.widget("remote_info").set_sensitive(True)
+
+ def remote_install(self, widget):
+ """Install a remote package"""
+ self.widget("remote_install").set_sensitive(False)
+ item = self.remote.selected
+ try:
+ item.install()
+ except Exception as err:
+ self.dialog(str(err))
+ return
+ self.remote.refresh()
+ self.refresh_local()
+ self.widget("main_notebook").set_current_page(0)
+
+ def local_install(self, widget):
+ """Install from a local filename"""
+ dialog = Gtk.FileChooserDialog(
+ title="Please choose a package file",
+ transient_for=self.window,
+ action=Gtk.FileChooserAction.OPEN,
+ )
+
+ dialog.add_buttons(
+ Gtk.STOCK_CANCEL,
+ Gtk.ResponseType.CANCEL,
+ Gtk.STOCK_OPEN,
+ Gtk.ResponseType.OK,
+ )
+
+ filter_py = Gtk.FileFilter()
+ filter_py.set_name("Packages")
+ filter_py.add_mime_type("application/x-compressed-tar")
+ filter_py.add_mime_type("application/zip")
+ dialog.add_filter(filter_py)
+
+ filter_text = Gtk.FileFilter()
+ filter_text.set_name("Python Wheel")
+ filter_text.add_mime_type("application/zip")
+ filter_text.add_pattern("*.whl")
+ dialog.add_filter(filter_text)
+
+ filter_any = Gtk.FileFilter()
+ filter_any.set_name("Any files")
+ filter_any.add_pattern("*")
+ dialog.add_filter(filter_any)
+
+ response = dialog.run()
+ if response == Gtk.ResponseType.OK:
+ self.target._install(dialog.get_filename(), {})
+ self.refresh_local()
+
+ dialog.destroy()
+
+ def update_all(self, widget=None):
+ """Update the extensions manager, and everything else"""
+ pass
+
+ def dialog(self, msg):
+ self.widget("dialog_msg").set_label(msg)
+ self.widget("dialog").set_transient_for(self.window)
+ self.widget("dialog").show_all()
+
+ def close_dialog(self, widget):
+ self.widget("dialog_msg").set_label("")
+ self.widget("dialog").hide()
diff --git a/share/extensions/other/inkman/inkman/package.py b/share/extensions/other/inkman/inkman/package.py
new file mode 100644
index 0000000..a19127e
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/package.py
@@ -0,0 +1,330 @@
+#
+# Copyright (C) 2019 Martin Owens
+#
+# 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.
+#
+"""
+Support for constructing and understanding installed extensions
+as python packages.
+
+Start by using 'PackageLists' and iterate over to get 'PackageList' objects
+iterate over those to get 'Package' objects and use those to know more
+information about the installed packages.
+"""
+
+import os
+import sys
+import json
+import logging
+from fnmatch import fnmatch
+
+from .utils import (
+ DATA_DIR,
+ ICON_SEP,
+ parse_metadata,
+ clean_author,
+ get_user_directory,
+ get_inkscape_directory,
+ ExtensionInx,
+)
+
+# The ORDER of these places is important, when installing packages it will
+# choose the FIRST writable directory in the lsit, so make sure that the
+# more preferable locations appear at the top.
+EXTENSION_PLACES = []
+
+for path in sys.path:
+ if "extensions" in path:
+ if "/bin" in path:
+ path = path.replace("/bin", "")
+ EXTENSION_PLACES.append(path)
+
+CORE_ICON = os.path.join(DATA_DIR, "pixmaps", "core_icon.svg")
+ORPHAN_ICON = os.path.join(DATA_DIR, "pixmaps", "orphan_icon.svg")
+DEFAULT_ICON = os.path.join(DATA_DIR, "pixmaps", "default_icon.svg")
+MODULE_ICON = os.path.join(DATA_DIR, "pixmaps", "module_icon.svg")
+
+
+class PackageItem(object):
+ """
+ Gets information about the package using requests.
+
+ Can be remote, or local json file.
+ """
+
+ default_icon = DEFAULT_ICON
+
+ @classmethod
+ def is_pkg(cls, info):
+ """Returns true if this info package is considered a managed package"""
+ for field in ("name", "author", "verified", "links", "summary"):
+ if field not in info:
+ return False
+ return True
+
+ def __init__(self, info, remote=None):
+ if not self.is_pkg(info):
+ raise ValueError("Not a valid package, refusing to create it.")
+
+ self.info = info
+ self.remote = remote
+ self.installed = None
+ self._installer = None
+ self._uninstaller = None
+ self._missing = []
+ self._icon = None
+
+ ident = property(lambda self: self.info.get("id"))
+ url = property(lambda self: self.info["links"]["file"])
+ link = property(lambda self: self.info["links"]["html"])
+ name = property(lambda self: self.info["name"] or "Unnamed")
+ license = property(lambda self: self.info.get("license") or "")
+ author = property(lambda self: self.info["author"])
+ tags = property(lambda self: self.info.get("tags", []))
+
+ stars = property(lambda self: self.info["stats"]["liked"])
+ downloads = property(lambda self: self.info["stats"]["downloaded"])
+ verified = property(lambda self: self.info["verified"])
+ recommended = property(lambda self: self.info["stats"].get("extra", 0) == 7)
+
+ targets = property(lambda self: self.info.get("Inkscape Version", []))
+ target = property(lambda self: ", ".join(self.targets))
+
+ @property
+ def summary(self):
+ ret = self.info["summary"] or "No summary"
+ if len(ret) > 110:
+ ret = ret.split(". ", 1)[0]
+ if len(ret) > 110:
+ ret = ret[:110].rsplit(" ", 1)[0] + "..."
+ return ret
+
+ @property
+ def version(self):
+ if "version" in self.info:
+ return str(self.info["version"])
+ if "stats" in self.info and "revisions" in self.info["stats"]:
+ return str(int(self.info["stats"]["revisions"]) + 1)
+ return "?"
+
+ def set_installer(self, fn):
+ self._installer = fn
+
+ def set_uninstaller(self, fn, *args):
+ def _inner(info):
+ return fn(info, *args)
+
+ self._uninstaller = _inner
+
+ def set_installed(self, installed=True):
+ self.installed = installed
+
+ def is_installable(self, version):
+ if version not in self.targets or not self.verified:
+ return False
+ return bool(not self.installed and self._installer)
+
+ def is_uninstallable(self):
+ return bool(self._uninstaller)
+
+ def install(self):
+ """Install the remote package"""
+ if not self.remote:
+ raise IOError("Can not install without a defined remote")
+ url = self.remote(self.info["links"]["file"])
+ msg = self._installer(url.as_local_file(), self.info)
+ self.set_installed(True)
+ return msg
+
+ def uninstall(self):
+ """Remove the pakage if possible"""
+ if self._uninstaller(self.info):
+ self.set_installed(False)
+ return True
+ return False
+
+ def get_icon(self):
+ if self._icon:
+ return self._icon
+ if self.info.get("icon"):
+ if not self.remote:
+ raise IOError("Can get icon without a defined remote")
+ icon = self.remote(self.info["icon"])
+ self._icon = icon.as_local_file() or self.default_icon
+ return self._icon
+ for filename in self.get_files():
+ name = os.path.basename(filename)
+ if name in ("icon.svg", "icon.png"):
+ self._icon = os.path.abspath(filename)
+ return filename
+ return self.default_icon
+
+ def get_files(self, missing=False):
+ """List files"""
+ return [
+ name
+ for name in self.info.get("files", [])
+ if missing or name not in self._missing
+ ]
+
+
+class OrphanedItem(PackageItem):
+ """
+ A special kind of item to collect all orphaned files
+ """
+
+ default_icon = ORPHAN_ICON
+
+ def __init__(self, parent):
+ super().__init__(
+ {
+ "name": "Orphan Extensions",
+ "author": "Various",
+ "verified": False,
+ "summary": "Old and manually installed extensions",
+ "license": "Unknown",
+ "links": {},
+ "version": "-",
+ "stats": {"liked": -1, "downloaded": -1},
+ }
+ )
+
+ self._icon = self.default_icon
+ self._parent = os.path.abspath(parent)
+ self._files = set()
+ self._removed = set()
+ self._items = {}
+
+ def _get_target_file(self, filename):
+ if not os.path.isabs(filename):
+ filename = os.path.join(self._parent, filename)
+ path = os.path.abspath(filename)
+ return path.replace(self._parent, "").lstrip("/")
+
+ def add_file(self, filename):
+ """Add a file to the 'this file exists' list"""
+ self._files.add(self._get_target_file(filename))
+
+ def remove_file(self, filename, item=None):
+ """Add a file to the 'this file is said to exist' list"""
+ fn = self._get_target_file(filename)
+ self._removed.add(fn)
+ if item is not None:
+ self._items[fn] = item
+
+ def get_files(self, filters=()):
+ """Returns a filtered set of files which exist, minus ones said to exist"""
+ if not filters:
+ filters = ("*",)
+ items = []
+ for item in self._files - self._removed:
+ if any([fnmatch(item, filt) for filt in filters]):
+ items.append(item)
+ return items
+
+ def get_missing(self):
+ """Returns a set of files which don't exist, even though they were said to"""
+ return [(fn, self._items.get(fn, None)) for fn in self._removed - self._files]
+
+
+class PythonItem(PackageItem):
+ """
+ A python package that has an inx file, but was never installed properly.
+ """
+
+ def __init__(self, pip):
+ self.pip = pip
+ info = self.pip.get_metadata()
+ super().__init__(
+ {
+ "pip": True,
+ "name": info["name"],
+ "summary": info["summary"],
+ "author": info["author"] or "Unknown",
+ "version": info["version"],
+ "license": info["license"],
+ "verified": False,
+ "links": {},
+ "stats": {"liked": -1, "downloaded": -1},
+ }
+ )
+
+ def get_files(self):
+ return self.pip.package_files()
+
+
+class PythonPackage(object):
+ """
+ A reprisentation of the python package, NOT the json based packages.
+ """
+
+ name = property(lambda self: self.get_metadata()["name"])
+ version = property(lambda self: self.get_metadata()["version"])
+
+ def __init__(self, path, parent):
+ self._metadata = None
+ self.path = path
+ self.parent = parent
+
+ def get_inx(self):
+ """Yields all of the inx files in this package"""
+ for filename in self.package_files():
+ if filename.endswith(".inx"):
+ yield filename
+
+ def package_files(self):
+ """Return a generator of all files in this installed package"""
+ parent = os.path.abspath(os.path.dirname(self.path))
+ record = self.get_file("RECORD")
+ if not record:
+ return
+ for line in record.split("\n"):
+ if line and "," in line:
+ (filename, checksum, size) = line.rsplit(",", 2)
+ # XXX Check filesize or checksum?
+ if not os.path.isabs(filename):
+ filename = os.path.join(parent, filename)
+ yield filename
+
+ def get_metadata(self):
+ """Returns the metadata from an array of known types"""
+ if self._metadata is None:
+ for name in ("METADATA", "PKG-INFO"):
+ md_mail = self.get_file(name)
+ if md_mail:
+ self._metadata = parse_metadata(md_mail)
+
+ if self._metadata is None:
+ md_json = self.get_file("metadata.json")
+ if md_json:
+ self._metadata = clean_author(json.loads(md_json))
+
+ if self._metadata is None:
+ raise KeyError("Can't find package meta data: {}".format(self.path))
+ return self._metadata
+
+ def get_file(self, name):
+ """Get filename if it exists"""
+ if not self.path or not os.path.isdir(self.path):
+ return None
+ path = os.path.join(self.path, name)
+ if os.path.isfile(path):
+ with open(path, "r") as fhl:
+ return fhl.read()
+ return None
+
+ def get_depedencies(self):
+ """Return a list of other pip packages this packages needs"""
+ return self.get_metadata()["requires"]
diff --git a/share/extensions/other/inkman/inkman/remote.py b/share/extensions/other/inkman/inkman/remote.py
new file mode 100644
index 0000000..c2c4b54
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/remote.py
@@ -0,0 +1,153 @@
+#
+# Copyright (C) 2019-2021 Martin Owens
+#
+# 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.
+#
+"""
+Searching for external packages and getting meta data about them.
+"""
+
+import re
+import os
+import json
+import logging
+import requests
+
+try:
+ from cachecontrol import CacheControl, CacheControlAdapter
+ from cachecontrol.caches.file_cache import FileCache
+ from cachecontrol.heuristics import ExpiresAfter
+except (ImportError, ModuleNotFoundError):
+ CacheControl = None
+
+from inkex.command import CommandNotFound, ProgramRunError, call
+from collections import defaultdict
+
+from .utils import INKSCAPE_VERSION, CACHE_DIR
+from .package import DEFAULT_ICON, PackageItem
+
+PYTHON_VERSION = "py3"
+
+class SearchError(IOError):
+ pass
+
+class LocalFile(object):
+ """Same API as RemoteFile, but for locals"""
+
+ def __init__(self, basedir, url):
+ self.basedir = basedir
+ self.url = url
+
+ def __str__(self):
+ return self.url
+
+ def filename(self):
+ return self.url.split("/")[-1]
+
+ def filepath(self):
+ return os.path.join(self.basedir, self.url)
+
+ def as_local_file(self):
+ filename = self.filepath()
+ if os.path.isfile(filename):
+ return filename
+ raise IOError(f"Can't find file: {filename}")
+
+
+class RemoteFile(object):
+ """A remote file, icon, zip etc"""
+
+ def __init__(self, session, url):
+ self.session = session
+ self.url = url
+
+ def __str__(self):
+ return self.url
+
+ def get(self):
+ return self.session.get(self.url)
+
+ def filename(self):
+ return self.url.split("/")[-1]
+
+ def filepath(self):
+ return os.path.join(CACHE_DIR, self.filename())
+
+ def as_local_file(self):
+ if self.url:
+ remote = self.get()
+ if remote and remote.status_code == 200:
+ with open(self.filepath(), "wb") as fhl:
+ fhl.write(remote.content)
+ return self.filepath()
+ return None
+
+
+class RemoteArchive(object):
+ """The remote archive used to be PyPI but is now inkscape's own website."""
+
+ URL = "https://inkscape.org/gallery/={category}/json/"
+
+ def __init__(self, category, version=INKSCAPE_VERSION):
+ self.version = version
+ self.url = self.URL.format(category=category)
+ self.session = requests.session()
+ if CacheControl is not None:
+ self.session.mount(
+ "https://",
+ CacheControlAdapter(
+ cache=FileCache(CACHE_DIR),
+ heuristic=ExpiresAfter(days=1),
+ ),
+ )
+
+ def _remote_file(self, url):
+ return RemoteFile(self.session, url)
+
+ def search(self, query, filtered=True):
+ """Search for extension packages"""
+ for info in self._search(query):
+ item = PackageItem(info, remote=self._remote_file)
+ if not filtered or not self.version or self.version in item.targets:
+ yield item
+
+ def _search(self, query, tags=[]):
+ """Search for the given query and yield each item, will raise if any other response"""
+ response = None
+
+ if query is None:
+ try:
+ response = self.session.get(
+ self.url,
+ params={
+ "tags": tags,
+ "checked": 1,
+ "limit": 10,
+ "order": "extra_status",
+ },
+ )
+ except requests.exceptions.RequestException as err:
+ raise SearchError(str(err))
+ except ConnectionError as err:
+ raise SearchError(str(err))
+ except requests.exceptions.RequestsWarning:
+ pass
+ else:
+ response = self.session.get(
+ self.url, params={"q": query, "tags": tags, "checked": 1}
+ )
+ if response is not None:
+ for item in response.json()["items"]:
+ yield item
diff --git a/share/extensions/other/inkman/inkman/target.py b/share/extensions/other/inkman/inkman/target.py
new file mode 100644
index 0000000..dff1211
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/target.py
@@ -0,0 +1,375 @@
+#
+# Copyright (C) 2019 Martin Owens
+#
+# 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.
+#
+"""
+Target a directory to install resources into.
+"""
+
+import os
+import sys
+import json
+import logging
+from shutil import which
+
+from inkex.inx import InxFile
+from inkex.command import call, CommandNotFound, ProgramRunError
+
+from .archive import Archive, UnrecognizedArchiveFormat
+from .remote import RemoteArchive, LocalFile
+from .utils import INKSCAPE_PROFILE, CACHE_DIR, ExtensionInx
+from .package import PackageItem, OrphanedItem, PythonItem, PythonPackage
+
+
+class BasicTarget(object):
+ """
+ A location where to install something, plus how to search for it.
+ """
+
+ version_specific = False
+
+ def __init__(self, category, label, path, is_search=False, filters=()):
+ self.category = category
+ self.label = label
+ self.path = os.path.join(INKSCAPE_PROFILE, path)
+ self.is_search = is_search
+ self.archive = RemoteArchive(category)
+ self.filters = filters
+ self._installed = None
+
+ def search(self, query, filtered=False):
+ """Search the online archive for things"""
+ for pkg in self.archive.search(query, filtered):
+ pkg.set_installer(self._install)
+ yield pkg
+
+ def is_writable(self):
+ """Can the folder be written to (for installation)"""
+ try:
+ return os.access(self.path, os.W_OK)
+ except IOError:
+ return False
+
+ def _install(self, filename, info):
+ if not info.get("id"):
+ info["id"] = self.generate_id(filename)
+
+ if not info.get("id"):
+ raise ValueError("Id is a required field for packages")
+
+ if filename.endswith(".zip"):
+ location = info["id"]
+ fname = "info.json"
+ info["files"] = list(self.install_zip_files(filename, location))
+ else:
+ location = "pkg"
+ fname = info["id"] + ".json"
+ info["files"] = [self.write_file(filename, os.path.basename(filename))]
+
+ self.write_file(json.dumps(info).encode("utf8"), fname, extra=location)
+
+ return f"Package installed! Remember to restart inkscape to use it!"
+
+ def _uninstall(self, info, json_file):
+ self._installed = None
+ for fname in info.get("files"):
+ self.remove_file(fname)
+ if json_file and os.path.isfile(json_file):
+ self.remove_file(json_file)
+ return True
+
+ def install_zip_files(self, filename, location):
+ """Install the files in the zip filename as non-pip files"""
+ with Archive(filename) as archive:
+ for filename in archive.filenames():
+ yield self.write_file(archive.read(filename), filename, extra=location)
+
+ def generate_id(self, filename):
+ """User submitted zip file, generate an id as best we can"""
+ return filename.replace(".zip", "")
+
+ def list_installed(self, cached=True):
+ """
+ Loops through all the files in the target path and finds all the installed items.
+ """
+ if cached and self._installed:
+ yield from self._installed
+ return
+
+ self._installed = []
+ for item in self._list_installed():
+ self._installed.append(item)
+ yield item
+
+ def _list_installed(self):
+ orphans = OrphanedItem(self.path)
+ for root, subs, files in os.walk(self.path):
+ for fname in files:
+ fpath = os.path.join(root, fname)
+ name = self.unprefix_path(fpath)
+ if fname.endswith(".json"):
+ if os.path.basename(fpath) == "package.json":
+ continue
+ with open(fpath, "rb") as fhl:
+ data = fhl.read()
+ info = json.loads(data)
+ if not PackageItem.is_pkg(info):
+ continue
+
+ item = PackageItem(
+ info, remote=self._remote_or_local_file(root)
+ )
+ item.set_uninstaller(self._uninstall, fpath)
+ yield item
+
+ for pkg_file in item.get_files(missing=True):
+ orphans.remove_file(pkg_file, item)
+ orphans.remove_file(os.path.join(root, pkg_file), item)
+ else:
+ orphans.add_file(name)
+
+ for fname, item in orphans.get_missing():
+ if item is not None:
+ item._missing.append(fname)
+
+ if orphans.get_files(filters=self.filters):
+ yield orphans
+
+ def _remote_or_local_file(self, basedir):
+ # If a json file specifies something that's local, it's "ALWAYS" local to the
+ # json file as a basedir.
+ def _inner(url):
+ if "://" not in url:
+ return LocalFile(basedir, url)
+ return self.archive._remote_file(url)
+
+ return _inner
+
+ def write_file(self, source, source_name=None, extra=None):
+ target = os.path.join(self.path, extra) if extra else self.path
+
+ if isinstance(source, str):
+ if not source_name:
+ source_name = source
+ with open(source, "rb") as fhl:
+ source = fhl.read()
+
+ path = os.path.join(target, source_name)
+ filedir = os.path.dirname(path)
+ if not os.path.isdir(filedir):
+ os.makedirs(filedir)
+
+ # Ignore paths
+ if not os.path.isdir(path):
+ with open(path, "wb") as whl:
+ whl.write(source)
+
+ return self.unprefix_path(path)
+
+ def remove_file(self, filename):
+ """
+ Remove the given file and clean up
+ """
+ if not filename.startswith(self.path):
+ filename = os.path.join(self.path, filename)
+ if os.path.isfile(filename):
+ os.unlink(filename)
+
+ # Recursively clean up directories (if empty)
+ path = os.path.dirname(filename)
+ while path.lstrip("/") != self.path.lstrip("/"):
+ if os.listdir(path):
+ break
+ os.rmdir(path)
+ path = os.path.dirname(path)
+
+ def unprefix_path(self, path):
+ """
+ Removes the prefix of the given path, if it's based in self.path
+ """
+ # Strip just the OS seperator, but what if the files were moved from another OS?
+ return path.replace(self.path, "").lstrip("/").lstrip("\\")
+
+
+class ExtensionsTarget(BasicTarget):
+ """
+ Extra functional target for extensions (pip based)
+ """
+
+ version_specific = True
+
+ def get_pip(self):
+ path = os.path.abspath(os.path.join(self.path, "bin"))
+ return which("pip", path=path + ":" + os.environ["PATH"])
+
+ def _install(self, filename, info):
+ if self.is_pip_package(filename):
+ results = self.pip_install(filename)
+ if results:
+ info["pip"] = True
+ info["id"] = results.strip().split()[-1]
+ fname = info["id"] + ".json"
+ self.write_file(json.dumps(info).encode("utf8"), fname, extra="lib")
+ return (
+ f"Python Package installed! Remember to restart inkscape to use it!"
+ )
+ return f"Failed to install, something is wrong with your setup."
+
+ return super()._install(filename, info)
+
+ def _uninstall(self, info, json_file):
+ self._installed = None
+ if not info.get("pip"):
+ return super()._uninstall(info, json_file)
+ self.pip_uninstall(info["name"])
+ if json_file and os.path.isfile(json_file):
+ self.remove_file(json_file)
+ return True
+
+ def is_pip_package(self, filename):
+ """Return true if this is a detectable pip package"""
+ if filename.endswith(".whl"):
+ return True
+ try:
+ with Archive(filename) as archive:
+ for filename in archive.filenames():
+ if filename.endswith("setup.py"):
+ return True
+ except UnrecognizedArchiveFormat:
+ return False
+ return False
+
+ def pip_install(self, filename):
+ """Install the filename as a pip package"""
+ pip = self.get_pip()
+ if pip is None:
+ logging.error(
+ "This package requires python VirtualEnv which is not available on your system."
+ )
+ return None
+ try:
+ results = call(
+ pip,
+ "install",
+ ("isolated", True),
+ ("disable-pip-version-check", True),
+ ("cache-dir", CACHE_DIR),
+ filename,
+ ).decode("utf8")
+ except ProgramRunError as err:
+ raise
+ return results
+
+ def pip_uninstall(self, name):
+ """Uninstall the given pip package name"""
+ try:
+ results = call(
+ self.get_pip(), "uninstall", ("disable-pip-version-check", True), name
+ ).decode("utf8")
+ except ProgramRunError as err:
+ raise
+ return results
+
+ def generate_id(self, filename):
+ """Extensions have an id internally, try and use it"""
+ try:
+ with Archive(filename) as archive:
+ inxes = [item for item in archive.filenames() if item.endswith(".inx")]
+ if not inxes:
+ raise IOError("Refusing to install extension without inx file!")
+ inx = ExtensionInx(archive.read(inxes[0]).decode("utf-8"))
+ return inx.ident
+ except UnrecognizedArchiveFormat:
+ raise IOError(
+ "Refusing the install extension without inx file (unknown archive)"
+ )
+ except:
+ raise IOError("Refusing the install extension with bad inx file!")
+
+ def _list_installed(self):
+ """
+ Add pip packages to file lists.
+ """
+ orphans = None
+ packages = {}
+ all_deps = set()
+ all_files = set()
+
+ # First collect a list of python packages installed
+ for node in self.get_python_paths():
+ if node.endswith(".dist-info") or node.endswith(".egg-info"):
+ package = PythonPackage(node, self.path)
+ packages[package.name] = package
+ all_files |= set(package.package_files())
+ for dep, _ in package.get_depedencies():
+ all_deps.add(dep)
+
+ # Now return all non pip packaged extensions (from super)
+ for item in super()._list_installed():
+ if item.info.get("pip", False):
+ if self.info.ident not in packages:
+ print(f"Can't find python package: {item.ient}")
+ continue
+
+ pip_pkg = packages[item.ident]
+ item.info["version"] = pip_pkg.version
+
+ if isinstance(item, OrphanedItem):
+ orphans = item
+ else:
+ yield item
+
+ # Remove all orphaned files that were installed by pip packages
+ if orphans is not None:
+ for fn in all_files:
+ orphans.remove_file(fn)
+ if orphans.get_files(filters=self.filters):
+ # Yield if we still have orphans
+ yield orphans
+
+ # Now what to do with all these remaining packages, pretend their installed?
+ for name, package in packages.items():
+ for inx in package.get_inx():
+ item = PythonItem(package)
+ item.set_uninstaller(self._uninstall, None)
+ yield item
+ break
+
+ for dep in all_deps:
+ if dep not in packages:
+ # These packages are often just installed into the system, nothing to say.
+ # XXX But, there is a future where pip could be interigated.
+ # logging.error(f"Missing python depedency: {dep}")
+ continue
+ packages.pop(dep)
+
+ def get_python_paths(self):
+ """Returns paths related to the python packages"""
+ pyver = "python" + sys.version[:3]
+ for varient in [
+ os.path.join(self.path, "lib", pyver, "site-packages"),
+ ]:
+ if os.path.isdir(varient):
+ for subpath in os.listdir(varient):
+ yield os.path.join(varient, subpath)
+
+ def get_package(self, name, version=None):
+ """Test every package in this list if it matches the name and version"""
+ for package in self.iter():
+ found = package.is_package(name, version=version)
+ if found:
+ return package
+ return None
diff --git a/share/extensions/other/inkman/inkman/targets.py b/share/extensions/other/inkman/inkman/targets.py
new file mode 100644
index 0000000..e7bed7c
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/targets.py
@@ -0,0 +1,20 @@
+"""
+Definition of available Inkscape target directories and their machinery
+"""
+
+from .target import ExtensionsTarget, BasicTarget
+
+TARGETS = [
+ # Website slug, Visible name, local directory, search instead of list
+ ExtensionsTarget("extension", "Extensions", "extensions", True, filters=("*.inx",)),
+ BasicTarget("template", "Templates", "templates", True, filters=("*.svg",)),
+ BasicTarget("palette", "Shared Paletts", "palettes", filters=("*.gpl",)),
+ BasicTarget("symbol", "Symbol Collections", "symbols", filters=("*.svg",)),
+ BasicTarget("keyboard", "Keyboard Shortcuts", "keys", filters=("*.xml",)),
+ # ('marker', 'Marker Collections', '', False), # No marker config
+ # ('pattern', 'Pattern Collections', '', False), # No pattern config
+ # ('', 'User Interface Themes', 'themes', False), # No website category
+ # ('', 'Paint Server', 'paint', False), # No website category
+ # ('', 'User Interfaces', 'ui', False), # No website category
+ # ('', 'Icon Sets', 'icons', False), # No website category
+]
diff --git a/share/extensions/other/inkman/inkman/utils.py b/share/extensions/other/inkman/inkman/utils.py
new file mode 100644
index 0000000..f98f3b1
--- /dev/null
+++ b/share/extensions/other/inkman/inkman/utils.py
@@ -0,0 +1,166 @@
+#
+# Copyright (C) 2019 Martin Owens
+#
+# 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.
+#
+"""
+Utilities functions for inkscape extension manager.
+"""
+
+import os
+
+from collections import defaultdict
+from email.parser import FeedParser
+from appdirs import user_cache_dir
+
+from inkex.inx import InxFile
+from inkex.command import inkscape, ProgramRunError, CommandNotFound
+
+DEFAULT_VERSION = "1.1"
+CACHE_DIR = user_cache_dir("inkscape-extension-manager", "Inkscape")
+INKSCAPE_VERSION = os.environ.get("INKSCAPE_VERSION", None)
+INKSCAPE_PROFILE = os.environ.get("INKSCAPE_PROFILE_DIR", None)
+
+# This directory can be passed and used by inkscape to override it's
+# profile directory for extensions
+INKSCAPE_EXTENSIONS = os.environ.get("INKSCAPE_EXTENSIONS_DIR", None)
+
+if not INKSCAPE_PROFILE and "VIRTUAL_ENV" in os.environ:
+ INKSCAPE_PROFILE = os.path.dirname(os.environ["VIRTUAL_ENV"])
+
+if not INKSCAPE_PROFILE and "APPDATA" in os.environ:
+ INKSCAPE_PROFILE = os.path.join(os.environ["APPDATA"], "inkscape")
+
+if not INKSCAPE_PROFILE and not INKSCAPE_EXTENSIONS:
+ raise ImportError("The Inkscape profile directory isn't set!")
+
+if not os.path.isdir(CACHE_DIR):
+ os.makedirs(CACHE_DIR)
+
+DATA_DIR = os.path.join(os.path.dirname(__file__), "data")
+ICON_SEP = ("-" * 12) + "SVGICON" + ("-" * 12)
+
+
+def _pythonpath():
+ for pth in os.environ.get("PYTHONPATH", "").split(":"):
+ if os.path.isdir(pth):
+ yield pth
+
+
+def get_user_directory():
+ """Return the user directory where extensions are stored."""
+ if INKSCAPE_EXTENSIONS:
+ return os.path.abspath(INKSCAPE_EXTENSIONS)
+
+ if "INKSCAPE_PROFILE_DIR" in os.environ:
+ return os.path.abspath(
+ os.path.expanduser(
+ os.path.join(os.environ["INKSCAPE_PROFILE_DIR"], "extensions")
+ )
+ )
+
+ home = os.path.expanduser("~")
+ for pth in _pythonpath():
+ if pth.startswith(home):
+ return pth
+
+
+def get_inkscape_directory():
+ """Return the system directory where inkscape's core is."""
+ for pth in _pythonpath():
+ if os.path.isdir(os.path.join(pth, "inkex")):
+ return pth
+
+
+def get_inkscape_version():
+ """Attempt to detect the inkscape version"""
+ try:
+ line = inkscape(version=True, svg_file=None)
+ except (ProgramRunError, CommandNotFound):
+ return DEFAULT_VERSION
+ if isinstance(line, bytes):
+ line = line.decode("utf8")
+ (major, minor) = line.strip().split(" ")[1].split(".")[:2]
+ return "{}.{}".format(int(major), int(minor.split("-")[0]))
+
+
+def format_requires(string):
+ """Get a version requires."""
+ primary = string.split("; ", 1)[0]
+ if "(" in primary:
+ primary, version = primary.split("(", 1)
+ return (primary.strip(), version.strip(") "))
+ return (primary.strip(), None)
+
+
+def parse_metadata(data):
+ """
+ Convert older email based meta data into a newer json format,
+ See PEP 566 for details.
+ """
+ feed_parser = FeedParser()
+ feed_parser.feed(data)
+ metadata = feed_parser.close()
+
+ def getdict():
+ """Multi-dimentional dictionary"""
+ return defaultdict(getdict)
+
+ ret = defaultdict(getdict)
+
+ ret["description"] = metadata.get_payload()
+ ret["requires"] = [
+ format_requires(m) for m in metadata.get_all("Requires-Dist", [])
+ ]
+
+ for key, value in metadata.items():
+ if key == "Home-page":
+ ret["extensions"]["python.details"]["project_urls"]["Home"] = value
+ elif key == "Classifier":
+ ret["classifiers"] = list(ret["classifiers"])
+ ret["classifiers"].append(value)
+ else:
+ ret[key.lower().replace("-", "_")] = value
+
+ return ret
+
+
+def clean_author(data):
+ """Clean the author so it has consistant keys"""
+ for contact in (
+ data.get("extensions", {}).get("python.details", {}).get("contacts", [])
+ ):
+ if contact["role"] == "author":
+ data["author"] = contact["name"]
+ data["author_email"] = contact.get("email", "")
+ if "<" in data["author"]:
+ data["author"], other = data["author"].split("<", 1)
+ if "@" in other and not data["author_email"]:
+ data["author_email"] = data["author"].split(">")[0]
+ return data
+
+
+class ExtensionInx(InxFile):
+ """Information about an extension specifically"""
+
+ ident = property(lambda self: super().ident or f"[no-id] {self.filename}")
+ name = property(lambda self: super().name or f"[unnamed] {self.ident}")
+
+ @property
+ def menu(self):
+ menu = self.xml.find_one("effect/effects-menu")
+ if menu is not None and menu.get("hidden", "false") == "true":
+ return ["_hidden", self.name]
+ return super().menu
diff --git a/share/extensions/other/inkman/manage_extensions.inx b/share/extensions/other/inkman/manage_extensions.inx
new file mode 100644
index 0000000..dc2b01f
--- /dev/null
+++ b/share/extensions/other/inkman/manage_extensions.inx
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
+ <name>Manage Extensions...</name>
+ <id>org.inkscape.extension.manager</id>
+ <effect needs-document="false" refresh-extensions="true" implements-custom-gui="true">
+ <object-type>all</object-type>
+ <effects-menu hidden="true"/>
+ </effect>
+ <script>
+ <command location="inx" interpreter="python">manage_extensions.py</command>
+ </script>
+</inkscape-extension>
diff --git a/share/extensions/other/inkman/manage_extensions.py b/share/extensions/other/inkman/manage_extensions.py
new file mode 100755
index 0000000..41494c7
--- /dev/null
+++ b/share/extensions/other/inkman/manage_extensions.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright 2018 Martin Owens <doctormo@gmail.com>
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>
+#
+"""
+Inkscape Extensions Manager, Graphical User Interface (Gtk3)
+"""
+
+import os
+import sys
+import logging
+import warnings
+warnings.filterwarnings("ignore")
+
+from inkex import gui
+
+from argparse import ArgumentParser
+
+
+def run(args):
+ # Late imports to catch import errors.
+ from inkman.targets import TARGETS
+ from inkman.gui import ManagerApp
+ from inkman.utils import get_inkscape_version
+
+ arg_parser = ArgumentParser(description=__doc__)
+ arg_parser.add_argument("input_file", nargs="?")
+ arg_parser.add_argument(
+ "--target", default=TARGETS[0].category, choices=[t.category for t in TARGETS]
+ )
+ arg_parser.add_argument("--for-version", default=None)
+ options = arg_parser.parse_args(args)
+ version = options.for_version or get_inkscape_version()
+ try:
+ ManagerApp(
+ start_loop=True,
+ version=version,
+ target=[t for t in TARGETS if t.category == options.target][0],
+ )
+ except KeyboardInterrupt:
+ logging.error("User Interputed")
+ logging.debug("Exiting Application")
+
+
+def recovery_run(args):
+ try:
+ run(args)
+ except Exception:
+ from inkman.backfoot import attempt_to_recover
+
+ attempt_to_recover()
+
+
+if __name__ == "__main__":
+ recovery_run(sys.argv[1:])
diff --git a/share/extensions/other/inkman/pyproject.toml b/share/extensions/other/inkman/pyproject.toml
new file mode 100644
index 0000000..d2a4fbf
--- /dev/null
+++ b/share/extensions/other/inkman/pyproject.toml
@@ -0,0 +1,19 @@
+[tool.poetry]
+name = "inkman"
+version = "1.0.0"
+description = "A GTK3 based extension manager for Inkscape."
+authors = ["Martin Owens <doctormo@geek-2.com>"]
+maintainers = ["Martin Owens <doctormo@geek-2.com>"]
+license = "GPL-3.0-or-later"
+
+# The dependencies below are NOT used for packaging, they are abstract.
+# They are merely for packagers' convenience and are used in CI for extensions.
+[tool.poetry.dependencies]
+python = ">=3.7"
+appdirs = "1.4.4"
+requests = "*"
+CacheControl = {extras = ["filecache"], version = "*"}
+
+[build-system]
+requires = ["poetry-core>=1.0.0"]
+build-backend = "poetry.core.masonry.api"