diff options
Diffstat (limited to '')
49 files changed, 4086 insertions, 0 deletions
diff --git a/share/extensions/docs/Makefile b/share/extensions/docs/Makefile new file mode 100644 index 0000000..43276bb --- /dev/null +++ b/share/extensions/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = ../build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/share/extensions/docs/_templates/versions.html b/share/extensions/docs/_templates/versions.html new file mode 100644 index 0000000..476c8d1 --- /dev/null +++ b/share/extensions/docs/_templates/versions.html @@ -0,0 +1,27 @@ +{%- if current_version %} +<div class="rst-versions" data-toggle="rst-versions" role="note" aria-label="versions"> + <span class="rst-current-version" data-toggle="rst-current-version"> + <span class="fa fa-book"> Other Versions</span> + v: {{ current_version.name }} + <span class="fa fa-caret-down"></span> + </span> + <div class="rst-other-versions"> + {%- if versions.tags %} + <dl> + <dt>Tags</dt> + {%- for item in versions.tags %} + <dd><a href="{{ item.url }}">{{ item.name }}</a></dd> + {%- endfor %} + </dl> + {%- endif %} + {%- if versions.branches %} + <dl> + <dt>Branches</dt> + {%- for item in versions.branches %} + <dd><a href="{{ item.url }}">{{ item.name }}</a></dd> + {%- endfor %} + </dl> + {%- endif %} + </div> +</div> +{%- endif %}
\ No newline at end of file diff --git a/share/extensions/docs/authors/index.rst b/share/extensions/docs/authors/index.rst new file mode 100644 index 0000000..8e7b967 --- /dev/null +++ b/share/extensions/docs/authors/index.rst @@ -0,0 +1,29 @@ +Writing Extensions: In-Depth +============================ + +.. toctree:: + :maxdepth: 2 + + inx-overview + inx-widgets + interpreters + unit-tests + submit + +Highlevel explanation of specific inkex features +---------------------------------------------------- + +.. toctree:: + :maxdepth: 2 + + units + +Update guides +------------- + +.. toctree:: + :maxdepth: 2 + + update1.0 + update1.2 +
\ No newline at end of file diff --git a/share/extensions/docs/authors/interpreters.rst b/share/extensions/docs/authors/interpreters.rst new file mode 100644 index 0000000..254abd6 --- /dev/null +++ b/share/extensions/docs/authors/interpreters.rst @@ -0,0 +1,114 @@ +.. _supported_interpreters: + +Supported Interpreters +====================== + +Inkscape Script extensions can use one of the following interpreters: + ++----------+------------------+----------------------+------------------+ +| Language | Name (in INX | Name (in | Default value | +| | file) | preferences.xml) | | ++==========+==================+======================+==================+ +| Perl | "perl" | "perl-interpreter" | "perl" | +| | | | | +| | | | "wperl" (Windows;| +| | | | since Inkscape | +| | | | 1.0) | ++----------+------------------+----------------------+------------------+ +| Python | "python" | "python-interpreter" | "python" | +| | | | | +| | | | "pythonw" | +| | | | (Windows) | ++----------+------------------+----------------------+------------------+ +| Ruby | "ruby" | "ruby-interpreter" | "ruby" | ++----------+------------------+----------------------+------------------+ +| Shell | "shell" | "shell-interpreter" | "sh" | ++----------+------------------+----------------------+------------------+ + +(Code reference: `src/extension/implementation/script.cpp`_) + +.. _src/extension/implementation/script.cpp: https://gitlab.com/inkscape/inkscape/-/blob/master/src/extension/implementation/script.cpp + +.. _inx_files: + +INX files +--------- + +Within the INX file, you need to indicate the interpreter which will be +used to execute the script, using the name given in the table above: + +Example: + +:: + + <inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension"> + ... + <script> + <command reldir="extensions" interpreter="python">my_extension.py</command> + </script> + </inkscape-extension> + +.. _selecting_a_specific_interpreter_version_via_preferences_file: + +Selecting a specific interpreter version (via preferences file) +--------------------------------------------------------------- + +In the preferences.xml file, a user can set a specific executable of the +interpreter that Inkscape should use to execute extensions of a specific +type. + +This is especially useful, if the system's default version of the +interpreter is incompatible with the one used by Inkscape's extension +subsystem (e.g. Inkscape extensions that rely on inkex.py will only work +with Python 2 (as of Inkscape 0.92.1), while on some recent Linux +distributions, the default Python version used is Python 3, which +results in errors during execution of extensions). + +To change the executable that will be used to run script extensions to a +different value than the default value in the above table, you need to +do the following: + +#. quit all running Inkscape processes +#. Open your perferences.xml file with a text editor (find the exact + location of the file by going to Edit -> Preferences -> System: User + Preferences) +#. search the group which holds settings for the extension system itself + and options of various extensions: + :: + + <group + id="extensions" + … + org.ekips.filter.gears.teeth="24" + org.ekips.filter.gears.pitch="20" + org.ekips.filter.gears.angle="20" /> + +#. Insert a key for the interpreter, for example 'python-interpreter' + for setting the program that should be used to run python extensions, + and set the string to the absolute path to the python binary which is + compatible with Inkscape's current extension scripts (in the example + below, the path is "/usr/bin/python2.7". It will look different on + Windows systems.): + :: + + <group + id="extensions" + python-interpreter="/usr/bin/python2.7" + … + org.ekips.filter.gears.teeth="24" + org.ekips.filter.gears.pitch="20" + org.ekips.filter.gears.angle="20" /> + +#. Save the preferences file, and launch Inkscape to test the + extensions. + +.. _see_also: + +See Also +-------- + +- `INX Parameters <INX_Parameters>`__ +- `ScriptingHOWTO <ScriptingHOWTO>`__ + +`Category:Developer Documentation <Category:Developer_Documentation>`__ +`Category:Extensions <Category:Extensions>`__ diff --git a/share/extensions/docs/authors/inx-overview.rst b/share/extensions/docs/authors/inx-overview.rst new file mode 100644 index 0000000..83843d4 --- /dev/null +++ b/share/extensions/docs/authors/inx-overview.rst @@ -0,0 +1,238 @@ +INX extension descriptor format +=============================== + + +.. highlight:: xml + +Introduction +------------ + +In order for Inkscape to make use of an external script or program, you +must describe that script to inkscape using an INX file. The INX file is +an XML file with Inkscape-specific content that can be edited in a +plain-text editor. + +The INX file allows the author to: + +- Specify what type of extension it is, for example input, output, or + effect +- Identify :ref:`which interpreter <supported_interpreters>` should be used to run the extension +- List dependencies; files or other extensions required for operation +- Define parameters that can be set in the extension +- Create :ref:`a GUI with control widgets <inx-widgets>` for those parameters +- Add a submenu to the Extensions menu for the extension to reside in +- Label strings for translation +- Chain extensions +- Etc + +Nothing beats a working example, and Inkscape includes a great number of +extensions with INX files that you can read. To find the location of +your Inkscape extensions directory, where included extensions and their +INX files are located, look in the System pane of Inkscape Preferences, +under "Inkscape extensions". + +.. _translation_of_extensions: + +Translation of extensions +------------------------- + +Extension dialog windows, described in INX files, can be prepared for +translation or localisation by adding an ``_`` (underscore) to the XML +tags or attributes. Only add underscores when text needs to be +translated (not numeric values, for example!). + +Example:: + + <_name>Some translatable extension name</_name> + +Or:: + + <param name="..." type="..." _gui-text="Some translatable label text"> + +When extensions are included in the `Inkscape Extensions Repository`_, +various scripts will scan each INX file for translatable text and +prepare `translation files`_ for others to translate. + +See also: `Ted's blog`_. + +.. _attributes_description: + +Attributes description +---------------------- + ++---------------------------+-------------------------+ +| Attribute name | Allowed values | ++===========================+=========================+ +| ``implements-custom-gui`` | ``"true"`` | | +| | ``"false"`` (default) | +| .. versionadded:: 1.0 | | ++---------------------------+-------------------------+ +| If set to ``true`` **requires** an effect | +| extension to implement custom GUI. | +| | +| .. hint:: | +| *Implementation detail:* The "extension is | +| working" window is not shown for this kind of | +| extensions. This means user interaction with the | +| Inkscape interface is blocked until the | +| extension returns, with no way for the user to | +| abort the running extension! It is therefore | +| **absolutely essential** that your extension | +| provides the necessary visual feedback for the | +| user and has proper error handling, to rule out | +| any dead-locking behavior. | ++---------------------------+-------------------------+ +| ``needs-document`` | ``"true"`` (default) | | +| | ``"false"`` | +| .. versionadded:: 1.0 | | ++---------------------------+-------------------------+ +| If set to ``false`` an effect extension will not be | +| passed a document nor will a document be read back | +| ("no-op" effect). This is currently a hack to make | +| extension manager work and will likely be | +| removed/replaced in future, so use at your | +| **own risk**! | ++---------------------------+-------------------------+ +| ``needs-live-preview`` | ``"true"`` (default) | +| | ``"false"`` | ++---------------------------+-------------------------+ +| If set to ``true`` in an effect extension, it will | +| offer a "Live preview" checkbox in its GUI. When | +| the user checks that box, it will run the extension | +| in a "preview mode", visually showing the effect of | +| the extension, but not making any changes to the | +| SVG document, unless the user clicks the Apply | +| button. While "Live preview" is checked in the GUI, | +| any changes that the user makes to parameters | +| accessible in the GUI will generate an updated | +| preview. | ++---------------------------+-------------------------+ +| ``savecopyonly`` | ``"true"`` | | +| | ``"false"`` (default) | +| .. versionadded:: 1.2 | | ++---------------------------+-------------------------+ +| If set to ``true`` in an **output** extension, it | +| will limit the extension to being available only | +| in the "Save a Copy" menu. | ++---------------------------+-------------------------+ + + +Example +------- + +:: + + <?xml version="1.0" encoding="UTF-8"?> + <inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension"> + <_name>{Friendly Extension Name}</_name> + <id>{org.domain.sub-domain.extension-name}</id> + <dependency type="executable" location="[extensions|path|plugins|{location}]">program.ext</dependency> + <param name="tab" type="notebook"> + <page name="controls" _gui-text="Controls"> + <param name="{argumentName}" type="[int|float|string|bool]" min="{number}" max="{number}" + _gui-text="{Friendly Argument Name}">{default value}</param> + </page> + <page name="help" _gui-text="Help"> + <param name="help_text" type="description">{Friendly Extension Help}</param> + </page> + </param> + <effect> + <object-type>[all|{element type}]</object-type> + <effects-menu> + <submenu _name="{Extension Group Name}"/> + </effects-menu> + </effect> + <script> + <command reldir="extensions" interpreter="[python|perl|ruby|bash|{some other}]">program.ext</command> + </script> + </inkscape-extension> + +More example INX files are available in the Inkscape distribution, which +takes its files from the `Inkscape Extensions Repository`_. + +For a full list of currently supported interpreters, please see +:ref:`supported_interpreters`. + +.. _dtd_xml_schema: + +DTD XML schema +-------------- + +.. warning:: This section contains slightly outdated information. + +The following XML schema may not fully describe the current INX file +structure. The actual XML schema used is described in the :ref:`next +paragraph <relax_ng_xml_schema>`. + +:: + + <!ELEMENT inkscape-extension (name, id, dependency*, param*,(input|output|effect),(script|plugin))> + <!ELEMENT input (extension, mimetype, filetype, filetypetooltip, output_extension?)> + <!ELEMENT output (extension, mimetype, filetype, filetypetooltip, dataloss?)> + <!ELEMENT effect (object-type|submenu?)> + <!ELEMENT script (command, helper_extension*, check*)> + <!ELEMENT plugin (name)> + <!ELEMENT name (#PCDATA)> + <!ELEMENT id (#PCDATA)> + <!ELEMENT item (#PCDATA)> + <!ELEMENT option (#PCDATA)> + <!ELEMENT dependency (#PCDATA)> + <!ELEMENT param (#PCDATA|page|item|option)*> + <!ELEMENT page (#PCDATA, param*)> + <!ELEMENT extension (#PCDATA)> + <!ELEMENT mimetype (#PCDATA)> + <!ELEMENT filetype (#PCDATA)> + <!ELEMENT filetooltip (#PCDATA)> + <!ELEMENT object-type (#PCDATA)> + <!ELEMENT command (#PCDATA)> + <!ELEMENT check (#PCDATA)> + <!ELEMENT dataloss (#PCDATA)> + <!ELEMENT helper_extension (#PCDATA)> + <!ELEMENT output_extension (#PCDATA)> + <!ELEMENT menu-tip (#PCDATA)> + + <!ATTLIST check reldir (absolute|path|extensions|plugins) #REQUIRED> + <!ATTLIST command reldir (absolute|path|extensions|plugins) #REQUIRED> + <!ATTLIST command interpreter CDATA #REQUIRED> + <!ATTLIST dependency type (executable|extension) #REQUIRED> + <!ATTLIST dependency location (absolute|path|extensions|plugins) #IMPLIED> + <!ATTLIST dependency description CDATA #IMPLIED> + <!ATTLIST effect needs-live-preview (true|false) #REQUIRED> + <!ATTLIST effect implements-custom-gui (true|false) #IMPLIED> + <!ATTLIST effect needs-document (true|false) #IMPLIED> + <!ATTLIST page name CDATA #REQUIRED> + <!ATTLIST page gui-text CDATA #IMPLIED> + <!ATTLIST param name CDATA #REQUIRED> + <!ATTLIST param type (int|float|string|bool|notebook|path|optiongroup|color) #REQUIRED> + <!ATTLIST param min CDATA #IMPLIED> + <!ATTLIST param max CDATA #IMPLIED> + <!ATTLIST param max_length CDATA #IMPLIED> + <!ATTLIST param precision CDATA #IMPLIED> + <!ATTLIST param gui-text CDATA #IMPLIED> + <!ATTLIST param gui-tip CDATA #IMPLIED> + <!ATTLIST param gui-description CDATA #IMPLIED> + <!ATTLIST param scope CDATA #IMPLIED> + <!ATTLIST param gui-hidden CDATA #IMPLIED> + <!ATTLIST param appearance (minimal|) ""> + <!ATTLIST submenu name CDATA #REQUIRED> + +.. _relax_ng_xml_schema: + +RELAX NG XML schema +------------------- + +The XML schema for INX files is available in the `Inkscape extensions +Git repository`_. This is a `RELAX NG schema`_. + +.. _see_also: + +.. _next paragraph: INX_extension_descriptor_format#RELAX_NG_XML_schema +.. _Inkscape extensions Git repository: https://gitlab.com/inkscape/extensions/-/blob/master/inkscape.extension.rng +.. _RELAX NG schema: http://www.relaxng.org/ +.. _INX Parameters: Extensions:_INX_widgets_and_parameters +.. _ScriptingHOWTO: ScriptingHOWTO + +.. _Inkscape Extensions Repository: https://gitlab.com/inkscape/extensions +.. _a GUI with control widgets: Extensions:_INX_widgets_and_parameters +.. _translation files: https://gitlab.com/inkscape/inkscape/-/tree/master/po +.. _Ted's blog: http://gould.cx/ted/blog/Translating_Custom_XML
\ No newline at end of file diff --git a/share/extensions/docs/authors/inx-widgets.rst b/share/extensions/docs/authors/inx-widgets.rst new file mode 100644 index 0000000..5c4e1d5 --- /dev/null +++ b/share/extensions/docs/authors/inx-widgets.rst @@ -0,0 +1,536 @@ +.. _inx-widgets: + +INX widgets and parameters +========================== + +This page contains the reference documentation for INX widgets and +parameters. Their primary goal is to make it easy to design GUIs for +`Inkscape Extensions <Extension_subsystem>`__ using the built-in `INX +extension descriptor format <INX_extension_descriptor_format>`__, +although (invisible) parameters can also be used for extensions that +don't need to show a user interface. + +Introduction +------------ + +Extension GUIs consists of an arbitrary number of GUI elements, +so-called `Widgets <#Widgets>`__. These can be simple text labels, boxes +and spacers to control layout or more complex UI elements like images. + +A special class of Widgets are `Parameters <#Parameters>`__. They differ +from other Widgets in that they have a user-settable value, for example +a boolean (implemented as checkbox) or integer (implemented as number +entry). The value of each Parameter is passed to the extension on +execution and can be used to control its behavior. + +All Widgets are described using an easy-to-learn XML schema with +predefined tags and attributes which are described in detail below. + +.. _available_widgets: + +Available Widgets +~~~~~~~~~~~~~~~~~ + +A general Widget takes the form + +.. code:: + + <widget_name attribute1="value1" attribute2="value2" ...>value</widget_name> + +where ``widget_name`` specifies the name of the widget and is one of the +following: + +- ``label``:sup:`since 1.0`\ +- ``hbox``:sup:`since 1.0`\ /``vbox``:sup:`since 1.0`\ +- ``separator``:sup:`since 1.0`\ /``spacer``:sup:`since 1.0`\ +- ``image``:sup:`since 1.0`\ +- ``param`` (for all Parameter types) + +.. _apt: + +Available Parameter types +~~~~~~~~~~~~~~~~~~~~~~~~~ + +A general Parameter takes the form + +.. code:: + + <param type="parameter_type" attribute1="value1" atribute2="value2" ...>value</param > + +where ``parameter_type`` specifies the type of the parameter and is one +of the following: + +- ``bool``:sup:`since 1.0`\ +- ``int`` +- ``float`` +- ``string`` +- ``path``:sup:`since 1.0`\ +- ``optiongroup`` +- ``notebook`` +- ``color`` + +If a parameter is made invisible (see ``gui-hidden`` attribute in the +`next section <#common-attributes>`__) it will not be shown in the GUI +but it's value is still passed to an extension. This is useful if you +want to hardcode parameter value the user should not be able to change. +If all parameters (and potential widgets) are invisible, Inkscape will +not show a GUI and execute the extension immediately instead, but will +still pass the values of the invisible parameters. + +.. _common_attributes: + +Common attributes +----------------- + +For all widgets +~~~~~~~~~~~~~~~ + ++------------------+------------------+------------------+------------------+ +| Attribute | Allowed | Default | Required? | +| name | value(s) | value | | ++==================+==================+==================+==================+ +| ``gui-hidden`` | ``true``, | | | +| | ``false`` | ``false`` | optional | ++------------------+------------------+------------------+------------------+ +| If set to ``true`` the Widget is hidden from the GUI (primarily used to | +| add hidden parameters that are passed to the extension but are not | +| supposed to be editable by the user.) | +| | +| *Note: If there are* **no** *visible parameters defined in a GUI, the | +| extension is executed immediately without showing a dialog.* | ++------------------+------------------+------------------+------------------+ +| ``indent`` | ``0,1,2,…`` | ``0`` | optional | ++------------------+------------------+------------------+------------------+ +| Sets indentation level of the parameter. Increasing indentation adds | +| padding to the start of the line. | ++------------------+------------------+------------------+------------------+ + + + +Only for Parameters +~~~~~~~~~~~~~~~~~~~ + ++------------------------+------------------------+------------------------+------------------------+ +| Attribute name | Allowed value(s) | Default value | Required? | ++========================+========================+========================+========================+ +| ``name`` | *(text)* | -- | required | ++------------------------+------------------------+------------------------+------------------------+ +| Used as an identifier of the parameter. It has to be unique since the value of this attribute is | +| used to save and transmit parameter values internally! | ++------------------------+------------------------+------------------------+------------------------+ +| ``type`` | see `above <#apt>`__ | -- | required | ++------------------------+------------------------+------------------------+------------------------+ +| Determines the type of the parameter, see the extensive description of | +| `Parameters <#parameters>`__ below. | ++------------------------+------------------------+------------------------+------------------------+ +| ``gui-text`` | *(text)* | -- | required *(visible | +| | | | parameters)*, optional | +| | | | *(hidden parameters* + | +| | | | ``notebooks`` *)* | ++------------------------+------------------------+------------------------+------------------------+ +| Label shown for the parameter in the GUI. | ++------------------------+------------------------+------------------------+------------------------+ +| ``gui-description`` | *(text)* | -- | optional | ++------------------------+------------------------+------------------------+------------------------+ +| Tooltip shown for the parameter when the user hovers the mouse cursor over the active area of the | +| parameter in question. | ++------------------------+------------------------+------------------------+------------------------+ + + + +Widgets +------- + +``hbox`` / ``vbox`` +~~~~~~~~~~~~~~~~~~~ + +Creates a container for other widgets. No visual rendering but provides a possibility to align and +layout other widgets. Child widgets are either added in horizontal (``hbox``) or vertical +(``vbox``) direction. + + .. code:: xml + + <hbox>…</hbox> + <vbox>…</vbox> + +A box can contain an arbitrary number of other widgets and parameters (including other boxes) to +fine-tune the layout of the GUI. + +*Note*: When you start with an empty extension GUI, you're basically starting with a ``vbox``. +Also ``notebook`` pages behave like vertically oriented boxes. + +.. figure:: widgets/separator.png + :alt: Rendering of hbox/vbox + + ``hbox`` and ``vbox`` + +``image`` +~~~~~~~~~ + +Creates a widget displaying an image. The content of the node specifies +the path of the image file (ideally specify a path relative to the .inx +file itself). + +.. code:: xml + + <image>path/to/image.svg</image> + +By default the image will be rendered at it's actual size. Use +attributes ``width/heigth`` to override the default size (in this case +*both* attributes need to be supplied; units are pixels). + +Images are aligned in the horizontal center of the current box; different alignment +can be realized by wrapping the image in a `hbox <#hbox-vbox>`__ and adding a +`spacer <#spacer>`__ with ``size=expand`` +before (for right alignment) or after (for left alignment) of the image. + +*Implementation note: Loadable image formats are determined by GdkPixbuf +and therefore system-specific. PNG should always work and is the safe +choice. SVG should mostly work and is the preferred choice for obvious +reasons.* + +.. figure:: widgets/image.png + :alt: Rendering of image + + An ``image`` + +``label`` +~~~~~~~~~ + +Creates a widget showing text. The content of the node corresponds to +the text content that will be rendered. + +.. code:: xml + + <label>Some text here.</label> + +*Note: Labels are intended to provide additional information / help. For +labeling parameters use the ``gui-text`` attribute; for short help texts +that are specific to a single parameter prefer ``gui-description`` which +will render as a tooltip.* + +- When setting the attribute ``appearance="header"`` the text is styled + as a heading and can be used as another possibility to group + parameters. +- | When setting the attribute ``appearance="url"`` the text is rendered + as a clickable link. + | *Note: The text is escaped and used as the link target as-is. + Creating a link text that differs from the URL is prevented for + security reasons.* +- When setting the attribute ``xml:space="preserve"`` any white-space + (spaces, tabs, line-breaks, etc.) in the label will be preserved, + allowing to format the label accordingly. By default all + leading/tailing and intermediary whitespace is collapsed into a + single space character. + +.. figure:: widgets/label.png + :alt: Rendering of different labels + + Different label types (in order): default | ``appearance="header"`` | + ``appearance="url"`` | ``xml:space="preserve"`` + +``separator`` +~~~~~~~~~~~~~ + +Creates a separator for visual separation of other widgets. Renders as a +horizontal/vertical line. + +.. code:: xml + + <separator /> + +The direction of the separator will automatically adjust depending on +direction of the current container (vertical for "empty" extension GUIs +and ``notebook`` pages; vertical/horizontal for ``vbox`` and ``hbox`` +respectively). + +.. figure:: widgets/separator.png + :alt: Rendering of separators + + Separators can be used in `hbox` and `vbox` environments. + +``spacer`` +~~~~~~~~~~ + +Creates a spacer for visual separation of other widgets. No visual +rendering but provides variable spacing. + +.. code:: xml + + <spacer /> + +The direction of the spacer will automatically adjust depending on +direction of the current container (vertical for "empty" extension GUIs +and ``notebook`` pages; vertical/horizontal for ``vbox`` and ``hbox`` +respectively). + +Use the ``size`` attribute to set the spacing in pixels (default: +``size="10"``). The special value ``expand`` results in a spacer that +grows dynamically and always uses up as much space as possible (useful +for aligning content). + +.. figure:: widgets/spacer.png + :alt: Rendering of spacers + + Different spacer types: (1) default, (2) ``size="30"``, (3) ``size="expand"`` + +Parameters +---------- + +``bool`` +~~~~~~~~ + +.. versionadded:: 1.0 + +Creates a checkbox to set a **boolean value**. Allowed values are +``true`` or ``false`` (default value: ``true``). + +.. code:: xml + + <param name="name" type="boolean" gui-text="Some label text">false</param> + +.. figure:: widgets/bool.png + :alt: Checkbox + + Rendering of ``boolean`` values + + +``color`` +~~~~~~~~~ + +Creates a control to select an **RGBA color value**. Values should be +given in hexadecimal notation, e.g. ``0xff0000ff`` for red with full +opacity (default value: ``0x000000ff``) + +.. code:: xml + + <param name="name" type="color" gui-text="Some label text">0x000000ff</param> + +Use ``appearance="colorbutton"`` for a simple button that opens a +simplified color picker. Otherwise a full ColorNotebook will be +rendered. + +.. figure:: widgets/color.png + :alt: Rendering of color parameter + + Rendering of a full ColorNotebook for a ``color`` parameter + +.. versionchanged:: 1.0 + + *Implementation note:* colors values are internally treated as 32-bit + unsigned integers (unsigned long). Acceptable default values include + everything the standard library function ``strtoul`` [#]_ understands (since Inkscape 1.0). + Earlier Inkscape version only handled decimal numbers. The value passed + to the extension script will also be a decimal number. + + + +``float`` +~~~~~~~~~ + +Creates a input to enter a **floating point number**. Limit the input +range with the ``min`` and ``max`` attributes; set the number of decimal +places with the ``precision`` attribute. (defaults: ``min="0"``, +``max="10"`` and ``precision="1"``; default value: 0) + +.. code:: xml + + <param name="name" type="float" precision="1" min="0" max="100" + gui-text="Float Parameter">1.234</param> + +Use the attribute ``appearance="full"`` to create a slider with which +the value can be adjusted dynamically over the full range. + +.. figure:: widgets/float.png + :alt: Rendering of float parameter + + Rendering of ``float`` parameters: default and with ``appearance="full"`` + +``int`` +~~~~~~~ + +Creates a textbox input to enter an **integer number**. Limit the input +range with the ``min`` and ``max`` attributes. (defaults: ``min="0"`` +and ``max="10"``; default value: 0) + +.. code:: xml + + <param name="name" type="int" min="1" max="100" gui-text="Integer Parameter">1</param> + +Use the attribute ``appearance="full"`` to create a slider with which +the value can be adjusted dynamically over the full range. + +.. figure:: widgets/integer.png + :alt: Rendering of integer parameter + + Rendering of ``int`` parameters: default and with ``appearance="full"`` + + +``notebook`` +~~~~~~~~~~~~ + +Creates a set of pages (aka tab control). The user can switch between +individual pages. Each page can contain an arbitrary set of other +Widgets and Parameters. Individual pages are created with the element. + +The **returned value** for ``notebook`` parameters is the value of the +``name`` attribute of the selected . By default the first page is +selected. + +Notebooks can be used to show widgets based on an option; that option +would be implemented as notebook. + +.. code:: xml + + <param name="name" type="notebook"> + <page name="page_1" gui-text="First page"> + … + </page> + <page name="page_2" gui-text="Second page"> + … + </page> + </param> + +.. figure:: widgets/notebook.png + :alt: Rendering of notebook parameter + + Rendering of a ``notebook`` + + +``optiongroup`` +~~~~~~~~~~~~~~~ + +Creates a control that allows to select one option **one option** from a +set of multiple choices. The different choices are created with +elements. + +The **returned value** for ``optiongroup`` type parameters is the value +of the ``value`` attribute of the selected . By default the first is +selected. + +.. code:: xml + + <param name="name" type="optiongroup" appearance="radio/combo" + gui-text="Some label text"> + <option value="1">First option</option> + <option value="2">Second option</option> + </param> + +.. versionadded:: 1.0 + Set the attribute ``appearance="radio"``\ to render radio buttons + (default). Set the attribute ``appearance="combo"``\ to display a + drop-down list instead. + +.. figure:: widgets/optiongroup.png + :alt: Rendering of float parameter + + Rendering of ``optionsgroup`` parameters: ``appearance="radio"`` and + ``appearance="combo"``. On the bottom parameter, ``precision="1"`` + has been set. + + +``path`` +~~~~~~~~ + + +.. versionadded:: 1.0 + +Creates a control to choose a **path**. Paths can either be entered +manually or by using the file chooser that can be opened using the +ellipsis button. + +The ``mode`` attribute allows to set behavior of the file chooser (i.e. +if files or folders can be selected, if they need to exist previously +and if multiple selections are possible). The ``filetypes`` attribute +holds a comma-separated list of file extensions and restricts the +selectable file types in file picker mode. + +.. code:: + + <param type="path" name="varname" gui-text="label" mode="$mode" [filetypes="$filetypes"]/> + +Possible values for the ``mode`` attribute: + +- ``file`` - select a single existing file +- ``files`` - select multiple existing files +- ``folder`` - select a single existing folder +- ``folders`` - select multiple existing folders +- ``file_new`` - select a single new file name +- ``file_new`` - select a single new folder name + +Examples + +- Files: + + - Choose a file, with file type restriction (optional): + + .. code:: xml + + <param name="my_file" type="path" mode="file" filetypes="png,jpg" gui-text="A file:">my/path/to/file.png</param> + - Choose multiple files (file type restriction possible, too): + + .. code:: xml + + <param name="my_files" type="path" mode="files" gui-text="Multiple files:">my/path/to/file.png</param> + - Create a new file: + + .. code:: xml + + <param name="my_new_file" type="path" mode="file_new" filetypes="png" gui-text="A new file:">my/path/to/file.png</param> + +- Folders: + + - Choose a folder: + + .. code:: xml + + <param name="my_folder" type="path" mode="folder" gui-text="A folder:">my/path/</param> + - Choose multiple folders: + + .. code:: xml + + <param name="my_folders" type="path" mode="folders" gui-text="Folders:">my/path/</param> + - Create a new folder: + + .. code:: xml + + <param name="my_new_folder" type="path" mode="folder_new" filetypes="png" gui-text="A new folder:">my/path/</param> + + +.. figure:: widgets/path.png + :alt: Rendering of path parameter + + Rendering of ``path`` parameters + + +*Implementation note:* Existence of paths are not checked before passing +them to the extension, so extension authors need to implement suitable +error handling, especially in case of manual path entry. For multiple +selections the individual paths are joined using the pipe character +("|") and passed to the extension as a single string. + +``string`` +~~~~~~~~~~ + +Creates a input to enter a **string**. Limit the number of characters +the user is allowed to enter with the ``max-length`` attribute. +(defaults: no character limit; default value: empty string) + +.. code:: xml + + <param name="name" type="string" gui-text="Some text label">Some default text</param> + +.. versionadded:: 1.0 + Set the attribute ``appearance="multiline"``\ to render a multi-line + input. Line-breaks will be encoded as literal ``\n`` in the value passed + to the extension. + +.. figure:: widgets/string.png + :alt: Rendering of string parameters + + Rendering of ``string`` parameters: default and + ``appearance="multiline"`` + + + +.. [#] https://en.cppreference.com/w/cpp/string/byte/strtoul
\ No newline at end of file diff --git a/share/extensions/docs/authors/samples/Comparison_of_Lighter_extension_in_Inkscape_1.1.2_and_1.2.png b/share/extensions/docs/authors/samples/Comparison_of_Lighter_extension_in_Inkscape_1.1.2_and_1.2.png Binary files differnew file mode 100644 index 0000000..2d16fde --- /dev/null +++ b/share/extensions/docs/authors/samples/Comparison_of_Lighter_extension_in_Inkscape_1.1.2_and_1.2.png diff --git a/share/extensions/docs/authors/samples/unit_camera.svg b/share/extensions/docs/authors/samples/unit_camera.svg new file mode 100644 index 0000000..3a4bad4 --- /dev/null +++ b/share/extensions/docs/authors/samples/unit_camera.svg @@ -0,0 +1,730 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + width="100%" + height="" + viewBox="0 0 88.540985 36.87265" + version="1.1" + id="svg5" + inkscape:version="1.1-rc (52f87abb86, 2021-05-02)" + sodipodi:docname="unit_camera.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"> + <sodipodi:namedview + id="namedview7" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + objecttolerance="10.0" + gridtolerance="10.0" + guidetolerance="10.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:document-units="mm" + showgrid="false" + inkscape:zoom="2.7758979" + inkscape:cx="109.15387" + inkscape:cy="106.0918" + inkscape:window-width="2560" + inkscape:window-height="1377" + inkscape:window-x="1912" + inkscape:window-y="-8" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" + inkscape:snap-global="false" /> + <defs + id="defs2"> + <inkscape:path-effect + effect="perspective-envelope" + up_left_point="55.388344,10.223442" + up_right_point="71.623721,6.7765038" + down_left_point="55.388345,11.235241" + down_right_point="71.585933,7.7847094" + id="path-effect86769" + is_visible="true" + lpeversion="1" + deform_type="perspective" + horizontal_mirror="false" + vertical_mirror="false" + overflow_perspective="false" /> + <inkscape:path-effect + effect="perspective-envelope" + up_left_point="55.388344,10.223442" + up_right_point="71.623721,6.7765038" + down_left_point="55.388345,11.235241" + down_right_point="71.585933,7.7847094" + id="path-effect86166" + is_visible="true" + lpeversion="1" + deform_type="perspective" + horizontal_mirror="false" + vertical_mirror="false" + overflow_perspective="false" /> + <inkscape:path-effect + effect="perspective-envelope" + up_left_point="103.97511,-48.861284" + up_right_point="129.93311,-55.491011" + down_left_point="103.97412,-34.49448" + down_right_point="129.91676,-29.638231" + id="path-effect42857" + is_visible="true" + lpeversion="1" + deform_type="perspective" + horizontal_mirror="false" + vertical_mirror="false" + overflow_perspective="false" /> + <inkscape:path-effect + effect="perspective-envelope" + up_left_point="88.96005,-78.828685" + up_right_point="184.40196,-78.828685" + down_left_point="88.96005,-11.910725" + down_right_point="184.40196,-11.910725" + id="path-effect33952" + is_visible="true" + lpeversion="1" + deform_type="perspective" + horizontal_mirror="false" + vertical_mirror="false" + overflow_perspective="false" /> + <inkscape:path-effect + effect="perspective-envelope" + up_left_point="-61.0625,14.673828" + up_right_point="24.9375,14.673828" + down_left_point="-61.0625,72.673828" + down_right_point="24.9375,72.673828" + id="path-effect33902" + is_visible="true" + lpeversion="1" + deform_type="perspective" + horizontal_mirror="false" + vertical_mirror="false" + overflow_perspective="false" /> + <inkscape:path-effect + effect="perspective-envelope" + up_left_point="-61.0625,14.673828" + up_right_point="24.9375,14.673828" + down_left_point="-61.0625,72.673828" + down_right_point="24.9375,72.673828" + id="path-effect33670" + is_visible="true" + lpeversion="1" + deform_type="perspective" + horizontal_mirror="false" + vertical_mirror="false" + overflow_perspective="false" /> + <inkscape:path-effect + effect="ruler" + id="path-effect18116" + is_visible="true" + lpeversion="1" + unit="px" + mark_distance="20" + mark_length="14" + minor_mark_length="7" + major_mark_steps="5" + shift="0" + offset="0" + mark_dir="right" + border_marks="start" /> + <inkscape:path-effect + effect="ruler" + id="path-effect17993" + is_visible="true" + lpeversion="1" + unit="mm" + mark_distance="5" + mark_length="4" + minor_mark_length="2" + major_mark_steps="5" + shift="0" + offset="0" + mark_dir="left" + border_marks="start" /> + </defs> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-1.3110192,-2.5216988)"> + <path + style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 40.413349,23.352054 c 0,0 3.22081,-0.291276 -0.285943,0.04766 -3.316515,0.320549 -6.266696,3.267676 -5.146982,7.339218 0.910043,5.922045 -6.520039,8.024653 -9.674423,4.241495 -1.206381,-1.516856 -0.762516,-4.289155 -0.762516,-4.289155" + id="path63878" + sodipodi:nodetypes="csccc" /> + <path + id="rect60611" + style="fill:#666666;stroke:none;stroke-width:1.05696;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" + d="m 9.4252039,14.014133 c -0.965052,0 -1.742011,0.776446 -1.742011,1.741495 v 13.500468 c 0,0.965049 0.776959,1.742011 1.742011,1.742011 h 9.6562601 v 1.175639 h -2.325442 c -0.295359,0 -0.53368,0.235119 -0.538985,0.529167 -5.8e-5,0.0033 0,0.0065 0,0.0098 v 0.212391 0.562756 h 7.683254 v -0.562756 -0.212391 -0.0098 h -5.29e-4 c -0.0053,-0.294043 -0.243626,-0.529167 -0.538986,-0.529167 h -2.324922 v -1.175639 h 9.655743 c 0.965047,0 1.742012,-0.776962 1.742012,-1.742011 V 15.755628 c 0,-0.965049 -0.776965,-1.741495 -1.742012,-1.741495 z m -0.646472,0.972034 H 31.337562 v 15.03939 H 8.7787319 Z" + sodipodi:nodetypes="ssssccssscccccccsccsssssccccc" /> + <path + style="fill:#e6e6e6;stroke:none;stroke-width:0.261809px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 89.828264,39.39435 46.165216,30.524921 V 12.251262 L 89.852005,2.5216988 Z" + id="path5100" + sodipodi:nodetypes="ccccc" /> + <g + id="g42514" + transform="translate(-50.952535,62.00573)" + inkscape:path-effect="#path-effect42857"> + <path + style="color:#000000;fill:#000000;-inkscape-stroke:none" + d="m 105.83084,-48.317847 -10e-5,0.901053 0.0166,-0.0033 0,0.02245 23.66904,-4.70646 5e-5,-0.07586 -1.79911,0.360095 4.1e-4,-0.70118 -0.0889,0.0189 -4.1e-4,0.700071 -2.06041,0.412397 7.4e-4,-1.384086 -0.0822,0.01857 -7.4e-4,1.38198 -1.90875,0.38204 3.2e-4,-0.649514 -0.0763,0.01622 -3.2e-4,0.648562 -1.77323,0.354916 2.8e-4,-0.626434 -0.071,0.01509 -2.8e-4,0.625549 -1.65165,0.330582 2.5e-4,-0.60494 -0.0662,0.01407 -2.5e-4,0.604113 -1.54216,0.308667 2.2e-4,-0.58487 -0.0619,0.01316 -2.2e-4,0.584098 -1.44321,0.288862 4.1e-4,-1.161867 -0.058,0.01309 -4.1e-4,1.160382 -1.35348,0.270902 1.7e-4,-0.548478 -0.0544,0.01157 -1.7e-4,0.547799 -1.27188,0.254569 1.6e-4,-0.53193 -0.0512,0.01089 -1.6e-4,0.53129 -1.19743,0.239669 1.4e-4,-0.51635 -0.0482,0.01026 -1.3e-4,0.515747 -1.12934,0.226039 1.2e-4,-0.501656 -0.0455,0.0097 -1.1e-4,0.501089 -1.06689,0.21354 2.1e-4,-1.001131 -0.043,0.0097 -2.1e-4,1.000029 -1.00949,0.20205 9e-5,-0.474644 -0.0408,0.0087 -9e-5,0.474135 -0.95659,0.191464 8e-5,-0.462201 -0.0387,0.0082 -8e-5,0.461718 -0.90774,0.181687 6e-5,-0.450392 -0.0367,0.0078 -7e-5,0.449934 -0.86255,0.172642 6e-5,-0.439173 -0.0349,0.0074 -5e-5,0.438738 -0.82065,0.164254 9e-5,-0.879465 z" + id="path17823-0-5" + inkscape:original-d="m 99.4375,-74.835937 v 4 h 0.09961 v 0.09961 h 84 v -0.199219 h -3.90039 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -3.90039 h -0.19922 v 3.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -3.90039 h -0.19922 v 3.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -3.90039 h -0.19922 v 3.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -3.90039 z" /> + <path + style="color:#000000;fill:#000000;-inkscape-stroke:none" + d="m 104.88783,-46.799546 0,0.04407 0.57805,-0.107124 -1.2e-4,1.134724 -0.28335,0.04304 -1e-5,0.04402 0.28336,-0.04267 -1.2e-4,1.134666 -0.28335,0.0332 0,0.04402 0.28335,-0.03283 -1.2e-4,1.134608 -0.28334,0.02336 0,0.04445 0.28334,-0.02299 -1.2e-4,1.134551 -0.28333,0.01352 0,0.04402 0.28333,-0.01315 -1.2e-4,1.134492 -0.57796,0.0075 -1e-5,0.04363 0.57797,-0.0068 -1.2e-4,1.134434 -0.28331,-0.0062 0,0.04445 0.28331,0.0065 -1.1e-4,1.134375 -0.28331,-0.016 -1e-5,0.04401 0.28331,0.01637 -1.1e-4,1.134318 -0.2833,-0.02583 -1e-5,0.04401 0.2833,0.0262 -1.1e-4,1.13426 -0.28329,-0.03567 -1e-5,0.04444 0.28329,0.03604 -1.1e-4,1.134202 -0.57789,-0.09283 0,0.04362 0.57788,0.09358 -6e-5,0.664744 0.0325,0.0059 0.001,-12.488681 -0.0163,0.003 1e-5,-0.02264 z" + id="path17825-0-7" + inkscape:original-d="m 93.619141,-68.876953 v 0.201172 h 3.605468 v 5.091797 h -1.751953 v 0.199218 h 1.751953 v 5.091797 h -1.751953 v 0.199219 h 1.751953 v 5.091797 h -1.751953 v 0.201172 h 1.751953 v 5.091797 h -1.751953 v 0.199218 h 1.751953 v 5.091797 h -3.605468 v 0.199219 h 3.605468 v 5.091797 h -1.751953 v 0.201172 h 1.751953 v 5.091797 h -1.751953 v 0.199218 h 1.751953 v 5.091797 h -1.751953 v 0.199219 h 1.751953 v 5.091797 h -1.751953 v 0.201172 h 1.751953 v 5.091797 h -3.605468 v 0.199218 h 3.605468 v 2.984375 h 0.199219 v -56 h -0.09961 v -0.101562 z" /> + <g + id="g33047-4" + transform="translate(159.46446,-84.584553)"> + <path + style="color:#000000;fill:#ff7f2a;-inkscape-stroke:none" + d="m -53.805432,37.409378 -2.4e-5,0.224128 -0.0013,12.771711 24.259103,4.541105 0.01406,-22.231722 z m 0.333098,0.388189 22.988231,-4.14472 -0.01246,20.361969 -22.97715,-3.999636 z" + id="rect17821-2" + inkscape:original-d="m -61.0625,14.673828 v 1 57 h 86 v -58 z m 2,2 h 82 v 54 h -82 z" /> + <path + style="color:#000000;fill:#000000;-inkscape-stroke:none" + d="m -53.640032,40.732902 -5e-6,0.04486 23.62393,-2.228172 4.7e-5,-0.07575 z" + id="path17823-5" + inkscape:original-d="m -60.0625,29.574219 v 0.199218 h 84 v -0.199218 z" /> + <path + style="color:#000000;fill:#000000;-inkscape-stroke:none" + d="m -49.765187,36.878536 -0.0027,14.032224 0.04113,0.0074 0.0027,-14.047342 z" + id="path17825-5" + inkscape:original-d="m -39.162109,15.673828 v 56 h 0.199218 v -56 z" /> + <path + style="color:#000000;fill:#ff0000;-inkscape-stroke:none" + d="m -49.745196,39.82125 c -0.254313,0.02791 -0.459131,0.300677 -0.459187,0.607791 -5.6e-5,0.30711 0.204663,0.540975 0.458969,0.520578 0.257737,-0.02067 0.470427,-0.294178 0.470491,-0.608851 6.5e-5,-0.314677 -0.212528,-0.547802 -0.470273,-0.519518 z m -2.4e-5,0.125377 c 0.201266,-0.02143 0.364819,0.15875 0.36477,0.404163 -5e-5,0.245411 -0.163679,0.456655 -0.36494,0.473457 -0.199163,0.01663 -0.357976,-0.163993 -0.357932,-0.404804 4.5e-5,-0.240813 0.158934,-0.451613 0.358102,-0.472816 z" + id="c1-4-4" + inkscape:original-d="m -39.0625,27.423828 c -1.239678,0 -2.25,1.010322 -2.25,2.25 0,1.239678 1.010322,2.25 2.25,2.25 1.239678,0 2.25,-1.010322 2.25,-2.25 0,-1.239678 -1.010322,-2.25 -2.25,-2.25 z m 0,0.5 c 0.969459,0 1.75,0.780542 1.75,1.75 0,0.969459 -0.780541,1.75 -1.75,1.75 -0.969459,0 -1.75,-0.780541 -1.75,-1.75 0,-0.969458 0.780541,-1.75 1.75,-1.75 z" /> + <path + style="color:#000000;fill:#008000;-inkscape-stroke:none" + d="m -49.745099,39.319735 c -0.47808,0.05874 -0.858089,0.572569 -0.858189,1.147191 -1.01e-4,0.574608 0.379723,1.01624 0.857777,0.984172 0.490324,-0.03289 0.898409,-0.549342 0.898538,-1.150973 1.28e-4,-0.601647 -0.407773,-1.040637 -0.898126,-0.98039 z m -2.4e-5,0.12538 c 0.433188,-0.0518 0.790389,0.334429 0.790277,0.865255 -1.12e-4,0.530814 -0.357476,0.984882 -0.790641,1.015359 -0.423561,0.0298 -0.758958,-0.358479 -0.758867,-0.868199 9e-5,-0.509732 0.335649,-0.961761 0.759231,-1.012415 z" + id="c2-6-1" + inkscape:original-d="m -39.0625,25.423828 c -2.344247,0 -4.25,1.905753 -4.25,4.25 0,2.344247 1.905753,4.25 4.25,4.25 2.344247,0 4.25,-1.905753 4.25,-4.25 0,-2.344247 -1.905753,-4.25 -4.25,-4.25 z m 0,0.5 c 2.074027,0 3.75,1.675973 3.75,3.75 0,2.074027 -1.675973,3.75 -3.75,3.75 -2.074027,0 -3.75,-1.675973 -3.75,-3.75 0,-2.074027 1.675973,-3.75 3.75,-3.75 z" /> + <path + style="color:#000000;fill:#0000ff;-inkscape-stroke:none" + d="m -32.142378,51.926152 c -0.676533,-0.09592 -1.221569,0.28581 -1.221875,0.842436 -3.06e-4,0.556613 0.54419,1.112345 1.220679,1.233422 0.693297,0.124084 1.278322,-0.250472 1.278674,-0.832565 3.51e-4,-0.582108 -0.584135,-1.144993 -1.277478,-1.243293 z m -3.99e-4,0.692211 c 0.235841,0.03636 0.419534,0.216778 0.419419,0.413399 -1.15e-4,0.19662 -0.183982,0.317361 -0.419817,0.278077 -0.233859,-0.03895 -0.412465,-0.217834 -0.412355,-0.411545 1.09e-4,-0.193711 0.178889,-0.315988 0.412753,-0.279931 z" + id="c3-2-7" + inkscape:original-d="m 19.306641,65.751953 c -1.554338,0 -2.833984,1.2816 -2.833985,2.835938 0,1.554338 1.279646,2.833984 2.833985,2.833984 1.554338,0 2.835937,-1.279646 2.835937,-2.833984 -1e-6,-1.554338 -1.281599,-2.835938 -2.835937,-2.835938 z m 0,1.890625 c 0.533035,0 0.945312,0.412278 0.945312,0.945313 0,0.533035 -0.412277,0.943359 -0.945312,0.943359 -0.533036,0 -0.94336,-0.410324 -0.94336,-0.943359 0,-0.533035 0.410325,-0.945313 0.94336,-0.945313 z" /> + </g> + <g + aria-label="25" + id="text20650-4" + style="font-size:4.23333px;line-height:125%;-inkscape-font-specification:sans-serif;stroke-width:0.499999;stroke-linecap:round;stroke-linejoin:round"> + <path + d="m 110.36984,-49.782749 0.31384,-0.0744 -2e-5,0.09036 -0.42084,0.0988 10e-6,-0.08939 c 0.0337,-0.04974 0.0797,-0.116709 0.13799,-0.201033 0.0588,-0.085 0.0958,-0.139671 0.11091,-0.163827 0.0288,-0.04553 0.0489,-0.08296 0.0602,-0.112251 0.0116,-0.02973 0.0174,-0.05751 0.0174,-0.08331 1e-5,-0.04207 -0.0125,-0.07321 -0.0375,-0.09342 -0.0246,-0.02026 -0.0568,-0.02535 -0.0965,-0.01531 -0.0281,0.0071 -0.0577,0.02041 -0.089,0.03991 -0.0309,0.01939 -0.0639,0.04527 -0.0991,0.07762 l 2e-5,-0.107278 c 0.0358,-0.02628 0.0692,-0.04779 0.10042,-0.06453 0.0312,-0.01676 0.0598,-0.02847 0.0859,-0.03511 0.0687,-0.01755 0.12368,-0.01109 0.16477,0.01947 0.0412,0.03062 0.0618,0.08033 0.0618,0.149065 -1e-5,0.0326 -0.005,0.0649 -0.0157,0.09689 -0.0102,0.03155 -0.0288,0.07048 -0.056,0.116752 -0.007,0.01208 -0.0311,0.04754 -0.071,0.106316 -0.0398,0.0583 -0.0957,0.139925 -0.16768,0.244672 z" + style="stroke-width:0.5" + id="path42200" + inkscape:original-d="m 123.49461,-76.561811 h 1.45728 v 0.3514 h -1.95957 v -0.3514 q 0.23771,-0.24598 0.64699,-0.659391 0.41134,-0.415479 0.51676,-0.535368 0.2005,-0.225309 0.27905,-0.380338 0.0806,-0.157097 0.0806,-0.307992 0,-0.24598 -0.17363,-0.401009 -0.17157,-0.155029 -0.44856,-0.155029 -0.19637,0 -0.41547,0.06821 -0.21705,0.06821 -0.46509,0.206705 v -0.421679 q 0.25218,-0.101286 0.47129,-0.152963 0.2191,-0.05168 0.40101,-0.05168 0.47955,0 0.76481,0.239779 0.28525,0.239778 0.28525,0.640787 0,0.19017 -0.0724,0.361735 -0.0703,0.169499 -0.25838,0.401009 -0.0517,0.05994 -0.32866,0.347266 -0.27699,0.285254 -0.78135,0.799951 z" /> + <path + d="m 110.87593,-50.609346 0.36268,-0.09249 -2e-5,0.09164 -0.27866,0.07043 -4e-5,0.195909 c 0.0133,-0.0087 0.0267,-0.0159 0.0401,-0.02172 0.0134,-0.0062 0.0268,-0.01093 0.0402,-0.01426 0.0763,-0.01894 0.13695,-0.0094 0.18177,0.0287 0.0449,0.0382 0.0674,0.09943 0.0674,0.18363 -2e-5,0.08672 -0.0232,0.159672 -0.0693,0.218764 -0.0461,0.0586 -0.11084,0.09763 -0.19412,0.117153 -0.0286,0.0067 -0.0577,0.01068 -0.0875,0.01194 -0.0294,0.0012 -0.0598,-2.22e-4 -0.0911,-0.0042 l 2e-5,-0.108347 c 0.0272,0.01098 0.0553,0.01731 0.0843,0.01897 0.0291,0.0017 0.0599,-0.0013 0.0925,-0.009 0.0527,-0.01248 0.0946,-0.03869 0.12551,-0.07865 0.031,-0.04002 0.0465,-0.08805 0.0465,-0.144056 10e-6,-0.056 -0.0155,-0.09656 -0.0464,-0.121636 -0.0309,-0.02504 -0.0728,-0.03105 -0.12549,-0.01809 -0.0246,0.0061 -0.0493,0.01532 -0.0738,0.02779 -0.0242,0.01237 -0.0491,0.02844 -0.0745,0.0482 z" + style="stroke-width:0.5" + id="path42202" + inkscape:original-d="m 125.83245,-79.296527 h 1.63918 v 0.351399 h -1.25677 v 0.756543 q 0.0909,-0.03101 0.1819,-0.04547 0.091,-0.01654 0.1819,-0.01654 0.51677,0 0.81856,0.283187 0.30179,0.283187 0.30179,0.766879 0,0.49816 -0.31006,0.775146 -0.31006,0.274919 -0.87437,0.274919 -0.1943,0 -0.39687,-0.03307 -0.20051,-0.03307 -0.41548,-0.09922 v -0.419613 q 0.18603,0.101286 0.38447,0.150895 0.19844,0.04961 0.41961,0.04961 0.35761,0 0.56638,-0.188102 0.20877,-0.188103 0.20877,-0.510563 0,-0.322461 -0.20877,-0.510564 -0.20877,-0.188102 -0.56638,-0.188102 -0.16743,0 -0.33486,0.03721 -0.16536,0.03721 -0.339,0.115755 z" /> + </g> + <g + aria-label="25" + id="text20650-0-4" + style="font-size:4.23333px;line-height:125%;-inkscape-font-specification:sans-serif;stroke-width:0.499999;stroke-linecap:round;stroke-linejoin:round"> + <path + d="m 104.04959,-40.644937 0.21972,-5.01e-4 0,0.07553 -0.29477,-7e-6 0,-0.07485 c 0.0236,-0.03501 0.0559,-0.08202 0.0968,-0.1411 0.0412,-0.05953 0.0671,-0.09795 0.0777,-0.115169 0.0202,-0.03239 0.0342,-0.05973 0.0421,-0.08199 0.008,-0.02257 0.0122,-0.04464 0.0122,-0.06622 0,-0.03518 -0.009,-0.06371 -0.0262,-0.08557 -0.0172,-0.02184 -0.0398,-0.0325 -0.0676,-0.032 -0.0197,3.6e-4 -0.0404,0.0056 -0.0623,0.0157 -0.0217,0.01009 -0.0448,0.02518 -0.0695,0.04528 l 0,-0.08984 c 0.0251,-0.01488 0.0486,-0.02622 0.0704,-0.03401 0.0219,-0.0078 0.0419,-0.0119 0.0602,-0.01227 0.0481,-9.92e-4 0.0866,0.01536 0.11536,0.04909 0.0288,0.0338 0.0432,0.07945 0.0432,0.136907 0,0.02725 -0.004,0.05322 -0.011,0.07789 -0.007,0.02436 -0.0202,0.05322 -0.0391,0.08655 -0.005,0.0086 -0.0218,0.03361 -0.0497,0.0749 -0.0278,0.04093 -0.067,0.09819 -0.11745,0.171682 z" + style="stroke-width:0.5" + id="path42205" + inkscape:original-d="m 88.166067,-40.786962 h 1.457274 v 0.3514 h -1.959569 v -0.3514 q 0.237712,-0.245979 0.646989,-0.65939 0.411344,-0.415478 0.516764,-0.535368 0.200504,-0.225309 0.279052,-0.380338 0.08061,-0.157096 0.08061,-0.307991 0,-0.24598 -0.173632,-0.401009 -0.171566,-0.155029 -0.448551,-0.155029 -0.196371,0 -0.415479,0.06821 -0.21704,0.06821 -0.465087,0.206705 v -0.421679 q 0.252181,-0.101286 0.471289,-0.152962 0.219107,-0.05168 0.401008,-0.05168 0.479557,0 0.764811,0.239779 0.285254,0.239778 0.285254,0.640787 0,0.190169 -0.07235,0.361735 -0.07028,0.169498 -0.258382,0.401009 -0.05168,0.05994 -0.328662,0.347265 -0.276986,0.285254 -0.781347,0.79995 z" /> + <path + d="m 104.40357,-41.235989 0.25279,-0.0051 -1e-5,0.07643 -0.19416,0.0035 -1e-5,0.16358 c 0.009,-0.0046 0.0186,-0.008 0.028,-0.0102 0.009,-0.0025 0.0187,-0.0038 0.028,-0.004 0.0532,-7.11e-4 0.0954,0.01923 0.12662,0.05988 0.0313,0.04073 0.0469,0.09622 0.0469,0.166427 -10e-6,0.07231 -0.0161,0.128605 -0.0482,0.168834 -0.0321,0.03985 -0.0772,0.05974 -0.13522,0.05971 -0.0199,-8e-6 -0.0403,-0.0024 -0.061,-0.0072 -0.0205,-0.0048 -0.0417,-0.01191 -0.0636,-0.02142 l 1e-5,-0.09051 c 0.019,0.01451 0.0386,0.02532 0.0589,0.03242 0.0203,0.0071 0.0418,0.01064 0.0645,0.0106 0.0368,-6.9e-5 0.0659,-0.01373 0.0875,-0.041 0.0216,-0.02731 0.0324,-0.06433 0.0324,-0.111045 1e-5,-0.04671 -0.0108,-0.0836 -0.0323,-0.110626 -0.0215,-0.02699 -0.0507,-0.04027 -0.0874,-0.03987 -0.0172,1.9e-4 -0.0344,0.0031 -0.0515,0.0086 -0.0169,0.0055 -0.0342,0.01406 -0.052,0.02555 z" + style="stroke-width:0.5" + id="path42207" + inkscape:original-d="m 90.503907,-43.521676 h 1.639175 v 0.351399 h -1.25677 v 0.756543 q 0.09095,-0.03101 0.181901,-0.04548 0.09095,-0.01654 0.181901,-0.01654 0.516764,0 0.818554,0.283187 0.30179,0.283186 0.30179,0.766877 0,0.498161 -0.310058,0.775146 -0.310059,0.274918 -0.874365,0.274918 -0.194303,0 -0.396875,-0.03307 -0.200504,-0.03307 -0.415478,-0.09922 v -0.419612 q 0.186035,0.101285 0.384473,0.150895 0.198437,0.04961 0.419612,0.04961 0.3576,0 0.566373,-0.188102 0.208773,-0.188102 0.208773,-0.510563 0,-0.32246 -0.208773,-0.510562 -0.208773,-0.188103 -0.566373,-0.188103 -0.167432,0 -0.334863,0.03721 -0.165365,0.03721 -0.338997,0.115756 z" /> + </g> + <g + aria-label="50" + id="text25354-6" + style="font-size:4.23333px;line-height:125%;-inkscape-font-specification:sans-serif;stroke-width:0.499999;stroke-linecap:round;stroke-linejoin:round"> + <path + d="m 116.36044,-51.993208 0.47138,-0.120064 -3e-5,0.104546 -0.3623,0.09144 -7e-5,0.223278 c 0.0173,-0.01039 0.0347,-0.01917 0.0521,-0.02632 0.0174,-0.0076 0.0348,-0.01351 0.0522,-0.01782 0.0992,-0.02458 0.17806,-0.0161 0.23637,0.02562 0.0585,0.04183 0.0877,0.110817 0.0877,0.20689 -4e-5,0.09895 -0.0302,0.183065 -0.0903,0.252216 -0.0599,0.06856 -0.14417,0.115482 -0.25242,0.140819 -0.0372,0.0087 -0.075,0.01431 -0.11364,0.01684 -0.0381,0.0024 -0.0776,0.0019 -0.11834,-0.0015 l 4e-5,-0.123434 c 0.0353,0.0115 0.0718,0.01766 0.10948,0.01847 0.0378,8.14e-4 0.0778,-0.0038 0.12012,-0.01376 0.0685,-0.0162 0.12295,-0.04765 0.16317,-0.09438 0.0403,-0.04681 0.0605,-0.102192 0.0605,-0.16607 2e-5,-0.06388 -0.0201,-0.109538 -0.0604,-0.136944 -0.0402,-0.02736 -0.0946,-0.03259 -0.16313,-0.01576 -0.032,0.0079 -0.064,0.01937 -0.0959,0.03453 -0.0315,0.01504 -0.0637,0.03431 -0.0967,0.05779 z" + style="stroke-width:0.5" + id="path42210" + inkscape:original-d="m 147.78972,-79.245975 h 1.63918 v 0.3514 h -1.25677 v 0.756543 q 0.0909,-0.03101 0.1819,-0.04548 0.0909,-0.01654 0.1819,-0.01654 0.51676,0 0.81855,0.283187 0.30179,0.283187 0.30179,0.766878 0,0.498161 -0.31006,0.775146 -0.31005,0.274919 -0.87436,0.274919 -0.1943,0 -0.39688,-0.03307 -0.2005,-0.03307 -0.41547,-0.09922 v -0.419612 q 0.18603,0.101285 0.38447,0.150895 0.19844,0.04961 0.41961,0.04961 0.3576,0 0.56637,-0.188102 0.20878,-0.188102 0.20878,-0.510563 0,-0.322461 -0.20878,-0.510563 -0.20877,-0.188102 -0.56637,-0.188102 -0.16743,0 -0.33486,0.03721 -0.16537,0.03721 -0.339,0.115755 z" /> + <path + d="m 117.40356,-52.176079 c -0.064,0.01618 -0.11204,0.06022 -0.14432,0.13209 -0.0318,0.07125 -0.0478,0.170506 -0.0478,0.297837 -4e-5,0.126917 0.0158,0.2184 0.0476,0.274508 0.0322,0.05567 0.0803,0.076 0.14425,0.06089 0.0646,-0.01525 0.11301,-0.05853 0.14524,-0.129877 0.0327,-0.07196 0.0491,-0.17198 0.0491,-0.29997 5e-5,-0.128407 -0.0163,-0.220427 -0.0489,-0.275998 -0.0322,-0.05601 -0.0806,-0.07581 -0.14517,-0.05948 z m 4e-5,-0.09964 c 0.10329,-0.02635 0.1824,-0.0051 0.23707,0.06408 0.0552,0.06878 0.0828,0.182246 0.0828,0.340268 -6e-5,0.157602 -0.0278,0.284599 -0.0831,0.380817 -0.0547,0.09547 -0.13387,0.155255 -0.23716,0.179431 -0.10283,0.02407 -0.18117,0.0015 -0.23526,-0.06759 -0.0536,-0.06941 -0.0803,-0.181767 -0.0802,-0.337201 5e-5,-0.155847 0.0268,-0.28129 0.0805,-0.376496 0.0541,-0.09595 0.13251,-0.157078 0.23535,-0.183309 z" + style="stroke-width:0.5" + id="path42212" + inkscape:original-d="m 151.37193,-78.971056 q -0.32246,0 -0.48576,0.318326 -0.16123,0.31626 -0.16123,0.952914 0,0.634586 0.16123,0.952913 0.1633,0.31626 0.48576,0.31626 0.32453,0 0.48576,-0.31626 0.1633,-0.318327 0.1633,-0.952913 0,-0.636654 -0.1633,-0.952914 -0.16123,-0.318326 -0.48576,-0.318326 z m 0,-0.33073 q 0.51883,0 0.79168,0.411345 0.27492,0.409277 0.27492,1.190625 0,0.77928 -0.27492,1.190625 -0.27285,0.409277 -0.79168,0.409277 -0.51883,0 -0.79375,-0.409277 -0.27285,-0.411345 -0.27285,-1.190625 0,-0.781348 0.27285,-1.190625 0.27492,-0.411345 0.79375,-0.411345 z" /> + </g> + <g + aria-label="50" + id="text25354-5-4" + style="font-size:4.23333px;line-height:125%;-inkscape-font-specification:sans-serif;stroke-width:0.499999;stroke-linecap:round;stroke-linejoin:round"> + <path + d="m 103.99959,-35.624845 0.24657,0.03754 -1e-5,0.07546 -0.18937,-0.02927 -1e-5,0.16153 c 0.009,-0.003 0.0182,-0.0048 0.0273,-0.0054 0.009,-9.08e-4 0.0182,-6.37e-4 0.0273,8.12e-4 0.0519,0.0083 0.0931,0.03505 0.1235,0.08045 0.0305,0.04548 0.0458,0.102907 0.0458,0.172228 0,0.0714 -0.0157,0.124276 -0.047,0.158593 -0.0313,0.03395 -0.0753,0.046 -0.13189,0.03621 -0.0194,-0.0034 -0.0393,-0.0091 -0.0595,-0.01735 -0.02,-0.0082 -0.0407,-0.01877 -0.0621,-0.03185 l 1e-5,-0.08938 c 0.0185,0.01752 0.0376,0.0315 0.0574,0.04192 0.0198,0.01043 0.0408,0.01754 0.0629,0.02132 0.0358,0.0061 0.0643,-0.0025 0.0853,-0.02577 0.021,-0.02334 0.0316,-0.05808 0.0316,-0.104203 0,-0.04612 -0.0105,-0.08436 -0.0316,-0.114679 -0.021,-0.03028 -0.0494,-0.0483 -0.0853,-0.05409 -0.0168,-0.0027 -0.0335,-0.0028 -0.0502,-1.64e-4 -0.0165,0.0026 -0.0334,0.0081 -0.0507,0.01648 z" + style="stroke-width:0.5" + id="path42215" + inkscape:original-d="m 87.834017,-17.236643 h 1.639175 v 0.3514 h -1.25677 v 0.756542 q 0.09095,-0.03101 0.181901,-0.04547 0.09095,-0.01654 0.181901,-0.01654 0.516763,0 0.818554,0.283187 0.30179,0.283186 0.30179,0.766877 0,0.498161 -0.310059,0.775146 -0.310058,0.274919 -0.874364,0.274919 -0.194303,0 -0.396875,-0.03307 -0.200504,-0.03307 -0.415478,-0.09922 v -0.419612 q 0.186035,0.101286 0.384472,0.150895 0.198438,0.04961 0.419613,0.04961 0.3576,0 0.566373,-0.188102 0.208772,-0.188102 0.208772,-0.510563 0,-0.32246 -0.208772,-0.510562 -0.208773,-0.188102 -0.566373,-0.188102 -0.167432,0 -0.334863,0.03721 -0.165365,0.03721 -0.338997,0.115755 z" /> + <path + d="m 104.54332,-35.482488 c -0.0331,-0.0051 -0.0581,0.01401 -0.0748,0.0573 -0.0165,0.04299 -0.0248,0.110312 -0.0248,0.20201 -10e-6,0.0914 0.008,0.161404 0.0247,0.210048 0.0167,0.04843 0.0417,0.07549 0.0748,0.08115 0.0334,0.0057 0.0585,-0.0129 0.0751,-0.05586 0.0169,-0.04327 0.0254,-0.110895 0.0254,-0.20285 0,-0.09226 -0.008,-0.162628 -0.0253,-0.211082 -0.0166,-0.04867 -0.0417,-0.07556 -0.0751,-0.08071 z m 0,-0.07167 c 0.0535,0.0081 0.0944,0.04413 0.12263,0.108096 0.0285,0.06381 0.0428,0.152474 0.0428,0.265918 -1e-5,0.113144 -0.0143,0.197172 -0.0428,0.252015 -0.0283,0.05449 -0.0692,0.07706 -0.12263,0.06782 -0.0533,-0.0092 -0.0939,-0.04572 -0.12204,-0.109461 -0.0278,-0.06389 -0.0417,-0.151811 -0.0417,-0.263833 1e-5,-0.112319 0.0139,-0.195722 0.0418,-0.250278 0.0281,-0.05491 0.0688,-0.07837 0.12205,-0.07027 z" + style="stroke-width:0.5" + id="path42217" + inkscape:original-d="m 91.416224,-16.961724 q -0.322461,0 -0.485758,0.318326 -0.161231,0.31626 -0.161231,0.952913 0,0.634586 0.161231,0.952912 0.163297,0.31626 0.485758,0.31626 0.324528,0 0.485758,-0.31626 0.163297,-0.318326 0.163297,-0.952912 0,-0.636653 -0.163297,-0.952913 -0.16123,-0.318326 -0.485758,-0.318326 z m 0,-0.330729 q 0.518831,0 0.791682,0.411344 0.274919,0.409277 0.274919,1.190624 0,0.77928 -0.274919,1.190624 -0.272851,0.409277 -0.791682,0.409277 -0.518831,0 -0.793749,-0.409277 -0.272852,-0.411344 -0.272852,-1.190624 0,-0.781347 0.272852,-1.190624 0.274918,-0.411344 0.793749,-0.411344 z" /> + </g> + <g + aria-label="75" + id="text27250-9" + style="font-size:4.23333px;line-height:125%;-inkscape-font-specification:sans-serif;stroke-width:0.499999;stroke-linecap:round;stroke-linejoin:round"> + <path + d="m 124.66635,-54.08524 0.8053,-0.204756 -3e-5,0.06297 -0.45817,1.137339 -0.17606,0.0412 0.42805,-1.06509 -0.59915,0.15096 z" + style="stroke-width:0.5" + id="path42220" + inkscape:original-d="m 172.41506,-79.178577 h 1.98438 v 0.177767 l -1.12035,2.908349 h -0.43615 l 1.0542,-2.734716 h -1.48208 z" /> + <path + d="m 125.81099,-54.376276 0.69252,-0.176083 -7e-5,0.126864 -0.53253,0.134173 -1.4e-4,0.270483 c 0.0254,-0.01368 0.0509,-0.0254 0.0764,-0.03516 0.0255,-0.01026 0.0511,-0.01856 0.0767,-0.02488 0.14576,-0.03606 0.26174,-0.03075 0.34755,0.01618 0.0861,0.04708 0.12919,0.128984 0.12913,0.245604 -7e-5,0.120107 -0.0445,0.224044 -0.13297,0.311599 -0.0882,0.08678 -0.2121,0.148719 -0.37115,0.185876 -0.0546,0.01274 -0.11015,0.02179 -0.16679,0.02715 -0.056,0.0052 -0.11378,0.007 -0.1735,0.0052 l 8e-5,-0.149426 c 0.0517,0.01181 0.10516,0.01708 0.1605,0.01581 0.0555,-0.0013 0.11421,-0.0092 0.17629,-0.02387 0.10067,-0.02375 0.18067,-0.06516 0.23981,-0.124264 0.0593,-0.05923 0.089,-0.127641 0.089,-0.205135 4e-5,-0.07749 -0.0296,-0.131632 -0.0888,-0.162365 -0.0591,-0.03067 -0.13907,-0.03361 -0.23975,-0.0089 -0.047,0.01152 -0.0939,0.02746 -0.14079,0.0478 -0.0462,0.02017 -0.0935,0.0455 -0.1418,0.07598 z" + style="stroke-width:0.5" + id="path42222" + inkscape:original-d="m 175.21799,-79.178577 h 1.63918 v 0.3514 h -1.25677 v 0.756543 q 0.0909,-0.03101 0.1819,-0.04548 0.091,-0.01654 0.1819,-0.01654 0.51676,0 0.81855,0.283187 0.30179,0.283187 0.30179,0.766878 0,0.498161 -0.31006,0.775146 -0.31005,0.274919 -0.87436,0.274919 -0.1943,0 -0.39688,-0.03307 -0.2005,-0.03307 -0.41547,-0.09922 v -0.419612 q 0.18603,0.101286 0.38447,0.150895 0.19844,0.04961 0.41961,0.04961 0.3576,0 0.56637,-0.188102 0.20878,-0.188102 0.20878,-0.510563 0,-0.322461 -0.20878,-0.510563 -0.20877,-0.188102 -0.56637,-0.188102 -0.16743,0 -0.33486,0.03721 -0.16537,0.03721 -0.339,0.115755 z" /> + </g> + <g + aria-label="0" + id="text30700-8" + style="font-size:4.23333px;line-height:125%;-inkscape-font-specification:sans-serif;stroke-width:0.499999;stroke-linecap:round;stroke-linejoin:round"> + <path + d="m 105.91657,-49.25581 c -0.036,0.0091 -0.063,0.03982 -0.0812,0.09221 -0.0179,0.05196 -0.0269,0.125699 -0.0269,0.221251 -1e-5,0.09524 0.009,0.164609 0.0268,0.208138 0.0182,0.04321 0.0452,0.0606 0.0812,0.05212 0.0363,-0.0086 0.0635,-0.03881 0.0815,-0.09082 0.0183,-0.05242 0.0275,-0.126579 0.0275,-0.222424 10e-6,-0.09616 -0.009,-0.165835 -0.0275,-0.209 -0.0181,-0.04349 -0.0453,-0.06063 -0.0815,-0.05147 z m 1e-5,-0.07469 c 0.058,-0.01477 0.10242,0.005 0.13309,0.05937 0.0309,0.05411 0.0464,0.140334 0.0464,0.258586 -2e-5,0.117939 -0.0155,0.211725 -0.0465,0.281266 -0.0307,0.06905 -0.0751,0.110323 -0.13311,0.123878 -0.0578,0.01351 -0.10192,-0.0069 -0.1324,-0.06114 -0.0302,-0.0545 -0.0453,-0.140075 -0.0453,-0.256795 2e-5,-0.11703 0.0151,-0.209969 0.0453,-0.278906 0.0305,-0.06943 0.0746,-0.111533 0.13242,-0.126258 z" + style="stroke-width:0.5" + id="path42225" + inkscape:original-d="m 99.950146,-78.903658 q -0.322461,0 -0.485758,0.318326 -0.16123,0.31626 -0.16123,0.952914 0,0.634586 0.16123,0.952913 0.163297,0.31626 0.485758,0.31626 0.324524,0 0.485754,-0.31626 0.1633,-0.318327 0.1633,-0.952913 0,-0.636654 -0.1633,-0.952914 -0.16123,-0.318326 -0.485754,-0.318326 z m 0,-0.33073 q 0.518834,0 0.791684,0.411345 0.27492,0.409277 0.27492,1.190625 0,0.77928 -0.27492,1.190625 -0.27285,0.409277 -0.791684,0.409277 -0.518831,0 -0.79375,-0.409277 -0.272851,-0.411345 -0.272851,-1.190625 0,-0.781348 0.272851,-1.190625 0.274919,-0.411345 0.79375,-0.411345 z" /> + </g> + <g + aria-label="0" + id="text30700-1-3" + style="font-size:4.23333px;line-height:125%;-inkscape-font-specification:sans-serif;stroke-width:0.499999;stroke-linecap:round;stroke-linejoin:round"> + <path + d="m 104.46105,-46.978113 c -0.033,0.0064 -0.0578,0.03415 -0.0744,0.08316 -0.0164,0.04863 -0.0246,0.118686 -0.0247,0.2102 0,0.09122 0.008,0.158214 0.0246,0.201027 0.0166,0.04252 0.0414,0.06087 0.0744,0.055 0.0333,-0.0059 0.0582,-0.03319 0.0748,-0.08184 0.0168,-0.04904 0.0252,-0.11947 0.0252,-0.211239 0,-0.09207 -0.008,-0.159364 -0.0252,-0.201855 -0.0166,-0.04279 -0.0415,-0.06093 -0.0748,-0.05446 z m 0,-0.07153 c 0.0532,-0.01046 0.0939,0.01127 0.12204,0.06529 0.0284,0.05377 0.0426,0.137301 0.0426,0.250515 0,0.112914 -0.0142,0.201731 -0.0426,0.266368 -0.0281,0.06419 -0.0688,0.100927 -0.12205,0.110273 -0.053,0.0093 -0.0935,-0.013 -0.12146,-0.06685 -0.0277,-0.0541 -0.0415,-0.137007 -0.0415,-0.248804 0,-0.112093 0.0139,-0.200157 0.0416,-0.264272 0.028,-0.06456 0.0684,-0.102087 0.12147,-0.112517 z" + style="stroke-width:0.5" + id="path42228" + inkscape:original-d="m 90.875858,-70.070984 q -0.322461,0 -0.485758,0.318326 -0.16123,0.31626 -0.16123,0.952913 0,0.634586 0.16123,0.952913 0.163297,0.316259 0.485758,0.316259 0.324528,0 0.485758,-0.316259 0.163297,-0.318327 0.163297,-0.952913 0,-0.636653 -0.163297,-0.952913 -0.16123,-0.318326 -0.485758,-0.318326 z m 0,-0.330729 q 0.518831,0 0.791682,0.411344 0.274919,0.409277 0.274919,1.190624 0,0.77928 -0.274919,1.190624 -0.272851,0.409277 -0.791682,0.409277 -0.518831,0 -0.793749,-0.409277 -0.272852,-0.411344 -0.272852,-1.190624 0,-0.781347 0.272852,-1.190624 0.274918,-0.411344 0.793749,-0.411344 z" /> + </g> + </g> + <path + style="fill:none;stroke:#666666;stroke-width:0.154594px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 78.493638,31.832162 54.86572,27.579136 V 15.091444 l 23.640031,-4.4792 z" + id="path2507" + sodipodi:nodetypes="ccccc" /> + <path + style="fill:none;stroke:#666666;stroke-width:0.154594px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 54.86572,15.091444 -8.957173,7.728442" + id="path3003" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#666666;stroke-width:0.154594px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 78.505751,10.612244 45.908547,22.819886" + id="path3005" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#666666;stroke-width:0.154594px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 54.86572,27.579136 -8.957173,-4.75925" + id="path3007" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#666666;stroke-width:0.154594px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 78.493638,31.832162 45.908547,22.819886" + id="path3009" + sodipodi:nodetypes="cc" /> + <rect + style="fill:#000000;stroke-width:0.499999;stroke-linecap:round;stroke-linejoin:round" + id="rect4200" + width="5.6629953" + height="3.218504" + x="37.72229" + y="25.463196" + transform="rotate(-5.5946875)" + inkscape:transform-center-x="0.89473382" + inkscape:transform-center-y="0.88586789" /> + <path + style="fill:#000000;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 45.574462,22.840294 2.083868,-1.717559 0.37787,2.828131 z" + id="path4461" + sodipodi:nodetypes="cccc" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:tb-rl;fill:#e6e6e6;stroke:none;stroke-width:0.499999;stroke-linecap:round;stroke-linejoin:round" + x="78.783813" + y="19.947718" + id="text7072" + transform="rotate(11.68529)"><tspan + sodipodi:role="line" + id="tspan7070" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;stroke:none;stroke-width:0.5" + x="78.783813" + y="19.947718">canvas (infinitely large)</tspan></text> + <path + style="color:#000000;fill:#000000;-inkscape-stroke:none" + d="m -61.93684,-156.18135 v 4 h 0.09961 v 0.0996 h 84 v -0.19922 h -3.90039 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -3.90039 h -0.19922 v 3.90039 H 8.26238 v -1.90039 H 8.06316 v 1.90039 H 3.26238 v -1.90039 H 3.06316 v 1.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -3.90039 h -0.19922 v 3.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -3.90039 h -0.19922 v 3.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -1.90039 h -0.19922 v 1.90039 h -4.80078 v -3.90039 z" + id="path17823-0-5-5" /> + <path + style="color:#000000;fill:#000000;-inkscape-stroke:none" + d="m -67.755199,-150.22237 v 0.20117 h 3.605468 v 5.0918 h -1.751953 v 0.19922 h 1.751953 v 5.09179 h -1.751953 v 0.19922 h 1.751953 v 5.0918 h -1.751953 v 0.20117 h 1.751953 v 5.0918 h -1.751953 v 0.19922 h 1.751953 v 5.09179 h -3.605468 v 0.19922 h 3.605468 v 5.0918 h -1.751953 v 0.20117 h 1.751953 v 5.0918 h -1.751953 v 0.19922 h 1.751953 v 5.09179 h -1.751953 v 0.19922 h 1.751953 v 5.0918 h -1.751953 v 0.20117 h 1.751953 v 5.091798 h -3.605468 v 0.199218 h 3.605468 v 2.984375 h 0.199219 v -56.000001 h -0.09961 v -0.10156 z" + id="path17825-0-7-1" /> + <g + id="g33047-4-4" + transform="translate(-1.90988,-165.92997)"> + <path + style="color:#000000;fill:#000000;-inkscape-stroke:none" + d="m -61.0625,14.673828 v 1 57 h 86 v -58 z m 2,2 h 82 v 54 h -82 z" + id="rect17821-2-4" /> + <path + style="color:#000000;fill:#000000;-inkscape-stroke:none" + d="m -60.0625,29.574219 v 0.199218 h 84 v -0.199218 z" + id="path17823-5-5" /> + <path + style="color:#000000;fill:#000000;-inkscape-stroke:none" + d="m -39.162109,15.673828 v 56 h 0.199218 v -56 z" + id="path17825-5-8" /> + <path + style="color:#000000;fill:#ff0000;-inkscape-stroke:none" + d="m -39.0625,27.423828 c -1.239678,0 -2.25,1.010322 -2.25,2.25 0,1.239678 1.010322,2.25 2.25,2.25 1.239678,0 2.25,-1.010322 2.25,-2.25 0,-1.239678 -1.010322,-2.25 -2.25,-2.25 z m 0,0.5 c 0.969459,0 1.75,0.780542 1.75,1.75 0,0.969459 -0.780541,1.75 -1.75,1.75 -0.969459,0 -1.75,-0.780541 -1.75,-1.75 0,-0.969458 0.780541,-1.75 1.75,-1.75 z" + id="c1-4-4-3" /> + <path + style="color:#000000;fill:#008000;-inkscape-stroke:none" + d="m -39.0625,25.423828 c -2.344247,0 -4.25,1.905753 -4.25,4.25 0,2.344247 1.905753,4.25 4.25,4.25 2.344247,0 4.25,-1.905753 4.25,-4.25 0,-2.344247 -1.905753,-4.25 -4.25,-4.25 z m 0,0.5 c 2.074027,0 3.75,1.675973 3.75,3.75 0,2.074027 -1.675973,3.75 -3.75,3.75 -2.074027,0 -3.75,-1.675973 -3.75,-3.75 0,-2.074027 1.675973,-3.75 3.75,-3.75 z" + id="c2-6-1-0" /> + <path + style="color:#000000;fill:#0000ff;-inkscape-stroke:none" + d="m 19.306641,65.751953 c -1.554338,0 -2.833984,1.2816 -2.833985,2.835938 0,1.554338 1.279646,2.833984 2.833985,2.833984 1.554338,0 2.835937,-1.279646 2.835937,-2.833984 -1e-6,-1.554338 -1.281599,-2.835938 -2.835937,-2.835938 z m 0,1.890625 c 0.533035,0 0.945312,0.412278 0.945312,0.945313 0,0.533035 -0.412277,0.943359 -0.945312,0.943359 -0.533036,0 -0.94336,-0.410324 -0.94336,-0.943359 0,-0.533035 0.410325,-0.945313 0.94336,-0.945313 z" + id="c3-2-7-3" /> + </g> + <g + aria-label="25" + id="text20650-4-7" + style="font-size:4.23333px;line-height:125%;-inkscape-font-specification:sans-serif;stroke-width:0.499999;stroke-linecap:round;stroke-linejoin:round" + transform="translate(-161.37434,-81.345418)"> + <path + d="m 123.49461,-76.561811 h 1.45728 v 0.3514 h -1.95957 v -0.3514 q 0.23771,-0.24598 0.64699,-0.659391 0.41134,-0.415479 0.51676,-0.535368 0.2005,-0.225309 0.27905,-0.380338 0.0806,-0.157097 0.0806,-0.307992 0,-0.24598 -0.17363,-0.401009 -0.17157,-0.155029 -0.44856,-0.155029 -0.19637,0 -0.41547,0.06821 -0.21705,0.06821 -0.46509,0.206705 v -0.421679 q 0.25218,-0.101286 0.47129,-0.152963 0.2191,-0.05168 0.40101,-0.05168 0.47955,0 0.76481,0.239779 0.28525,0.239778 0.28525,0.640787 0,0.19017 -0.0724,0.361735 -0.0703,0.169499 -0.25838,0.401009 -0.0517,0.05994 -0.32866,0.347266 -0.27699,0.285254 -0.78135,0.799951 z" + style="stroke-width:0.5" + id="path42200-3" /> + <path + d="m 125.83245,-79.296527 h 1.63918 v 0.351399 h -1.25677 v 0.756543 q 0.0909,-0.03101 0.1819,-0.04547 0.091,-0.01654 0.1819,-0.01654 0.51677,0 0.81856,0.283187 0.30179,0.283187 0.30179,0.766879 0,0.49816 -0.31006,0.775146 -0.31006,0.274919 -0.87437,0.274919 -0.1943,0 -0.39687,-0.03307 -0.20051,-0.03307 -0.41548,-0.09922 v -0.419613 q 0.18603,0.101286 0.38447,0.150895 0.19844,0.04961 0.41961,0.04961 0.35761,0 0.56638,-0.188102 0.20877,-0.188103 0.20877,-0.510563 0,-0.322461 -0.20877,-0.510564 -0.20877,-0.188102 -0.56638,-0.188102 -0.16743,0 -0.33486,0.03721 -0.16536,0.03721 -0.339,0.115755 z" + style="stroke-width:0.5" + id="path42202-9" /> + </g> + <g + aria-label="25" + id="text20650-0-4-5" + style="font-size:4.23333px;line-height:125%;-inkscape-font-specification:sans-serif;stroke-width:0.499999;stroke-linecap:round;stroke-linejoin:round" + transform="translate(-161.37434,-81.345418)"> + <path + d="m 88.166067,-40.786962 h 1.457274 v 0.3514 h -1.959569 v -0.3514 q 0.237712,-0.245979 0.646989,-0.65939 0.411344,-0.415478 0.516764,-0.535368 0.200504,-0.225309 0.279052,-0.380338 0.08061,-0.157096 0.08061,-0.307991 0,-0.24598 -0.173632,-0.401009 -0.171566,-0.155029 -0.448551,-0.155029 -0.196371,0 -0.415479,0.06821 -0.21704,0.06821 -0.465087,0.206705 v -0.421679 q 0.252181,-0.101286 0.471289,-0.152962 0.219107,-0.05168 0.401008,-0.05168 0.479557,0 0.764811,0.239779 0.285254,0.239778 0.285254,0.640787 0,0.190169 -0.07235,0.361735 -0.07028,0.169498 -0.258382,0.401009 -0.05168,0.05994 -0.328662,0.347265 -0.276986,0.285254 -0.781347,0.79995 z" + style="stroke-width:0.5" + id="path42205-4" /> + <path + d="m 90.503907,-43.521676 h 1.639175 v 0.351399 h -1.25677 v 0.756543 q 0.09095,-0.03101 0.181901,-0.04548 0.09095,-0.01654 0.181901,-0.01654 0.516764,0 0.818554,0.283187 0.30179,0.283186 0.30179,0.766877 0,0.498161 -0.310058,0.775146 -0.310059,0.274918 -0.874365,0.274918 -0.194303,0 -0.396875,-0.03307 -0.200504,-0.03307 -0.415478,-0.09922 v -0.419612 q 0.186035,0.101285 0.384473,0.150895 0.198437,0.04961 0.419612,0.04961 0.3576,0 0.566373,-0.188102 0.208773,-0.188102 0.208773,-0.510563 0,-0.32246 -0.208773,-0.510562 -0.208773,-0.188103 -0.566373,-0.188103 -0.167432,0 -0.334863,0.03721 -0.165365,0.03721 -0.338997,0.115756 z" + style="stroke-width:0.5" + id="path42207-1" /> + </g> + <g + aria-label="50" + id="text25354-6-0" + style="font-size:4.23333px;line-height:125%;-inkscape-font-specification:sans-serif;stroke-width:0.499999;stroke-linecap:round;stroke-linejoin:round" + transform="translate(-161.37434,-81.345418)"> + <path + d="m 147.78972,-79.245975 h 1.63918 v 0.3514 h -1.25677 v 0.756543 q 0.0909,-0.03101 0.1819,-0.04548 0.0909,-0.01654 0.1819,-0.01654 0.51676,0 0.81855,0.283187 0.30179,0.283187 0.30179,0.766878 0,0.498161 -0.31006,0.775146 -0.31005,0.274919 -0.87436,0.274919 -0.1943,0 -0.39688,-0.03307 -0.2005,-0.03307 -0.41547,-0.09922 v -0.419612 q 0.18603,0.101285 0.38447,0.150895 0.19844,0.04961 0.41961,0.04961 0.3576,0 0.56637,-0.188102 0.20878,-0.188102 0.20878,-0.510563 0,-0.322461 -0.20878,-0.510563 -0.20877,-0.188102 -0.56637,-0.188102 -0.16743,0 -0.33486,0.03721 -0.16537,0.03721 -0.339,0.115755 z" + style="stroke-width:0.5" + id="path42210-9" /> + <path + d="m 151.37193,-78.971056 q -0.32246,0 -0.48576,0.318326 -0.16123,0.31626 -0.16123,0.952914 0,0.634586 0.16123,0.952913 0.1633,0.31626 0.48576,0.31626 0.32453,0 0.48576,-0.31626 0.1633,-0.318327 0.1633,-0.952913 0,-0.636654 -0.1633,-0.952914 -0.16123,-0.318326 -0.48576,-0.318326 z m 0,-0.33073 q 0.51883,0 0.79168,0.411345 0.27492,0.409277 0.27492,1.190625 0,0.77928 -0.27492,1.190625 -0.27285,0.409277 -0.79168,0.409277 -0.51883,0 -0.79375,-0.409277 -0.27285,-0.411345 -0.27285,-1.190625 0,-0.781348 0.27285,-1.190625 0.27492,-0.411345 0.79375,-0.411345 z" + style="stroke-width:0.5" + id="path42212-7" /> + </g> + <g + aria-label="50" + id="text25354-5-4-9" + style="font-size:4.23333px;line-height:125%;-inkscape-font-specification:sans-serif;stroke-width:0.499999;stroke-linecap:round;stroke-linejoin:round" + transform="translate(-161.37434,-81.345418)"> + <path + d="m 87.834017,-17.236643 h 1.639175 v 0.3514 h -1.25677 v 0.756542 q 0.09095,-0.03101 0.181901,-0.04547 0.09095,-0.01654 0.181901,-0.01654 0.516763,0 0.818554,0.283187 0.30179,0.283186 0.30179,0.766877 0,0.498161 -0.310059,0.775146 -0.310058,0.274919 -0.874364,0.274919 -0.194303,0 -0.396875,-0.03307 -0.200504,-0.03307 -0.415478,-0.09922 v -0.419612 q 0.186035,0.101286 0.384472,0.150895 0.198438,0.04961 0.419613,0.04961 0.3576,0 0.566373,-0.188102 0.208772,-0.188102 0.208772,-0.510563 0,-0.32246 -0.208772,-0.510562 -0.208773,-0.188102 -0.566373,-0.188102 -0.167432,0 -0.334863,0.03721 -0.165365,0.03721 -0.338997,0.115755 z" + style="stroke-width:0.5" + id="path42215-1" /> + <path + d="m 91.416224,-16.961724 q -0.322461,0 -0.485758,0.318326 -0.161231,0.31626 -0.161231,0.952913 0,0.634586 0.161231,0.952912 0.163297,0.31626 0.485758,0.31626 0.324528,0 0.485758,-0.31626 0.163297,-0.318326 0.163297,-0.952912 0,-0.636653 -0.163297,-0.952913 -0.16123,-0.318326 -0.485758,-0.318326 z m 0,-0.330729 q 0.518831,0 0.791682,0.411344 0.274919,0.409277 0.274919,1.190624 0,0.77928 -0.274919,1.190624 -0.272851,0.409277 -0.791682,0.409277 -0.518831,0 -0.793749,-0.409277 -0.272852,-0.411344 -0.272852,-1.190624 0,-0.781347 0.272852,-1.190624 0.274918,-0.411344 0.793749,-0.411344 z" + style="stroke-width:0.5" + id="path42217-1" /> + </g> + <g + aria-label="75" + id="text27250-9-6" + style="font-size:4.23333px;line-height:125%;-inkscape-font-specification:sans-serif;stroke-width:0.499999;stroke-linecap:round;stroke-linejoin:round" + transform="translate(-161.37434,-81.345418)"> + <path + d="m 172.41506,-79.178577 h 1.98438 v 0.177767 l -1.12035,2.908349 h -0.43615 l 1.0542,-2.734716 h -1.48208 z" + style="stroke-width:0.5" + id="path42220-2" /> + <path + d="m 175.21799,-79.178577 h 1.63918 v 0.3514 h -1.25677 v 0.756543 q 0.0909,-0.03101 0.1819,-0.04548 0.091,-0.01654 0.1819,-0.01654 0.51676,0 0.81855,0.283187 0.30179,0.283187 0.30179,0.766878 0,0.498161 -0.31006,0.775146 -0.31005,0.274919 -0.87436,0.274919 -0.1943,0 -0.39688,-0.03307 -0.2005,-0.03307 -0.41547,-0.09922 v -0.419612 q 0.18603,0.101286 0.38447,0.150895 0.19844,0.04961 0.41961,0.04961 0.3576,0 0.56637,-0.188102 0.20878,-0.188102 0.20878,-0.510563 0,-0.322461 -0.20878,-0.510563 -0.20877,-0.188102 -0.56637,-0.188102 -0.16743,0 -0.33486,0.03721 -0.16537,0.03721 -0.339,0.115755 z" + style="stroke-width:0.5" + id="path42222-1" /> + </g> + <g + aria-label="0" + id="text30700-8-8" + style="font-size:4.23333px;line-height:125%;-inkscape-font-specification:sans-serif;stroke-width:0.499999;stroke-linecap:round;stroke-linejoin:round" + transform="translate(-161.37434,-81.345418)"> + <path + d="m 99.950146,-78.903658 q -0.322461,0 -0.485758,0.318326 -0.16123,0.31626 -0.16123,0.952914 0,0.634586 0.16123,0.952913 0.163297,0.31626 0.485758,0.31626 0.324524,0 0.485754,-0.31626 0.1633,-0.318327 0.1633,-0.952913 0,-0.636654 -0.1633,-0.952914 -0.16123,-0.318326 -0.485754,-0.318326 z m 0,-0.33073 q 0.518834,0 0.791684,0.411345 0.27492,0.409277 0.27492,1.190625 0,0.77928 -0.27492,1.190625 -0.27285,0.409277 -0.791684,0.409277 -0.518831,0 -0.79375,-0.409277 -0.272851,-0.411345 -0.272851,-1.190625 0,-0.781348 0.272851,-1.190625 0.274919,-0.411345 0.79375,-0.411345 z" + style="stroke-width:0.5" + id="path42225-9" /> + </g> + <g + aria-label="0" + id="text30700-1-3-4" + style="font-size:4.23333px;line-height:125%;-inkscape-font-specification:sans-serif;stroke-width:0.499999;stroke-linecap:round;stroke-linejoin:round" + transform="translate(-161.37434,-81.345418)"> + <path + d="m 90.875858,-70.070984 q -0.322461,0 -0.485758,0.318326 -0.16123,0.31626 -0.16123,0.952913 0,0.634586 0.16123,0.952913 0.163297,0.316259 0.485758,0.316259 0.324528,0 0.485758,-0.316259 0.163297,-0.318327 0.163297,-0.952913 0,-0.636653 -0.163297,-0.952913 -0.16123,-0.318326 -0.485758,-0.318326 z m 0,-0.330729 q 0.518831,0 0.791682,0.411344 0.274919,0.409277 0.274919,1.190624 0,0.77928 -0.274919,1.190624 -0.272851,0.409277 -0.791682,0.409277 -0.518831,0 -0.793749,-0.409277 -0.272852,-0.411344 -0.272852,-1.190624 0,-0.781347 0.272852,-1.190624 0.274918,-0.411344 0.793749,-0.411344 z" + style="stroke-width:0.5" + id="path42228-5" /> + </g> + <g + id="g62074" + transform="translate(-41.843068,-27.937024)"> + <path + d="m 50.681392,41.369892 h 22.559037 m -22.559037,0 v -1.07424 m 1.3428,1.07424 v -0.53712 m 1.3428,0.53712 v -0.53712 m 1.342799,0.53712 v -0.53712 m 1.3428,0.53712 v -0.53712 m 1.3428,0.53712 v -1.07424 m 1.3428,1.07424 v -0.53712 m 1.3428,0.53712 v -0.53712 m 1.3428,0.53712 v -0.53712 m 1.3428,0.53712 v -0.53712 m 1.342799,0.53712 v -1.07424 m 1.3428,1.07424 v -0.53712 m 1.3428,0.53712 v -0.53712 m 1.3428,0.53712 v -0.53712 m 1.3428,0.53712 v -0.53712 m 1.3428,0.53712 v -1.07424 m 1.342799,1.07424 v -0.53712" + stroke="#000000" + stroke-width="0.053712px" + id="path17823-0" + style="fill:none" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.32639px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;stroke:none;stroke-width:0.13428;stroke-linecap:round;stroke-linejoin:round" + x="55.666538" + y="39.945011" + id="text20650"><tspan + sodipodi:role="line" + id="tspan20648" + style="font-size:1.32639px;stroke-width:0.13428" + x="55.666538" + y="39.945011">25 mm</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.32639px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;stroke:none;stroke-width:0.13428;stroke-linecap:round;stroke-linejoin:round" + x="62.431519" + y="39.994785" + id="text25354"><tspan + sodipodi:role="line" + id="tspan25352" + style="font-size:1.32639px;stroke-width:0.13428" + x="62.431519" + y="39.994785">50 mm</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.32639px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;stroke:none;stroke-width:0.13428;stroke-linecap:round;stroke-linejoin:round" + x="69.001923" + y="39.940487" + id="text27250"><tspan + sodipodi:role="line" + id="tspan27248" + style="font-size:1.32639px;stroke-width:0.13428" + x="69.001923" + y="39.940487">75 mm</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.32639px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;stroke:none;stroke-width:0.13428;stroke-linecap:round;stroke-linejoin:round" + x="49.417419" + y="39.940487" + id="text30700"><tspan + sodipodi:role="line" + id="tspan30698" + style="font-size:1.32639px;stroke-width:0.13428" + x="49.417419" + y="39.940487">0 mm</tspan></text> + </g> + <g + id="g62101" + transform="translate(-42.901401,-26.878691)"> + <path + d="m 50.087127,41.922938 v 15.039358 m 0,-15.039358 h -0.994791 m 0.994791,1.42113 h -0.497395 m 0.497395,1.421129 h -0.497395 m 0.497395,1.42113 h -0.497395 m 0.497395,1.42113 h -0.497395 m 0.497395,1.42113 h -0.994791 m 0.994791,1.42113 h -0.497395 m 0.497395,1.42113 h -0.497395 m 0.497395,1.421129 h -0.497395 m 0.497395,1.42113 h -0.497395 m 0.497395,1.42113 h -0.994791" + stroke="#000000" + stroke-width="0.053712px" + id="path17825-0" + style="fill:none" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.32639px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;stroke:none;stroke-width:0.13428;stroke-linecap:round;stroke-linejoin:round" + x="44.115273" + y="49.3717" + id="text20650-0"><tspan + sodipodi:role="line" + id="tspan20648-5" + style="font-size:1.32639px;stroke-width:0.13428" + x="44.115273" + y="49.3717">25 mm</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.32639px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;stroke:none;stroke-width:0.13428;stroke-linecap:round;stroke-linejoin:round" + x="44.121582" + y="56.503208" + id="text25354-5"><tspan + sodipodi:role="line" + id="tspan25352-5" + style="font-size:1.32639px;stroke-width:0.13428" + x="44.121582" + y="56.503208">50 mm</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.32639px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;stroke:none;stroke-width:0.13428;stroke-linecap:round;stroke-linejoin:round" + x="44.518791" + y="42.27639" + id="text30700-1"><tspan + sodipodi:role="line" + id="tspan30698-2" + style="font-size:1.32639px;stroke-width:0.13428" + x="44.518791" + y="42.27639">0 mm</tspan></text> + </g> + <g + id="g61992" + transform="translate(-41.841527,-26.878691)"> + <path + id="rect60227" + style="color:#000000;fill:#ff6600;stroke-width:0.26856" + d="M 50.620387,41.864982 V 56.904393 H 73.179435 V 41.864982 Z m 0.268544,0.268543 h 22.02196 v 14.502324 h -22.02196 z" /> + <path + d="M 50.620431,45.624854 H 73.179468" + stroke="#000000" + stroke-width="0.053712px" + id="path60229" + style="fill:none" /> + <path + d="M 56.26019,41.865014 V 56.904372" + stroke="#000000" + stroke-width="0.053712px" + id="path60231" + style="fill:none" /> + <circle + id="c1" + r="0.53711993" + cx="56.260189" + cy="45.624855" + stroke="#ff0000" + stroke-width="0.13428" + style="fill:none" /> + <circle + id="c2" + r="1.0742399" + cx="56.260189" + cy="45.624855" + stroke="#008000" + stroke-width="0.13428px" + style="fill:none" /> + <circle + id="c3" + r="0.13427998mm" + cx="71.936058" + cy="56.075432" + stroke="#0000ff" + stroke-width="0.13428mm" + style="fill:none" /> + </g> + <g + aria-label="user coordinate system" + id="text73128" + style="font-size:1.41111px;line-height:125%;-inkscape-font-specification:sans-serif;stroke-linecap:round;stroke-linejoin:round" + inkscape:path-effect="#path-effect86166" + transform="translate(1.0205426,0.14057686)"> + <path + d="m 55.388345,10.792719 -1e-6,-0.346292 0.127179,-0.02702 -1.01e-4,0.342711 c -1.6e-5,0.05409 0.01424,0.0917 0.04277,0.112828 0.02852,0.02079 0.07131,0.02511 0.128364,0.01297 0.06855,-0.01459 0.12262,-0.04224 0.162217,-0.08296 0.04006,-0.04082 0.06012,-0.08912 0.06019,-0.144911 l 3.93e-4,-0.32431 0.127085,-0.027 -8.62e-4,0.571667 -0.126912,0.02702 1.06e-4,-0.0877 c -0.03086,0.04124 -0.06677,0.0747 -0.107717,0.100409 -0.04049,0.02527 -0.08765,0.04363 -0.141469,0.05509 -0.08879,0.0189 -0.156191,0.01286 -0.202201,-0.01813 -0.04602,-0.031 -0.06903,-0.08578 -0.06903,-0.164363 z" + id="path86107" + inkscape:original-d="M 55.354646,9.7273056 V 9.260151 h 0.126779 v 0.4623314 q 0,0.109554 0.04272,0.1646755 0.04272,0.054432 0.128158,0.054432 0.102663,0 0.161919,-0.065457 0.05994,-0.065457 0.05994,-0.1784558 V 9.260151 h 0.126779 v 0.771701 H 55.874166 V 9.9133406 q -0.04617,0.07028 -0.107487,0.1047304 -0.06063,0.03376 -0.141249,0.03376 -0.132981,0 -0.201882,-0.082682 -0.0689,-0.082682 -0.0689,-0.2418455 z m 0.319015,-0.4857581 z" /> + <path + d="m 56.790826,10.165295 -2.9e-4,0.08889 c -0.03582,-0.006 -0.07304,-0.0083 -0.11165,-0.0069 -0.03862,0.0014 -0.07862,0.0065 -0.120019,0.0153 -0.06302,0.01339 -0.110423,0.03062 -0.142206,0.05167 -0.03132,0.02095 -0.04701,0.04573 -0.04707,0.07433 -5e-5,0.02179 0.01118,0.03659 0.03369,0.04439 0.02251,0.0075 0.06778,0.0096 0.135809,0.0063 l 0.04344,-0.0021 c 0.09007,-0.0049 0.153905,0.0018 0.191511,0.01997 0.03806,0.01774 0.05701,0.0499 0.05685,0.09649 -1.78e-4,0.05304 -0.0288,0.101075 -0.08586,0.144125 -0.0566,0.04295 -0.134512,0.07498 -0.23375,0.09611 -0.04135,0.0088 -0.08454,0.01494 -0.129563,0.01841 -0.04456,0.0037 -0.09166,0.0049 -0.141278,0.0036 l 1.93e-4,-0.09688 c 0.04686,0.008 0.09303,0.01181 0.138518,0.0113 0.04548,-8.46e-4 0.09051,-0.006 0.135092,-0.0155 0.05974,-0.01271 0.10571,-0.02997 0.13792,-0.05177 0.03221,-0.02214 0.04836,-0.04698 0.04844,-0.07452 7.8e-5,-0.0255 -0.01158,-0.04256 -0.03498,-0.05118 -0.02294,-0.0087 -0.0737,-0.01101 -0.152275,-0.0069 l -0.04412,0.0017 c -0.0786,0.0045 -0.135353,-0.0022 -0.170254,-0.0199 -0.03491,-0.01809 -0.05232,-0.04926 -0.05223,-0.09352 1.08e-4,-0.0538 0.02596,-0.10083 0.07757,-0.141078 0.05161,-0.04025 0.124809,-0.07045 0.219595,-0.09058 0.04693,-0.01 0.09108,-0.0168 0.132471,-0.02048 0.04138,-0.0037 0.07953,-0.0041 0.114456,-0.0013 z" + id="path86109" + inkscape:original-d="m 56.754042,9.2828886 v 0.1198892 q -0.05374,-0.027561 -0.111621,-0.041341 -0.05788,-0.01378 -0.119889,-0.01378 -0.09439,0 -0.141938,0.028939 -0.04685,0.028939 -0.04685,0.086816 0,0.044097 0.03376,0.069591 0.03376,0.024805 0.135737,0.047542 l 0.04341,0.00965 q 0.135047,0.028939 0.191547,0.081993 0.05719,0.052365 0.05719,0.1467609 0,0.1074869 -0.08544,0.1701876 -0.08475,0.0627 -0.233577,0.0627 -0.06201,0 -0.129536,-0.0124 -0.06683,-0.01171 -0.141248,-0.03583 V 9.8726885 q 0.07028,0.036518 0.138492,0.055121 0.06821,0.017914 0.135048,0.017914 0.08957,0 0.137804,-0.030317 0.04823,-0.031006 0.04823,-0.086816 0,-0.051676 -0.03514,-0.079237 -0.03445,-0.027561 -0.152273,-0.053055 l -0.0441,-0.010335 q -0.117822,-0.024805 -0.170188,-0.075792 -0.05237,-0.051676 -0.05237,-0.1412488 0,-0.1088649 0.07717,-0.1681205 0.07717,-0.059256 0.219108,-0.059256 0.07028,0 0.132291,0.010335 0.06201,0.010335 0.114377,0.031006 z" /> + <path + d="m 57.693325,10.218842 -2.46e-4,0.04592 -0.582713,0.123936 c 0.0053,0.06344 0.03125,0.107178 0.07793,0.131211 0.04715,0.02359 0.112723,0.02644 0.196723,0.0086 0.04865,-0.01036 0.09572,-0.02478 0.14119,-0.04329 0.04593,-0.0186 0.09143,-0.04152 0.136494,-0.06877 l -4.7e-4,0.08869 c -0.04549,0.02394 -0.09211,0.04472 -0.139871,0.06235 -0.04776,0.01763 -0.09619,0.03168 -0.145286,0.04213 -0.122998,0.02618 -0.220431,0.02045 -0.292301,-0.01722 -0.07144,-0.03778 -0.106995,-0.101895 -0.10666,-0.192369 3.46e-4,-0.09358 0.03464,-0.175014 0.102874,-0.244294 0.06871,-0.06973 0.160988,-0.116902 0.276808,-0.141509 0.103854,-0.022065 0.185744,-0.014624 0.245669,0.02231 0.06037,0.03648 0.09031,0.09727 0.08986,0.182334 z m -0.12657,-6.13e-4 c -6.58e-4,-0.05119 -0.01997,-0.08805 -0.05794,-0.110587 -0.03752,-0.02264 -0.08752,-0.02732 -0.150006,-0.01404 -0.07076,0.01504 -0.127581,0.04191 -0.170444,0.08062 -0.0424,0.03861 -0.06693,0.08548 -0.07358,0.140621 z" + id="path86111" + inkscape:original-d="m 57.657346,9.6143065 v 0.062012 h -0.58291 q 0.0083,0.1309135 0.07855,0.1998154 0.07097,0.068213 0.19706,0.068213 0.07304,0 0.141248,-0.017914 0.0689,-0.017915 0.136426,-0.053743 v 0.1198892 q -0.06821,0.028938 -0.139871,0.044097 -0.07166,0.01516 -0.145383,0.01516 -0.184657,0 -0.292833,-0.1074852 -0.107486,-0.1074869 -0.107486,-0.2907658 0,-0.1894801 0.101974,-0.3004121 0.102664,-0.111621 0.276297,-0.111621 0.155718,0 0.245979,0.1005967 0.09095,0.099908 0.09095,0.2721623 z m -0.12678,-0.037207 Q 57.529188,9.4730577 57.472,9.411046 57.4155,9.349034 57.321794,9.349034 q -0.106109,0 -0.170188,0.059945 -0.06339,0.059945 -0.07304,0.1688095 z" /> + <path + d="m 58.349056,9.9050877 c -0.01418,-0.0031 -0.02975,-0.00422 -0.04671,-0.00333 -0.01649,4.465e-4 -0.03484,0.00282 -0.05503,0.00711 -0.07159,0.015215 -0.126776,0.044282 -0.165548,0.087198 -0.03831,0.042474 -0.05766,0.096036 -0.05805,0.1606758 l -0.0018,0.300828 -0.127249,0.02709 0.0033,-0.5714393 0.127416,-0.027072 -5.45e-4,0.088874 c 0.02684,-0.040386 0.06165,-0.073459 0.104452,-0.099218 0.0428,-0.026099 0.09472,-0.045634 0.155767,-0.058603 0.0087,-0.00185 0.01835,-0.00339 0.02891,-0.00461 0.01055,-0.00156 0.02225,-0.00286 0.03508,-0.00389 z" + id="path86113" + inkscape:original-d="m 58.312602,9.3786622 q -0.02136,-0.012402 -0.04685,-0.017915 -0.0248,-0.0062 -0.05512,-0.0062 -0.107487,0 -0.165365,0.07028 -0.05719,0.069591 -0.05719,0.2005044 V 10.031852 H 57.860606 V 9.260151 h 0.127469 v 0.1198892 q 0.03996,-0.07028 0.104042,-0.1040418 0.06408,-0.034451 0.155718,-0.034451 0.01309,0 0.02894,0.00207 0.01585,0.00138 0.03514,0.00482 z" /> + <path + d="m 59.484319,9.5980769 -8.35e-4,0.087816 c -0.03559,-0.00704 -0.07145,-0.010288 -0.107576,-0.00974 -0.03567,1.064e-4 -0.07183,0.00405 -0.108489,0.011846 -0.08203,0.017432 -0.145901,0.050372 -0.191608,0.098815 -0.0457,0.048096 -0.06884,0.1070122 -0.06942,0.1767358 -5.86e-4,0.069701 0.02163,0.1190928 0.06664,0.1481858 0.045,0.02875 0.108474,0.0344 0.19042,0.01696 0.03662,-0.0078 0.07281,-0.01906 0.108582,-0.03379 0.03623,-0.01517 0.07226,-0.03385 0.108097,-0.05606 l -8.25e-4,0.08662 c -0.03535,0.01973 -0.07204,0.03669 -0.110082,0.05089 -0.03758,0.0141 -0.07766,0.02568 -0.120218,0.03474 -0.115806,0.02465 -0.207593,0.01724 -0.275366,-0.02224 -0.0678,-0.0395 -0.101332,-0.10514 -0.100588,-0.1969387 7.56e-4,-0.093199 0.03573,-0.1738363 0.104935,-0.2418887 0.06967,-0.06816 0.164566,-0.1150029 0.284657,-0.1405172 0.03896,-0.00828 0.07697,-0.013294 0.114027,-0.015051 0.03706,-0.0021 0.07295,-8.877e-4 0.107654,0.00363 z" + id="path86115" + inkscape:original-d="M 59.449483,9.2897788 V 9.40829 q -0.05374,-0.029628 -0.108176,-0.044097 -0.05374,-0.015158 -0.108865,-0.015158 -0.123334,0 -0.191547,0.078548 -0.06821,0.077859 -0.06821,0.2191079 0,0.1412488 0.06821,0.2197969 0.06821,0.077859 0.191547,0.077859 0.05512,0 0.108865,-0.014469 0.05443,-0.015158 0.108176,-0.044786 v 0.1171332 q -0.05305,0.02481 -0.110243,0.03721 -0.0565,0.0124 -0.120578,0.0124 -0.174322,0 -0.276986,-0.1095536 -0.102663,-0.109554 -0.102663,-0.295589 0,-0.1887911 0.103352,-0.296967 0.104042,-0.1081759 0.284565,-0.1081759 0.05857,0 0.114377,0.012402 0.05581,0.011713 0.108176,0.035829 z" /> + <path + d="m 60.001814,9.5319254 c -0.06775,0.014398 -0.121522,0.04552 -0.161303,0.093361 -0.03978,0.047495 -0.06001,0.1054245 -0.06071,0.173776 -6.97e-4,0.06833 0.0182,0.1180589 0.05668,0.1491985 0.03894,0.030695 0.09247,0.038788 0.160606,0.024287 0.06722,-0.014306 0.120702,-0.045342 0.160459,-0.093114 0.03977,-0.047778 0.06003,-0.1056538 0.06079,-0.1736372 7.6e-4,-0.067665 -0.01831,-0.1170511 -0.05723,-0.1481487 -0.03892,-0.031445 -0.09202,-0.040022 -0.159305,-0.025723 z m 8.53e-4,-0.079653 c 0.109873,-0.023343 0.195861,-0.015122 0.25796,0.024652 0.06207,0.039761 0.09256,0.1065766 0.09148,0.2004261 -0.0011,0.093469 -0.03324,0.1735187 -0.09647,0.2401719 -0.06322,0.066304 -0.149683,0.1111303 -0.2594,0.1344873 -0.110196,0.02346 -0.196354,0.01537 -0.258479,-0.02427 -0.06169,-0.040092 -0.09208,-0.106869 -0.09115,-0.2003521 9.29e-4,-0.093864 0.0328,-0.1739701 0.09561,-0.2402956 0.06327,-0.066432 0.150098,-0.1113759 0.260449,-0.1348211 z" + id="path86117" + inkscape:original-d="m 59.969003,9.3490344 q -0.101975,0 -0.16123,0.079926 -0.05926,0.079237 -0.05926,0.2177299 0,0.1384927 0.05857,0.2184189 0.05926,0.079237 0.161919,0.079237 0.101286,0 0.160541,-0.079926 0.05926,-0.079926 0.05926,-0.2177299 0,-0.1371147 -0.05926,-0.2170409 -0.05926,-0.080615 -0.160541,-0.080615 z m 0,-0.1074869 q 0.165364,0 0.25976,0.1074869 0.09439,0.1074869 0.09439,0.297656 0,0.1894801 -0.09439,0.297656 -0.0944,0.1074866 -0.25976,0.1074866 -0.166054,0 -0.260449,-0.1074866 -0.09371,-0.1081759 -0.09371,-0.297656 0,-0.1901691 0.09371,-0.297656 0.09439,-0.1074869 0.260449,-0.1074869 z" /> + <path + d="m 60.861639,9.3491995 c -0.06767,0.014381 -0.121412,0.045485 -0.161224,0.093308 -0.03981,0.047478 -0.06012,0.1053918 -0.06096,0.1737306 -8.33e-4,0.068317 0.01793,0.1180412 0.05629,0.1491835 0.03881,0.030698 0.09224,0.038802 0.160293,0.024318 0.06714,-0.014289 0.120594,-0.045307 0.160382,-0.093062 0.0398,-0.047761 0.06014,-0.1056211 0.06104,-0.1735919 8.94e-4,-0.067652 -0.01805,-0.1170336 -0.05683,-0.148134 -0.03879,-0.031448 -0.09179,-0.040035 -0.158992,-0.025753 z m 0.001,-0.079638 c 0.109739,-0.023315 0.195568,-0.015076 0.257485,0.024704 0.0619,0.039766 0.09221,0.1065752 0.09094,0.2004072 -0.0013,0.093451 -0.03353,0.1734801 -0.0968,0.2401086 -0.06324,0.066277 -0.149653,0.111075 -0.259243,0.134405 -0.11006,0.02343 -0.196061,0.015327 -0.258004,-0.02432 -0.0615,-0.040098 -0.09171,-0.1068695 -0.0906,-0.2003352 0.0011,-0.093846 0.03309,-0.1739308 0.09593,-0.2402302 0.06331,-0.066407 0.15008,-0.1113236 0.26029,-0.1347387 z" + id="path86119" + inkscape:original-d="m 60.832343,9.3490344 q -0.101974,0 -0.16123,0.079926 -0.05926,0.079237 -0.05926,0.2177299 0,0.1384927 0.05857,0.2184189 0.05926,0.079237 0.161919,0.079237 0.101286,0 0.160542,-0.079926 0.05926,-0.079926 0.05926,-0.2177299 0,-0.1371147 -0.05926,-0.2170409 -0.05926,-0.080615 -0.160542,-0.080615 z m 0,-0.1074869 q 0.165365,0 0.25976,0.1074869 0.0944,0.1074869 0.0944,0.297656 0,0.1894801 -0.0944,0.297656 -0.09439,0.1074866 -0.25976,0.1074866 -0.166053,0 -0.260449,-0.1074866 -0.09371,-0.1081759 -0.09371,-0.297656 0,-0.1901691 0.09371,-0.297656 0.0944,-0.1074869 0.260449,-0.1074869 z" /> + <path + d="m 61.867335,9.1573455 c -0.01406,-0.00311 -0.02952,-0.00424 -0.04637,-0.00337 -0.01639,4.313e-4 -0.03463,0.00278 -0.05472,0.00705 -0.07123,0.015138 -0.126286,0.044134 -0.165147,0.086983 -0.0384,0.042407 -0.05806,0.095912 -0.05898,0.1605017 l -0.0043,0.300599 -0.126616,0.026953 0.008,-0.5710036 0.12678,-0.026937 -0.0013,0.088806 c 0.02699,-0.040331 0.06184,-0.073348 0.104562,-0.099048 0.04273,-0.026041 0.09446,-0.045514 0.155198,-0.058418 0.0087,-0.00184 0.01826,-0.00337 0.02875,-0.00458 0.01049,-0.00155 0.02212,-0.00283 0.03488,-0.00385 z" + id="path86121" + inkscape:original-d="m 61.843823,9.3786622 q -0.02136,-0.012402 -0.04685,-0.017915 -0.0248,-0.0062 -0.05512,-0.0062 -0.107487,0 -0.165365,0.07028 -0.05719,0.069591 -0.05719,0.2005044 V 10.031852 H 61.391826 V 9.260151 h 0.127469 v 0.1198892 q 0.03996,-0.07028 0.104042,-0.1040418 0.06408,-0.034451 0.155718,-0.034451 0.01309,0 0.02894,0.00207 0.01585,0.00138 0.03514,0.00482 z" /> + <path + d="m 62.479275,9.0262725 0.0051,-0.3093893 0.125969,-0.026744 -0.01329,0.7934913 -0.125738,0.026766 0.0014,-0.085534 c -0.02699,0.039571 -0.06089,0.071986 -0.101721,0.097249 -0.04036,0.024824 -0.0888,0.043251 -0.145312,0.055282 -0.09252,0.019697 -0.167539,0.00827 -0.225052,-0.034302 -0.05707,-0.042681 -0.08494,-0.1088637 -0.08358,-0.198564 0.0014,-0.089738 0.03144,-0.1683274 0.09025,-0.2357496 0.05928,-0.067532 0.135254,-0.1111459 0.227903,-0.13083 0.05659,-0.012023 0.104827,-0.013963 0.14471,-0.00582 0.04034,0.0077 0.07346,0.025753 0.09936,0.054144 z m -0.432196,0.290605 c -0.0011,0.068976 0.01702,0.1191282 0.05426,0.1504691 0.03769,0.030897 0.08981,0.03926 0.156361,0.025096 0.06655,-0.014163 0.119276,-0.044838 0.158197,-0.09203 0.03893,-0.047538 0.05897,-0.1057854 0.0601,-0.1747545 0.0011,-0.068991 -0.01713,-0.118972 -0.0548,-0.1499314 -0.03768,-0.031307 -0.08982,-0.039885 -0.156435,-0.025729 -0.06662,0.014158 -0.119409,0.04504 -0.158358,0.09264 -0.03848,0.047158 -0.05826,0.1052414 -0.05932,0.174239 z" + id="path86123" + inkscape:original-d="M 62.459805,9.3772841 V 8.9597389 h 0.12678 v 1.0721131 h -0.12678 V 9.9160966 q -0.03996,0.068902 -0.101286,0.1026634 -0.06063,0.03307 -0.146072,0.03307 -0.13987,0 -0.228065,-0.1116207 -0.0875,-0.111621 -0.0875,-0.2935219 0,-0.1819009 0.0875,-0.2935219 0.0882,-0.111621 0.228065,-0.111621 0.08544,0 0.146072,0.033762 0.06132,0.033073 0.101286,0.1019747 z m -0.432014,0.2694063 q 0,0.1398708 0.05719,0.2197969 0.05788,0.079237 0.158474,0.079237 0.100597,0 0.158475,-0.079237 0.05788,-0.079926 0.05788,-0.2197969 0,-0.1398708 -0.05788,-0.2191079 -0.05788,-0.079926 -0.158475,-0.079926 -0.100596,0 -0.158474,0.079926 -0.05719,0.079237 -0.05719,0.2191079 z" /> + <path + d="m 62.86587,8.8576892 0.125834,-0.026736 -0.01007,0.5708077 -0.125669,0.026751 z m 0.0039,-0.2226229 0.125899,-0.02673 -0.0021,0.1189958 -0.125864,0.026733 z" + id="path86125" + inkscape:original-d="m 62.847723,9.260151 h 0.126779 v 0.771701 h -0.126779 z m 0,-0.3004121 h 0.126779 v 0.1605413 h -0.126779 z" /> + <path + d="m 63.886573,8.8662942 -0.0068,0.3442745 -0.125508,0.026718 0.0066,-0.3412259 c 0.001,-0.054034 -0.01228,-0.091484 -0.03998,-0.1123421 -0.02771,-0.020861 -0.0698,-0.025293 -0.126271,-0.013292 -0.06786,0.014422 -0.121683,0.041948 -0.161458,0.082576 -0.03977,0.040624 -0.06018,0.088808 -0.06121,0.1445413 l -0.006,0.3223956 -0.126278,0.026881 0.01041,-0.5707761 0.126449,-0.026867 -0.0016,0.088771 c 0.03071,-0.040738 0.06649,-0.073919 0.10735,-0.099541 0.04132,-0.02572 0.08863,-0.044241 0.14192,-0.055564 0.0879,-0.018676 0.153996,-0.012392 0.198278,0.018843 0.04427,0.030888 0.06563,0.085762 0.06408,0.1646089 z" + id="path86127" + inkscape:original-d="m 63.881251,9.5660752 v 0.4657768 h -0.12678 V 9.5702093 q 0,-0.1095539 -0.04272,-0.1639864 -0.04272,-0.054432 -0.128157,-0.054432 -0.102664,0 -0.16192,0.065457 -0.05926,0.065457 -0.05926,0.1784558 V 10.031853 H 63.234951 V 9.260151 h 0.127469 v 0.1198892 q 0.04548,-0.069591 0.106798,-0.1040418 0.06201,-0.034451 0.142626,-0.034451 0.132981,0 0.201194,0.082682 0.06821,0.081993 0.06821,0.2418455 z" /> + <path + d="m 64.483051,8.7967868 c -0.101385,0.021562 -0.171816,0.045163 -0.211279,0.070802 -0.03947,0.025639 -0.05962,0.059342 -0.06048,0.1011044 -6.81e-4,0.033268 0.01332,0.056647 0.04202,0.07014 0.02915,0.013055 0.06894,0.014214 0.119387,0.00348 0.06953,-0.014797 0.125576,-0.044967 0.168156,-0.090514 0.04305,-0.045988 0.06523,-0.099539 0.06653,-0.1606607 l 4.47e-4,-0.020888 z m 0.251057,-0.091936 -0.0071,0.3253563 -0.125356,0.026685 0.0018,-0.086513 c -0.02936,0.040701 -0.06557,0.073906 -0.108624,0.099618 -0.04305,0.025372 -0.09547,0.044634 -0.157262,0.057789 -0.07816,0.016639 -0.140086,0.013611 -0.185783,-0.00909 -0.04525,-0.023141 -0.06732,-0.062204 -0.06621,-0.1171954 0.0013,-0.064174 0.03093,-0.1186671 0.0889,-0.163466 0.05843,-0.044899 0.14473,-0.079485 0.258871,-0.1037539 l 0.175956,-0.037411 1.96e-4,-0.00917 c 9.22e-4,-0.043156 -0.01746,-0.072404 -0.05516,-0.087739 -0.03724,-0.015774 -0.09021,-0.016365 -0.158893,-0.00177 -0.04368,0.00928 -0.08629,0.022231 -0.127852,0.038849 -0.04156,0.016619 -0.08162,0.03681 -0.120155,0.060572 l 0.0018,-0.086702 c 0.04623,-0.023031 0.09103,-0.04237 0.134397,-0.058017 0.04337,-0.015987 0.08553,-0.028331 0.126478,-0.03703 0.11055,-0.023487 0.192652,-0.019601 0.246308,0.011648 0.05364,0.031241 0.07951,0.090362 0.07763,0.1773426 z" + id="path86129" + inkscape:original-d="m 64.484831,9.6439343 q -0.153651,0 -0.212907,0.03514 -0.05926,0.03514 -0.05926,0.1198892 0,0.067524 0.0441,0.1074869 0.04479,0.039274 0.121267,0.039274 0.10542,0 0.168809,-0.074414 0.06408,-0.075103 0.06408,-0.1991263 v -0.02825 z M 64.7377,9.5915689 V 10.031852 H 64.610921 V 9.9147186 q -0.04341,0.07028 -0.108176,0.1040414 -0.06477,0.03307 -0.158474,0.03307 -0.118511,0 -0.188791,-0.066146 -0.06959,-0.066835 -0.06959,-0.1784558 0,-0.1302245 0.08682,-0.1963703 0.08751,-0.066146 0.260449,-0.066146 h 0.177767 v -0.012402 q 0,-0.087505 -0.05788,-0.1350476 -0.05719,-0.048231 -0.161231,-0.048231 -0.06615,0 -0.128846,0.015847 -0.0627,0.015847 -0.120579,0.047542 V 9.2952909 q 0.06959,-0.026872 0.135048,-0.039963 0.06546,-0.01378 0.127469,-0.01378 0.167431,0 0.250113,0.086816 0.08268,0.086816 0.08268,0.263205 z" /> + <path + d="m 65.125648,8.2160672 -0.0037,0.1622681 0.258334,-0.054888 -0.0017,0.072926 -0.258291,0.054892 -0.007,0.3098046 c -0.001,0.0465 0.0067,0.074577 0.02317,0.084236 0.01695,0.00956 0.05153,0.00879 0.103729,-0.00232 l 0.128668,-0.027383 -0.0018,0.078356 -0.128644,0.027385 c -0.09667,0.020578 -0.163093,0.021385 -0.199263,0.00241 -0.03617,-0.019313 -0.05346,-0.0646 -0.05187,-0.1358753 l 0.0069,-0.3098137 -0.09204,0.019562 0.0016,-0.072934 0.09206,-0.01956 0.0036,-0.1622724 z" + id="path86131" + inkscape:original-d="M 65.12424,9.0410431 V 9.260151 h 0.261138 v 0.09853 H 65.12424 v 0.4189233 q 0,0.094396 0.02549,0.1212673 0.02618,0.026872 0.10542,0.026872 h 0.130224 V 10.031853 H 65.25515 q -0.146761,0 -0.202572,-0.054433 -0.05581,-0.055121 -0.05581,-0.1998154 v -0.418924 h -0.09302 v -0.09853 h 0.09302 V 9.0410431 Z" /> + <path + d="m 66.191082,8.4117557 -0.0011,0.045837 -0.575701,0.1224442 c 0.0039,0.063339 0.02863,0.1070484 0.07408,0.1311386 0.04592,0.023645 0.110373,0.026633 0.193362,0.00897 0.04807,-0.01023 0.09465,-0.024531 0.139754,-0.042903 0.04556,-0.018468 0.09077,-0.04125 0.135635,-0.068345 l -0.0022,0.08853 c -0.04523,0.023794 -0.0915,0.044438 -0.138831,0.061934 -0.04733,0.017497 -0.09525,0.031409 -0.14376,0.041736 -0.121519,0.02587 -0.217259,0.019934 -0.28722,-0.017819 -0.06953,-0.037864 -0.10325,-0.1019395 -0.101137,-0.1922464 0.0022,-0.093402 0.03753,-0.1746164 0.106023,-0.2436203 0.06897,-0.069451 0.16068,-0.1163376 0.275105,-0.1406482 0.102603,-0.021799 0.183019,-0.014195 0.241243,0.022801 0.05867,0.036549 0.08693,0.097285 0.08481,0.182192 z m -0.124504,-8.861e-4 c 3.48e-4,-0.051092 -0.01793,-0.08793 -0.05482,-0.1105081 -0.03646,-0.022676 -0.08556,-0.027457 -0.147295,-0.014337 -0.06991,0.014857 -0.126336,0.041558 -0.169266,0.0801 -0.04247,0.038443 -0.06753,0.085179 -0.07516,0.140202 z" + id="path86133" + inkscape:original-d="m 66.2122,9.6143065 v 0.062012 h -0.582909 q 0.0083,0.1309135 0.07855,0.1998154 0.07097,0.068213 0.197059,0.068213 0.07304,0 0.141249,-0.017914 0.0689,-0.017915 0.136425,-0.053743 v 0.1198892 q -0.06821,0.028938 -0.13987,0.044097 -0.07166,0.01516 -0.145383,0.01516 -0.184657,0 -0.292833,-0.1074852 -0.107487,-0.1074869 -0.107487,-0.2907658 0,-0.1894801 0.101975,-0.3004121 0.102663,-0.111621 0.276296,-0.111621 0.155718,0 0.24598,0.1005967 0.09095,0.099908 0.09095,0.2721623 z m -0.126779,-0.037207 q -0.0014,-0.1040418 -0.05857,-0.1660535 -0.0565,-0.062012 -0.150206,-0.062012 -0.106109,0 -0.170187,0.059945 -0.06339,0.059945 -0.07304,0.1688095 z" /> + <path + d="m 67.330983,7.9257188 -0.0025,0.088686 c -0.03495,-0.00608 -0.07137,-0.00847 -0.10924,-0.00718 -0.03787,0.00129 -0.0772,0.00627 -0.117981,0.014939 -0.06209,0.013194 -0.108959,0.030251 -0.14061,0.051167 -0.0312,0.02082 -0.04718,0.045499 -0.04794,0.074034 -5.8e-4,0.021739 0.01006,0.03653 0.03193,0.044376 0.02187,0.00751 0.06618,0.00973 0.132927,0.00668 l 0.04261,-0.00197 c 0.08838,-0.00462 0.150772,0.0022 0.187181,0.020435 0.03686,0.017801 0.05465,0.049944 0.05336,0.096425 -0.0015,0.052914 -0.03069,0.1007673 -0.08765,0.1435661 -0.05651,0.042699 -0.133639,0.074453 -0.231401,0.095265 -0.04074,0.00867 -0.08321,0.01468 -0.12741,0.018024 -0.04377,0.00359 -0.08994,0.00465 -0.13853,0.00319 l 0.0026,-0.096659 c 0.04572,0.00815 0.09088,0.012028 0.135463,0.011644 0.04459,-7.224e-4 0.08884,-0.00576 0.132757,-0.015104 0.05885,-0.012525 0.104318,-0.029619 0.136412,-0.051284 0.0321,-0.022005 0.04853,-0.046744 0.04929,-0.07422 6.98e-4,-0.025444 -0.01031,-0.042497 -0.03303,-0.051158 -0.02227,-0.00876 -0.07195,-0.01118 -0.14905,-0.00727 l -0.04328,0.00161 c -0.07713,0.00425 -0.132582,-0.00252 -0.166348,-0.020316 -0.03377,-0.018142 -0.05007,-0.049288 -0.0489,-0.093443 0.0014,-0.053677 0.0279,-0.1005285 0.07945,-0.1405455 0.05155,-0.04002 0.12402,-0.06995 0.217393,-0.089788 0.04623,-0.00982 0.08967,-0.016516 0.130312,-0.020082 0.04064,-0.00357 0.07804,-0.00391 0.112189,-0.00103 z" + id="path86135" + inkscape:original-d="m 67.360794,9.2828886 v 0.1198892 q -0.05374,-0.027561 -0.111621,-0.041341 -0.05788,-0.01378 -0.119889,-0.01378 -0.0944,0 -0.141938,0.028939 -0.04685,0.028939 -0.04685,0.086816 0,0.044097 0.03376,0.069591 0.03376,0.024805 0.135736,0.047542 l 0.04341,0.00965 q 0.135048,0.028939 0.191548,0.081993 0.05719,0.052365 0.05719,0.1467609 0,0.1074869 -0.08544,0.1701876 -0.08475,0.0627 -0.233577,0.0627 -0.06201,0 -0.129536,-0.0124 -0.06684,-0.01171 -0.141249,-0.03583 V 9.8726885 q 0.07028,0.036518 0.138493,0.055121 0.06821,0.017914 0.135048,0.017914 0.08957,0 0.137803,-0.030317 0.04823,-0.031006 0.04823,-0.086816 0,-0.051676 -0.03514,-0.079237 -0.03445,-0.027561 -0.152273,-0.053055 l -0.0441,-0.010335 q -0.117822,-0.024805 -0.170187,-0.075792 -0.05237,-0.051676 -0.05237,-0.1412488 0,-0.1088649 0.07717,-0.1681205 0.07717,-0.059256 0.219108,-0.059256 0.07028,0 0.132292,0.010335 0.06201,0.010335 0.114377,0.031006 z" /> + <path + d="m 67.869797,8.4137452 c -0.03721,0.07527 -0.07284,0.1267909 -0.106882,0.1545756 -0.03404,0.027783 -0.07908,0.047643 -0.135132,0.059583 l -0.09968,0.021235 0.0022,-0.078239 0.07325,-0.015599 c 0.03436,-0.00732 0.06121,-0.019097 0.08054,-0.035339 0.01934,-0.016238 0.04118,-0.049514 0.06554,-0.099835 l 0.02361,-0.047474 -0.291623,-0.4956695 0.132481,-0.028148 0.224856,0.3955942 0.250509,-0.4965942 0.132365,-0.028123 z" + id="path86137" + inkscape:original-d="m 67.9251,10.10351 q -0.05374,0.137803 -0.104731,0.179834 -0.05099,0.04203 -0.136425,0.04203 h -0.101286 v -0.106109 h 0.07441 q 0.05236,0 0.0813,-0.02481 0.02894,-0.0248 0.06408,-0.117133 l 0.02274,-0.05788 -0.312125,-0.759298 h 0.134359 l 0.241156,0.6035802 0.241157,-0.6035802 h 0.134358 z" /> + <path + d="m 68.878015,7.5970049 -0.0028,0.088655 c -0.03483,-0.00609 -0.07112,-0.0085 -0.108887,-0.00722 -0.03777,0.00128 -0.07699,0.00624 -0.117685,0.014887 -0.06194,0.013164 -0.108736,0.030196 -0.140376,0.051094 -0.03118,0.020801 -0.0472,0.045465 -0.04807,0.07399 -6.57e-4,0.021731 0.0099,0.036522 0.03167,0.044374 0.02178,0.00751 0.06595,0.00976 0.132507,0.00673 l 0.04249,-0.00195 c 0.08813,-0.00458 0.150314,0.00226 0.186547,0.020503 0.03669,0.01781 0.05431,0.049949 0.05285,0.096414 -0.0017,0.052896 -0.03096,0.1007216 -0.08791,0.1434834 -0.0565,0.042663 -0.133511,0.074375 -0.231057,0.095141 -0.04065,0.00865 -0.08301,0.014642 -0.127096,0.017967 -0.04364,0.00357 -0.08968,0.00461 -0.138127,0.00314 l 0.0029,-0.096626 c 0.04556,0.00816 0.09056,0.01206 0.135015,0.011695 0.04446,-7.044e-4 0.0886,-0.00572 0.132417,-0.015046 0.05872,-0.012497 0.104115,-0.029568 0.136193,-0.051213 0.03209,-0.021984 0.04856,-0.046709 0.04941,-0.074175 7.88e-4,-0.025435 -0.01013,-0.042487 -0.03275,-0.051154 -0.02217,-0.00876 -0.07169,-0.011205 -0.148579,-0.00732 l -0.04315,0.00159 c -0.07692,0.00422 -0.132178,-0.00257 -0.16578,-0.020376 -0.0336,-0.018149 -0.04974,-0.049291 -0.04842,-0.093431 0.0016,-0.053659 0.02818,-0.1004837 0.07972,-0.1404668 0.05154,-0.039986 0.123904,-0.069878 0.217071,-0.089672 0.04613,-0.0098 0.08946,-0.016474 0.129994,-0.020023 0.04053,-0.00355 0.07782,-0.00388 0.111859,-9.838e-4 z" + id="path86139" + inkscape:original-d="m 68.931067,9.2828886 v 0.1198892 q -0.05374,-0.027561 -0.111621,-0.041341 -0.05788,-0.01378 -0.119889,-0.01378 -0.09439,0 -0.141938,0.028939 -0.04685,0.028939 -0.04685,0.086816 0,0.044097 0.03376,0.069591 0.03376,0.024805 0.135737,0.047542 l 0.04341,0.00965 q 0.135047,0.028939 0.191547,0.081993 0.05719,0.052365 0.05719,0.1467609 0,0.1074869 -0.08544,0.1701876 -0.08475,0.0627 -0.233577,0.0627 -0.06201,0 -0.129536,-0.0124 -0.06683,-0.01171 -0.141248,-0.03583 V 9.8726885 q 0.07028,0.036518 0.138492,0.055121 0.06821,0.017914 0.135048,0.017914 0.08957,0 0.137804,-0.030317 0.04823,-0.031006 0.04823,-0.086816 0,-0.051676 -0.03514,-0.079237 -0.03445,-0.027561 -0.152273,-0.053055 l -0.0441,-0.010335 q -0.117822,-0.024805 -0.170188,-0.075792 -0.05237,-0.051676 -0.05237,-0.1412488 0,-0.1088649 0.07717,-0.1681205 0.07717,-0.059256 0.219108,-0.059256 0.07028,0 0.132291,0.010335 0.06201,0.010335 0.114377,0.031006 z" /> + <path + d="m 69.246421,7.3410082 -0.0052,0.162119 0.256818,-0.054566 -0.0024,0.072859 -0.256775,0.05457 -0.0099,0.3095211 c -0.0015,0.046458 0.0059,0.074518 0.02218,0.084186 0.01672,0.00957 0.05103,0.00883 0.10293,-0.00221 l 0.127914,-0.027222 -0.0026,0.078284 -0.127891,0.027225 c -0.0961,0.020458 -0.162007,0.021193 -0.197709,0.0022 -0.0357,-0.019334 -0.05242,-0.064599 -0.05016,-0.1358095 l 0.0098,-0.3095304 -0.0915,0.019447 0.0023,-0.072867 0.09152,-0.019445 0.0051,-0.1621233 z" + id="path86141" + inkscape:original-d="M 69.299692,9.0410431 V 9.260151 h 0.261138 v 0.09853 h -0.261138 v 0.4189233 q 0,0.094396 0.02549,0.1212673 0.02618,0.026872 0.10542,0.026872 h 0.130224 v 0.1061094 h -0.130224 q -0.146761,0 -0.202572,-0.054433 Q 69.17222,9.922299 69.17222,9.7776046 V 9.3586806 H 69.0792 v -0.09853 h 0.09302 V 9.0410431 Z" /> + <path + d="m 70.30154,7.5376483 -0.0016,0.045794 -0.572325,0.1217262 c 0.0033,0.063287 0.02737,0.1069836 0.07223,0.1311005 0.04533,0.023672 0.109243,0.026726 0.191746,0.00917 0.04779,-0.01017 0.09414,-0.024409 0.139062,-0.042717 0.04537,-0.018404 0.09045,-0.041117 0.135221,-0.068141 l -0.003,0.088449 c -0.0451,0.023725 -0.09121,0.044302 -0.13833,0.061733 -0.04713,0.017431 -0.0948,0.03128 -0.143025,0.041547 -0.120807,0.025718 -0.215732,0.019687 -0.284776,-0.018107 -0.06862,-0.037904 -0.101452,-0.1019583 -0.09849,-0.1921827 0.0031,-0.093317 0.03891,-0.174421 0.107529,-0.2432909 0.06909,-0.069316 0.160528,-0.116064 0.274282,-0.1402318 0.102001,-0.021671 0.181707,-0.013989 0.239115,0.023036 0.05785,0.036578 0.08531,0.09729 0.08238,0.1821194 z m -0.12351,-0.00102 c 8.36e-4,-0.051046 -0.01694,-0.087871 -0.05333,-0.1104675 -0.03596,-0.022695 -0.08462,-0.027523 -0.145992,-0.01448 -0.0695,0.01477 -0.125736,0.041388 -0.168698,0.07985 -0.04251,0.038363 -0.06781,0.085032 -0.07591,0.1399975 z" + id="path86143" + inkscape:original-d="m 70.387653,9.6143065 v 0.062012 h -0.582909 q 0.0083,0.1309135 0.07855,0.1998154 0.07097,0.068213 0.197059,0.068213 0.07304,0 0.141249,-0.017914 0.0689,-0.017915 0.136426,-0.053743 v 0.1198892 q -0.06821,0.028938 -0.139871,0.044097 -0.07166,0.01516 -0.145383,0.01516 -0.184657,0 -0.292833,-0.1074852 -0.107487,-0.1074869 -0.107487,-0.2907658 0,-0.1894801 0.101975,-0.3004121 0.102664,-0.111621 0.276296,-0.111621 0.155719,0 0.24598,0.1005967 0.09095,0.099908 0.09095,0.2721623 z m -0.126779,-0.037207 q -0.0014,-0.1040418 -0.05857,-0.1660535 -0.0565,-0.062012 -0.150206,-0.062012 -0.106108,0 -0.170187,0.059945 -0.06339,0.059945 -0.07304,0.1688095 z" /> + <path + d="m 71.100593,7.2167201 c 0.03261,-0.0487 0.07092,-0.087664 0.114901,-0.1168888 0.04399,-0.029225 0.09526,-0.05006 0.153824,-0.062502 0.07883,-0.016748 0.138853,-0.00878 0.180077,0.023889 0.04123,0.032323 0.0604,0.086829 0.05753,0.163504 l -0.01288,0.3436846 -0.124808,0.026568 0.01267,-0.3406412 c 0.002,-0.05462 -0.0093,-0.092442 -0.03398,-0.1134583 -0.02468,-0.02102 -0.06338,-0.025933 -0.116073,-0.014733 -0.06441,0.013689 -0.115903,0.040631 -0.154469,0.080824 -0.03856,0.04019 -0.05885,0.088107 -0.06088,0.1437449 l -0.0117,0.3218423 -0.124886,0.026585 0.01229,-0.3406794 c 0.002,-0.054966 -0.0094,-0.092791 -0.03413,-0.113468 -0.02473,-0.02102 -0.06391,-0.025832 -0.117552,-0.014433 -0.06355,0.013506 -0.114619,0.040532 -0.153188,0.081074 -0.03855,0.040199 -0.0588,0.087954 -0.06075,0.1432587 l -0.01134,0.3218777 -0.124983,0.026606 0.01991,-0.5698579 0.125144,-0.026589 -0.0031,0.088627 c 0.02964,-0.041008 0.06459,-0.074048 0.104853,-0.099119 0.04026,-0.025071 0.08767,-0.043401 0.142221,-0.054991 0.05499,-0.011684 0.101265,-0.011067 0.138814,0.00185 0.038,0.012817 0.0655,0.037293 0.08252,0.073424 z" + id="path86145" + inkscape:original-d="m 71.196561,9.40829 q 0.04754,-0.085438 0.113688,-0.1260904 0.06615,-0.040652 0.155718,-0.040652 0.120578,0 0.186035,0.084749 0.06546,0.08406 0.06546,0.2397785 V 10.031852 H 71.589991 V 9.5702093 q 0,-0.110932 -0.03928,-0.1646754 -0.03927,-0.053743 -0.119889,-0.053743 -0.09853,0 -0.155718,0.065457 -0.05719,0.065457 -0.05719,0.1784558 V 10.031853 H 71.090452 V 9.5702093 q 0,-0.111621 -0.03927,-0.1646754 -0.03927,-0.053743 -0.121267,-0.053743 -0.09715,0 -0.15434,0.066146 -0.05719,0.065457 -0.05719,0.1777668 V 10.031853 H 70.590914 V 9.260151 h 0.127468 v 0.1198892 q 0.04341,-0.070969 0.104042,-0.1047308 0.06063,-0.033762 0.144005,-0.033762 0.08406,0 0.142627,0.042719 0.05926,0.042719 0.08751,0.1240234 z" /> + </g> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" + x="9.8286581" + y="9.82693" + id="text73128-2"><tspan + sodipodi:role="line" + style="font-size:1.41111px;fill:#000000;stroke:none;stroke-width:1" + x="9.8286581" + y="9.82693" + id="tspan81002-8">viewport coordinate system</tspan></text> + </g> +</svg> diff --git a/share/extensions/docs/authors/samples/units1.svg b/share/extensions/docs/authors/samples/units1.svg new file mode 100644 index 0000000..b221eda --- /dev/null +++ b/share/extensions/docs/authors/samples/units1.svg @@ -0,0 +1,4 @@ +<svg xmlns='http://www.w3.org/2000/svg' + width="200" height="100"> + <rect x="0" y="0" width="200" height="100" fill="#aaa"/> +</svg>
\ No newline at end of file diff --git a/share/extensions/docs/authors/samples/units2.svg b/share/extensions/docs/authors/samples/units2.svg new file mode 100644 index 0000000..cf2fe17 --- /dev/null +++ b/share/extensions/docs/authors/samples/units2.svg @@ -0,0 +1,9 @@ +<svg xmlns='http://www.w3.org/2000/svg' + width="84mm" height="56mm" viewBox="0 0 84 56" fill="none"> + <rect x="0" y="0" width="84" height="56" stroke="orange" stroke-width="2px"/> + <path d="M 0, 14 H 84" stroke="black" stroke-width="0.2px"/> + <path d="M 21, 0 V 56" stroke="black" stroke-width="0.2px"/> + <circle id="c1" r="2" cx="21" cy="14" stroke="red" stroke-width="0.5"/> + <circle id="c2" r="4px" cx="21px" cy="14px" stroke="green" stroke-width="0.5px"/> + <circle id="c3" r="0.5mm" cx="21mm" cy="14mm" stroke="blue" stroke-width="0.5mm"/> +</svg>
\ No newline at end of file diff --git a/share/extensions/docs/authors/submit.rst b/share/extensions/docs/authors/submit.rst new file mode 100644 index 0000000..c140009 --- /dev/null +++ b/share/extensions/docs/authors/submit.rst @@ -0,0 +1,97 @@ +Submitting and reviewing extensions +=================================== + +This page details how extensions can be submitted to and moderated on +the Inkscape website. + +I want to submit my extension +----------------------------- + +Go through each of these actions and check to make sure your extension +is ready to be made available in Inkscape: + +#. Check for limitations + + * Your extension must not contact the internet (unless exempted for a good reason) + * It must not self-update, or edit files in the config directory. + * It must be readable code, in English. Code in other languages or too obscure may not be accepted. + +#. Check the license of your code + + * Your code must be Free and Open Source. Using one of the available licenses such + as GPL, AGPL, MIT, Apache2 etc. + * Every included dependency must be also Free and Open Source. + +#. Check all of your dependencies + + * Your extension MUST be python based (except for template extensions) + * It MUST work with python 3.6 or later + * Any dependency not shipped with Inkscape MUST be packaged along side your + extension. For example jinja2 would be included in a folder. + +#. Create a zip file of your extension and any external depdencies. + + * Include only one copy in the root of the zip file. + * No specific versions for windows or linux, macOS. + +#. Check which versions of Inkscape it works with (each one, make a note for tagging + later) + + * set the variable "INKSCAPE_PROFILE_DIR=/tmp/folder" + * run the inkscape version + * open the extensions manager + * install the zip file you hope to submit (second tab, folder button at the bottom) + * Your extension MUST work with at least one version of Inkscape. + +#. Sign your zip file + + * Use GnuPG to sign your zip file, use the same signature as the public key you + uploaded to inkscape.org + * OR use md5hash to create a less secure md5 signature of the zip file. Make sure + you have some text in your inkscape.org gnupg key profile setting so you see the + signature field when uploading. + +#. Upload the zip file to the extensions category in the website. + + * Include the generated signature + * Title and description in English with as much detail as possible + * Add Inkscape versions as you tested above. + * Include a link to the Git repository. + * Include an icon and screenshot file. + +#. Send a message to the Inkscape extensions team on `RocketChat`_ asking for a review. + +.. _RocketChat: https://chat.inkscape.org/channel/inkscape_extensions + +I want to review a submission +----------------------------- + +Extensions Reviewer Checklist +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- ☐ Take next popular extension [#]_ or request to review +- ☐ Check for existing verification signature +- ☐ Contact author to inform about review +- ☐ Unpack zip to extensions folder +- ☐ Check zip contents for inx and py file +- ☐ Check for license header and/or file +- ☐ Run pytest and record test coverage +- ☐ Run pylint to get code quality score +- ☐ Visually confirm no mallicious or internet code +- ☐ If no tests, add simple test upstream [#]_ +- ☐ Install zip using extensions manager +- If everything is correct … +- ☐ Add version tags and any other tags +- ☐ Edit description, title, logos to improve presentation +- ☐ contact a website administrator to complete + +If everything is correct (must be admin): +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- ☐ Add testing and quality scores to decription +- ☐ Generate signature key and upload +- ☐ Generate md5 if package is not self-signed + +.. [#] https://inkscape.org/gallery/=extension/ + +.. [#] Add simple inkex.tester comparision test
\ No newline at end of file diff --git a/share/extensions/docs/authors/unit-tests.rst b/share/extensions/docs/authors/unit-tests.rst new file mode 100644 index 0000000..3384d59 --- /dev/null +++ b/share/extensions/docs/authors/unit-tests.rst @@ -0,0 +1,67 @@ +.. _unittests: + +Writing unit tests +================== + +All Inkscape extensions should come with tests. This package provides you with +the tools needed to create tests and thus ensure that your extension continues +to work with future versions of Inkscape, the "inkex" python modules, and other +python and non-python tools you may use. + +Make sure your extension is a python extension and is using the +:py:mod:`inkex.extensions` base classes. These provide the greatest amount of +functionality for testing. + +You should start by creating a folder in your repository called ``tests`` with +an empty file inside called ``__init__.py`` to turn it into a module folder. + +For each of your extensions, you should create a file called +``test_{extension_name}.py`` where the name reflects the name of your extension. + +There are two types of tests: + +1. Full-process Comparison tests - These are tests which invoke your + extension with various arguments and attempt to compare the + output to a known good reference. These are useful for testing + that your extension would work if it was used in Inkscape. + + Good example of writing comparison tests can be found in the + Inkscape core repository, each test which inherits from + the ComparisonMixin class is running comparison tests. + +2. Unit tests - These are individual test functions which call out to + specific functions within your extension. These are typical + python unit tests and many good python documents exist + to describe how to write them well. For examples here you + can find the tests that test the inkex modules themselves + to be the most instructive. + +When running a test, it will cause a certain fraction of the code within the +extension to execute. This fraction called it's **coverage** and a higher +coverage score indicates that your test is better at exercising the various +options, features, and branches within your code. + +.. versionadded:: 1.2 + ``EXPORT_COMPARE`` environment variable + +Generating comparison output can be done using the EXPORT_COMPARE environment +variable when calling pytest and comes in 3 modes, the first of which is the +CHECK comparisons mode:: + + EXPORT_COMPARE=1 pytest tests/test_my_specific_test.py + +This will create files in ``tests/data/refs/*.{ext}`` and these files +should be manually checked to make sure they are correct. Once you are happy +with the output you can re-run the test with the WRITE comparisons mode:: + + EXPORT_COMPARE=2 pytest tests/test_my_specific_test.py + +Which will create an output file of the right name and then run the test suite +against it. But only if the file doesn't already exist. The final mode is the +OVERWRITE comparisons mode:: + + EXPORT_COMPARE=3 pytest tests/test_my_specific_test.py + +This is like mode 2, but will over-write any existing files too. This allows +you to update the test compare files. + diff --git a/share/extensions/docs/authors/units.rst b/share/extensions/docs/authors/units.rst new file mode 100644 index 0000000..055fbfd --- /dev/null +++ b/share/extensions/docs/authors/units.rst @@ -0,0 +1,316 @@ +.. _units: + +Units +================= + +If you are reading this page, you are probably confused about how units work in Inkscape, inkex and +SVG in general. This is understandable, since there's quite a bit of conflicting information online. + +Units in SVG +------------ + +SVG means "scalable vector graphics". This introduces an inherent difficulty with how to map units +to the real world. Should units be pixels? Millimeters? Something else? The answer to this depends +on the output format you're targeting. + +The authors of the SVG specification solved this problem by introducing an abstract "dimensionless" +unit called **user units**. The SVG1.1 specification [1]_ is quite clear about their definition: + + *One px unit is defined to be equal to one user unit. + Thus, a length of "5px" is the same as a length of "5".* + +So whenever you read "user unit", think "pixel". And when you encounter a coordinate without unit, +it's specified in user units, i.e. pixels. You might have heard or read something like "I can choose +the unit of a document, so that one user unit equals one millimeter". This statement is misleading, +although not entirely wrong. It will be explained below. + +An `<svg>` tag has two different properties that influence its size and the mapping of coordinates. +These are called *viewport coordinate system* and *user coordinate system*. + +And as the name indicates, **user units always refer to the user coordinate system**. So for +the next section which explains the **viewport coordinate system**, forget user units. + +Viewport coordinate system +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The viewport coordinate system is [2]_ + + *[...] a top-level SVG viewport that establishes a mapping between the coordinate system used by the + containing environment (for example, CSS pixels in web browsers) and user units.* + +The viewport coordinate system is established by the ``width`` and ``height`` attributes of the SVG tag. +To reformulate the quote above: The viewport tells the SVG viewer how big the visible part of the +canvas should be *rendered*. It may be ``200px x 100px`` on your screen (``width="200px" height="100px"``) +or ``210mm x 297mm`` (``width="210mm" height="297mm"``), i.e. one A4 page. + + *If the width or height presentation attributes on the outermost svg element are in user units + (i.e., no unit identifier has been provided), then the value is assumed to be equivalent to the + same number of "px" units.* [3]_ + +Expressed in simple terms: if no unit has been specified in the ``width`` or ``height`` attributes, +assume the user means pixels. Otherwise, the unit is converted by the SVG viewer. Inkscape uses a +DPI of 96 px/in, and corresponding conversions for mm, yd etc. are used. + +Consider the following SVG file: + +.. code-block:: XML + + <svg xmlns='http://www.w3.org/2000/svg' width="200" height="100"> + <rect x="0" y="0" width="200" height="100" fill="#aaa"/> + </svg> + +which renders as follows: + +.. image:: samples/units1.svg + +If your browser zoom is set to 100%, this image should have a size of 100 times 200 pixels, +and is filled with a grey rectangle. You can verify this by taking a screenshot. + +Likewise, in ``mm`` based documents, you might see code such as +``width="210mm" height="297mm"`` which tells an standard-compliant program that if printed or +exported to PDF, the document should span an entire A4 page. + +User coordinate system +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You may have noticed that we didn't explicitly specify in the above svg that we want to draw +everything within the area with the coordinates ``0 ≤ x ≤ 200`` and ``0 ≤ y ≤ 100``. This was +done for us automatically since we specified ``width`` and ``height``. The ``viewBox`` attribute +allows to change this. + +Again from the specification [4]_: + + *The effect of the viewBox attribute is that the user agent automatically supplies the + appropriate transformation matrix to map the specified rectangle in user coordinate system + to the bounds of a designated region (often, the SVG viewport).* + +Let's break this down. Imagine the ``viewBox`` attribute as a camera that moves over the infinite +canvas. It can zoom in or out and move around - but whatever image the camera outputs, it is +rendered in the rectangle defined by ``width`` and ``height``, i.e. the viewport. Initially, the +camera is located such that the region ``viewBox="0 0 width height"`` is pictured. We may +however modify the viewBox as we wish. + +In a ``mm`` based documents, where we specified ``width="210mm" height="297mm"``, the viewbox is +initially ``viewBox="0 0 793.7 1122.5"`` due to the conversion from mm to px. This means that the +bottom right corner is at ``(210, 297) mm * 1/25.4 in/mm * 96 px/in ≈ (793.7, 1122.5) px``. + +As already mentioned: no units means user unit means pixels. So a rectangle with +``x="793.7" y="1122.5"`` (no units specified) is at the bottom right corner of the page. It would be +nicer if unitless values would be implicitly in millimeters, so we could specify such a rectangle +with ``x="210" y="297"``. This can be done with the ``viewBox`` attribute and will be explained with +an example SVG. + +Let's say we want to design a business card that should eventually be *printed on 84mm x 56mm*, so +we specifiy ``width="84mm" height="56mm"```. We also want the user units to behave like real-world +millimeters, so we have to zoom the viewbox camera: ``viewBox="0 0 84 56"``. As mentioned above, +no units means px, so these attributes together tell the SVG viewer "move the camera in such a way +that (84, 56) in user units, i.e. px, is the bottom right corner, and scale the image such that when +printed or rendered it has a size of 84mm by 56mm". + +You can imagine this situation like this [5]_: + +.. image:: samples/unit_camera.svg + +To illustrate this, we draw a crosshair at ``(14, 21)`` (note: no units in the path specification!), +i.e. a fourth horizontally and vertically for reference. Then we draw three circles: one at +``(21, 14)``, one at ``(21px, 14px)`` and one at ``(21mm, 14mm)``. + +.. code-block:: XML + + <svg xmlns='http://www.w3.org/2000/svg' width="84mm" height="56mm" viewBox="0 0 84 56" fill="none"> + <rect x="0" y="0" width="84" height="56" stroke="orange" stroke-width="2px"/> + <path d="M 0, 14 H 84" stroke="black" stroke-width="0.2px"/> + <path d="M 21, 0 V 56" stroke="black" stroke-width="0.2px"/> + <circle id="c1" r="2" cx="21" cy="14" stroke="red" stroke-width="0.5"/> + <circle id="c2" r="4px" cx="21px" cy="14px" stroke="green" stroke-width="0.5px"/> + <circle id="c3" r="0.5mm" cx="21mm" cy="14mm" stroke="blue" stroke-width="0.5mm"/> + </svg> + +.. image:: samples/units2.svg + +The rendered image at 100% browser resolution should be approximatly ``85mm`` by ``56mm``, but this +highly depends on your screen resolution. + +Note that the first two circles specified without unit +(i.e. user units) and specified in px are at the correct position and identical except for radius +and stroke color. + +The third circle's coordinates, radius and stroke-width are specified in mm. It should be located +somewhere near the bottom right corner (where exactly depends on the DPI conversion of your browser, +but most browsers use ``96dpi = 96 px/in`` today, which yields a conversion factor of approx. +``3.77px/mm``). The stroke is thicker by the same factor and the radius has been reduced to be +comparable to the first circle. + +This is somewhat unintuitive. Didn't we create a mm based document? Now we can explain the +statement from the introduction +"I can choose the unit of a document, so that one user unit equals one millimeter". +We didn't change the core statement "no unit = user unit = pixels" by specifying width and +height in mm. But the special choice of the viewbox attribute - the same width and height, but +without the unit) makes the following statement true: "**One user unit looks like one millimeter on +the output device** (e.g. screen or paper)". + +Now you understand why appending "mm" to the circle's position moved it. The transformation px->mm +has been applied twice! Once in the coordinate specification itself, and once by the "camera". + + +Units in Inkex +----------------- + +As an extension autor, you may have four different questions regarding units. + +What is the position of this object [in the user coordinate system]? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This is a question that typically needs to be answered if you want to position an object relative +to other objects, whose coordinates may be specified in a different unit. + +The most convenient way to deal with this is to get rid of the units, and that means converting +everything to user units. + +Each :class:`BaseElement <inkex.elements._base.BaseElement>` has a method +:meth:`to_dimensionless <inkex.elements._base.BaseElement.to_dimensionless>`. This method parses a +``length`` value and returns it, converted to px (user units). + +:meth:`~inkex.elements._base.BaseElement.to_dimensionless` fulfils the following task: +**Convert this string from the XML into a number, while processing the unit. +When using this function on any SVG attribute and replacing the +original value with the result, the output doesn't change visually.** + +In these and the following examples, the above "business card" SVG will be used. + +>>> svg = inkex.load_svg("docs/samples/units2.svg").getroot() +>>> svg.to_dimensionless(svg.getElementById("c1").get("cx")) +21.0 +>>> svg.to_dimensionless(svg.getElementById("c2").get("cx")) +21.0 +>>> svg.to_dimensionless(svg.getElementById("c3").get("cx")) +79.370078 + +For some classes, e.g. :class:`Rectangle <inkex.elements._polygons.Rectangle>`, convenience +properties are available which do the conversion for you, e.g. +:attr:`Rectangle.left <inkex.elements._polygons.RectangleBase.left>`. Similarly there are some +properties for circles: + +>>> svg.getElementById("c3").center +Vector2d(79.3701, 52.9134) +>>> svg.getElementById("c2").radius +4.0 + +What is the dimension of an object in a specified unit in the user coordinate system? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can also convert from user units to any unit. This is done using +:meth:`BaseElement.to_dimensional <inkex.elements._base.BaseElement.to_dimensional>`. + +>>> svg.to_dimensional(svg.getElementById("c2").radius, "px") +4.0 +>>> svg.to_dimensional(svg.getElementById("c2").radius, "mm") +1.0583333333333333 + +What is the dimension of an object on the viewport in arbitrary units? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This is useful if you want to draw a property of a shape (for example its area) as text on the +canvas, in a unit specified by the user. The default unit to convert to is px. + +The method for this is called :meth:`BaseElement.unit_to_viewport <inkex.elements._base.BaseElement.unit_to_viewport>`. + +>>> svg.unit_to_viewport(svg.getElementById("c2").radius) +15.118110236220472 +>>> svg.unit_to_viewport(svg.getElementById("c2").radius, "mm") +4.0 +>>> svg.unit_to_viewport("4", "mm") +4.0 + +In other words, ``unit_to_viewport(value, unit="px")`` answers the following +question: **What does the the width/height widget of the selection +tool (set to** ``unit`` **) show when selecting an element with width** +``value`` **as defined in the SVG?** Consider again +``<svg width="210mm" viewBox="0 0 105 147.5"><rect width="100" height="100"/></svg>`` +, i.e. a "mm-based" document with scale=2. When selecting this rectangle, the rectangle tool +shows ``viewport_to_unit("100", unit="mm") = 200``, if the rectangle tool is set to mm. + +Obviously the element needs to know the viewport of its SVG document for this. This method therefore +does not work if the element is unrooted. + + +How big does an object have to be to have the specified size on the viewport? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This is useful if you want to draw a shape at a given location on the viewport, regardless of +what the user coordinate system is. This is done using +:meth:`BaseElement.viewport_to_unit <inkex.elements._base.BaseElement.viewport_to_unit>`. + +>>> svg.viewport_to_unit("4mm", "px") +4.0 +>>> svg.viewport_to_unit("4mm", "mm") +1.0583333333333333 + +An example for this would be text elements. In order for text to show up in Inkscape's text +tool as ``9pt``, you have to user + +>>> element.style["font-size"] = self.svg.viewport_to_unit("9pt") + +Again, this method will raise an error if the element is unrooted. + +In other words, ``viewport_to_unit(value, target_unit="px")`` answers the following question: +**What is the SVG representation of entering** ``value`` **in the width/height widget of the +selection tool (set to the unit of value)?** Consider +``<svg width="210mm" viewBox="0 0 105 147.5"><rect width="?" height="?"/></svg>``, +i.e. a "mm-based" SVG with scale=2. When typing ``200`` in the +rectangle tool, set to mm, the XML editor shows ``100`` = +``100px``. That's what ``viewport_to_unit("200mm") = 100`` does. + +Note that this is different than +``viewport_to_unit("200", "mm")``, which would be for a rectangle +with a width (in the width/height widget of the rectangle tool) of +200 (px), while writing the width in ``mm`` *in the SVG*: +``<rect width="7.00043mm" height="7.00043mm"/>``. + +Document dimensions +^^^^^^^^^^^^^^^^^^^^^^^^ + +* :attr:`SvgDocumentElement.viewport_width <inkex.elements._svg.SvgDocumentElement.viewport_width>` + and + :attr:`SvgDocumentElement.viewport_height <inkex.elements._svg.SvgDocumentElement.viewport_height>` + are the width and height of the viewport coordinate system, i.e. the "output screen" of the + viewBox camera, in pixels. In above example: ``(317.480314, 211.653543)`` + +.. code-block: + 84mm * 96px/in / (25.4mm/in) = 317.480314 + [output size] [resolution 96dpi] [output size in pixels] + +* :attr:`SvgDocumentElement.viewbox_width <inkex.elements._svg.SvgDocumentElement.viewbox_height>` + and + :attr:`SvgDocumentElement.viewbox_height <inkex.elements._svg.SvgDocumentElement.viewbox_height>` + are the width and height of the user coordinate system, i.e. for a viewport without offset, the + largest ``x`` and ``y`` values that are visible to the viewport camera. + In above example: ``(84, 56)`` + +Conversion between arbitrary units +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The functions listed above are methods of :class:`BaseElement <inkex.elements._base.BaseElement>` +because they use properties of the root SVG. For an unrooted SVG fragment, +:meth:`BaseElement.to_dimensionless <inkex.elements._base.BaseElement.to_dimensionless>`. +:meth:`BaseElement.to_dimensional <inkex.elements._base.BaseElement.to_dimensional>` work as well. + +If you want to convert between arbitrary units, you can do so using the +:meth:`convert_unit <inkex.units.convert_units>` method: + +>>> inkex.units.convert_unit("4mm", "px") +15.118110236220472 + + +Note that inkex doesn't support relative units (percentage, `em` and `ex`) yet. You will have to +implement these yourself if you want your extension to support them. + +.. [1] https://www.w3.org/TR/SVG11/coords.html#Units +.. [2] https://www.w3.org/TR/SVG2/coords.html#Introduction +.. [3] https://www.w3.org/TR/SVG2/coords.html#ViewportSpace +.. [4] https://www.w3.org/TR/SVG2/coords.html#ViewBoxAttribute +.. [5] Note that this drawing has ``width="100%" height="" viewBox="0 0 88.540985 36.87265"``. + This instructs the viewer that the SVG should span the entire width of the containing + element (in this case, an HTML div) and the height should be chosen such that the image + is scaled proportionally. Inkex doesn't support these relative units and these don't really + make sense in standalone SVGs anyway.
\ No newline at end of file diff --git a/share/extensions/docs/authors/update1.0.rst b/share/extensions/docs/authors/update1.0.rst new file mode 100644 index 0000000..294af52 --- /dev/null +++ b/share/extensions/docs/authors/update1.0.rst @@ -0,0 +1,301 @@ +Updating your extension for Inkscape 1.0 +======================================== + +.. warning:: This information is partially outdated. + +This is a preliminary and incomplete list of actions to take for +updating Python extensions for Inkscape 1.0: + +.. _adjusting_folder_structure: + +Adjusting folder structure +-------------------------- + +For easier extension 'installation' by users and for having a better +overview about the installed extensions, you can now put extensions into +their own subfolders of the ``extensions`` directory. This is optional. + +When specifying the command in the .inx file, you can use the new +parameter 'location'. + +- If you set ``location="extensions"`` (de-facto default in 0.92.x), it + will assume the path is relative to either user or system extensions + folder. +- If it's ``location="inx"`` (new and recommended in 1.0), it will + assume the path is relative to the .inx file location. + +An extension that uses the following snippet: + +.. code:: xml + + <script> + <command location="inx" interpreter="python">hello.py</command> + </script> + +can be put into any subfolder in ``extensions`` or into the +``extensions`` folder itself, as long as the file ``hello.py`` is in +that same folder, at the same hierarchy level. + +The old parameter ``reldir`` is deprecated. It is recommended to use +Unix style path separators (i.e. ``/``), if your script file is located +in a nested subdirectory (should be a very rare case). + +.. _updating_.inx_files: + +Updating \*.inx files +--------------------- + +.. _remove_dependency_listings: + +Remove dependency listings +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Remove the dependency listings for the following modules: + +- bezmisc.py +- coloreffect.py +- cspsubdiv.py +- cubicsuperpath.py +- ffgeom.py +- inkex.py (removal not strictly required) +- pathmodifier.py +- simplepath.py +- simplestyle.py +- simpletransform.py +- more? + +This change is backwards compatible (as long as the user has a fully +functioning Inkscape installation). Not removing these will result in +the extension not being selectable (disabled and greyed out) in Inkscape +1.0 or higher. + +.. _changes_to_parameter_definitions: + +Changes to parameter definitions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There are also some updates to the parameter definitions in .inx files. +While these are intended to be backwards compatible to 0.92, you may +wish to review the changes below: + +- **Underscores** in inx parameter tags and attributes for translation + **can be dropped** entirely. Use ``translatable="no"`` to make an + item (e.g. a unit name) untranslatable. +- ``boolean`` can be renamed to ``bool`` +- ``<param type="enum" />`` is deprecated, instead use optiongroups. + Remember to rename ``item`` to ``option`` when replacing. +- In optiongroups ``appearance="minimal"`` is deprecated. + + - In optiongroups you can now define dropdown selections + (comboboxes) and radio buttons. + - i.e. ``<param type="optiongroup" appearance="combo" />``, or + ``<param type="optiongroup" appearance="radio" />``. + +- Choosing files / folders with ``<param type="path" />`` + (these return the path as a string to the Python script) +- Color choosers: make them more compact with + ``appearance="colorbutton"`` for parameters of type ``color`` +- Multiline text entry fields are available with + ``appearance="multiline"`` for parameters of type ``string`` +- The following new widgets (static, do not need to be read in by the + .py file's option parser anymore): + + - ``label``: (``<label>Some text</label>``), replaces parameters of type + ``description`` (which never really were parameters in the actual + sense), optionally with ``appearance="header"``. + - ``hbox``/``vbox``: for layouting purposes (allow to pack child + widgets into horizontally/vertically oriented boxes) + - ``<spacer/>`` / ``<separator/>``: which add a variable space or separating line between child + widgets. + - ``<image>my_image.svg</image>``: which allows to display an image in the + extension UI + +See :ref:`inx-widgets` for more details. + +Example file with many of the new features: + +.. code:: xml + + <?xml version="1.0" encoding="UTF-8"?> + <inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension"> + <name>Layout Demo</name> + <id>org.inkscape.test.layout_demo</id> + <dependency type="executable" location="extensions">pathmodifier.py</dependency> + + <hbox> + <vbox> + <label appearance="header">Multiple vboxes packed into an hbox</label> + <hbox> + <vbox> + <label>Vertical stack</label> + <param name="param_bool" type="bool" gui-text="Boolean">true</param> + <param name="param_int" type="int" gui-text="Int:" >12345</param> + <param name="param_float" type="float" gui-text="Float:">1.2345</param> + <param name="param_color" type="color" appearance="colorbutton" gui-text="Color:">0x12345678</param> + </vbox> + <spacer /> + <vbox> + <label>Vertical stack with separators</label> + <param name="param_string" type="string" gui-text="Single line string:">a string value</param> + <separator></separator> + <param name="param_string_empty" type="string" gui-text="Empty single line:"></param> + <separator></separator> + <param name="param_string_multiline" type="string" appearance="multiline" gui-text="Multiline string:">a\nmultiline\nstring\nvalue</param> + </vbox> + <spacer /> + <vbox> + <label>Vertical stack with spacers</label> + <param name="param_file_new" type="path" mode="file_new" filetypes="png" gui-text="A new file:">my/path/to/file.png</param> + <spacer /> + <param name="param_file" type="path" mode="file" filetypes="png,jpg" gui-text="A file:">my/path/to/file.png</param> + <spacer /> + <param name="param_files" type="path" mode="files" gui-text="Multiple files:">my/path/to/file.png</param> + <spacer /> + + </vbox> + <spacer /> + <vbox> + <label>Vertical stack with expanding spacer</label> + <spacer size="expand"/> + <param name="param_folder" type="path" mode="folder" gui-text="A folder:">my/path/</param> + <param name="param_folders" type="path" mode="folders" gui-text="Folders:">my/path/to/file.png</param> + <param name="param_folder_new" type="path" mode="folder_new" gui-text="A new folder:">my/path/</param> + </vbox> + <spacer /> + <vbox> + <label appearance="header">An image!</label> + <image>ink_icon.svg</image> + <spacer /> + <label appearance="header" indent="1">Indented header</label> + <spacer /> + <label>For details please refer to</label> + <label appearance="url" indent="1">https://clickable.url</label> + </vbox> + </hbox> + </vbox> + </hbox> + + <effect needs-live-preview="false"> + <object-type>all</object-type> + <effects-menu> + <submenu _name="Test"/> + </effects-menu> + </effect> + <script> + <command reldir="extensions" interpreter="python">do_nothing.py</command> + </script> + </inkscape-extension> + +.. _updating_.py_files: + +Updating \*.py files +-------------------- + +.. _collecting_the_options_of_the_extension: + +Collecting the options of the extension +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#. Instead of ``inkex.Effect.OptionParser.add_option``, your extension + should now use ``inkex.Effect.arg_parser.add_argument``. +#. The 'type' option now works with variables instead of strings. Use + ``int`` instead of ``"int"`` (same for float,...). +#. The 'inkbool' type is now ``inkex.Boolean``. +#. ``action="store"`` can be removed. + +These changes are not backwards compatible. The old options will still +work, but are deprecated and should no longer be used when you develop +your extension for Inkscape 1.0 or higher. + +.. _replace_specific_functions: + +Replace specific functions +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When the .inx file is valid and not greyed out (meaning: a dependency is +missing), you can start building the .py file up again. + +In the Inkscape extensions refactoring process for Inkscape 1.0, many +inkex functions have been removed, or renamed, or moved, or options have +changed. Wherever possible, Inkscape will try to replace the old +function by the new one, and will give you a deprecation warning, with +instructions what to replace them by. + +E.g. ``inkex.Effect.selected`` is replaced by +``inkex.Effect.svg.selected`` - however, most replacements do not follow +this naming scheme translation. + +These changes are not backwards compatible. + +.. _python_3_python_2_compatibility: + +Python 3 / Python 2 compatibility +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. warning:: Starting from Inkscape 1.1, only Python 3 is supported. + +Test your extension with both Python 2 and Python 3, if you want it to +work for as many users as possible. With the updated extensions, +Inkscape does no longer require Python 2, so some users will probably be +using Python 3, and may no longer have Python 2 installed on their +system. See `Extension_Interpreters <Extension_Interpreters>`__ for how +to set the Python version for your extension in the preferences file +(for testing). + +.. _getting_your_extension_added_to_inkscapes_stock_extensions: + +Getting your extension added to Inkscape's stock extensions +----------------------------------------------------------- + +Inkscape now has a `separate repository for its Python +extensions <https://gitlab.com/inkscape/extensions>`__, which is +included into Inkscape proper by using a Git submodule. + +.. _writing_tests: + +Writing tests +~~~~~~~~~~~~~ + +Previously Inkscape didn't require any unit testing for code. You should +now write test code if you expect your module to be included into the +Inkscape extensions repository and included in the shipped Inkscape +release. In this case, a test suite file should be made in the tests +directory for your extension. It should test each aspect of your +extension and exercise all assumptions. + +If you are writing a standalone extension that users will install +themselves, there is no strict requirement for tests. But having them +will greatly improve your code and your ability to upgrade the code +later. You can have tests in your own folders and use the extension's +setup.py as a harness to run them (a setup.py file is also useful for +installing your python code as a non-inkscape related python module, +which might be useful too). See Python documentation for creating +packages. + +.. _documenting_your_extension: + +Documenting your extension +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Docstrings +---------- + +Include docstrings in your extension, so documentation can be built from +them automatically. + +.. _submitting_your_extension_for_inclusion: + +Submitting your extension for inclusion +--------------------------------------- + +Visit https://gitlab.com/inkscape/extensions, fork the repository, and +create a merge request on GitLab. + +.. _external_links: + +External links +-------------- + +A script to perform some of the conversion steps automatically has been +contributed: https://gitlab.com/inkscape/extensions/-/issues/380 + diff --git a/share/extensions/docs/authors/update1.2.rst b/share/extensions/docs/authors/update1.2.rst new file mode 100644 index 0000000..d50323a --- /dev/null +++ b/share/extensions/docs/authors/update1.2.rst @@ -0,0 +1,229 @@ +Updating your extension for Inkscape 1.2 +========================================= + +This page is intended for extension authors who want to use the new +capabilities of inkex in Inkscape 1.2. As of the Release of 1.2alpha +(Feb 5, 2022), no more breaking changes will be introduced until the +final release of 1.2. + +There are no breaking changes in this release, but a few methods have +been deprecated. + +.. _deprecating_changes: + +Deprecating changes +------------------- + +- The Transforms multiplication operator has been changed from ``*`` + (``*=``) to ``@`` (``@=``), in accordance with + `PEP-465 <https://www.python.org/dev/peps/pep-0465/>`__ (`MR + extensions#389 <https://gitlab.com/inkscape/extensions/-/merge_requests/389>`__, + `Issue + extensions#327 <https://gitlab.com/inkscape/extensions/-/issues/327>`__) +- ``svg.width`` and ``svg.height`` have been deprecated, and replaced + with ``svg.viewbox_width``, ``svg.viewport_width``, + ``svg.viewbox_height`` and ``svg.viewport_height``, see `New Units + API <Updating_your_Extension_for_1.2#New_Units_API>`__. +- ``selection.paint_order`` has been renamed to + ``selection.rendering_order`` to be conformant with the specification + (`MR + extensions#344 <https://gitlab.com/inkscape/extensions/-/merge_requests/344>`__, + `Issue + extensions#310 <https://gitlab.com/inkscape/extensions/-/issues/310>`__) +- ``FallbackStyle`` has been deprecated in favor of ``Style``, see `New + Style API <Updating_your_Extension_for_1.2#New_Style_API>`__. + +.. _new_style_api: + +New Style API +------------- +.. figure:: samples/Comparison_of_Lighter_extension_in_Inkscape_1.1.2_and_1.2.png + + Top: W3C SVG1.1 Test suite, + test `styling-css-04-f.svg <https://www.w3.org/Graphics/SVG/Test/20110816/harness/htmlObjectApproved/styling-css-04-f.html>`__. + This test includes various CSS selectors, and includes group inheritance + and pseudo-selectors. It is rendered correctly in Inkscape 1.2. Bottom + left: Output of the "Lighter" extension in Inkscape 1.1.2, only two + squares are processed correctly, two squares have a wrong color and the + other 14 raise unhandled exceptions. Bottom right: Correct output in + Inkscape 1.2. This shows that inkex correctly handles different types of + CSS selectors. + +Added in `MR +extensions#294 <https://gitlab.com/inkscape/extensions/-/merge_requests/294>`__, +`MR +extensions#296 <https://gitlab.com/inkscape/extensions/-/merge_requests/296>`__, +`MR +extensions#298 <https://gitlab.com/inkscape/extensions/-/merge_requests/298>`__, +`MR +extensions#300 <https://gitlab.com/inkscape/extensions/-/merge_requests/300>`__, +`MR +extensions#352 <https://gitlab.com/inkscape/extensions/-/merge_requests/352>`__, +`MR +extensions#403 <https://gitlab.com/inkscape/extensions/-/merge_requests/403>`__ + +Inkex now exposes styles to extensions authors as intended by the SVG +specification. This means: + +- ``BaseElement`` now has functions ``cascaded_style``, + ``specified_style`` and ``presentation_style``. +- In most use cases, extensions querying a style will use + ``specified_style``. This computes the `effective + style <https://www.w3.org/TR/CSS22/cascade.html#specified-value>`__ + of the element, including CSS classes / pseudo-selectors, inherited + styles, presentation attributes etc. +- While ``style.get()`` and ``style[key]`` has been unchaged, a new + getter has been added in form of ``style(key)`` (similar to a + function call), which attempts to parse the attribute in a reasonable + datatype. If the attribute is unset, the (parsed) default value will + be returned. For example: + + - ``style("fill")`` returns a ``Color`` / ``Gradient`` / ``Pattern`` + / ``None``, + - ``style("opacity")`` returns a value between 0 and 1, regardless + if opacity is defined as percentage or as float, is out of bounds + or undefined, + - ``style("stroke-dasharray")`` returns a list of floats of + dash/gap/dash/gap in user units. + +- Not for all attributes there is a parser defined - in that case, a + string will be returned. Additional parsers may be added in the + future, so if you handle the string value, typecheck it first! + +.. _using_the_new_style_api_in_your_extension: + +Using the new Style API in your extension +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following calls can probably be simplified: + ++----------------------------------------------------+----------------------------------------------------+ +| Old code (pre-1.2) | New code (1.2+) | ++====================================================+====================================================+ +| .. code:: python3 | .. code:: python3 | +| | | +| if "fill-opacity" in self.style: | alpha = self.style("fill-opacity") | +| alpha = self.style["fill-opacity"] | | +| else: | | +| alpha = 1 | | ++----------------------------------------------------+----------------------------------------------------+ +| .. code:: python3 | .. code:: python3 | +| | | +| if not node.style.get(attr, '')\ | marker_node = node.style(attr) | +| .startswith('url(#'): | | +| continue | | +| | | +| marker_id = node.style[attr][5:-1] | | +| marker_node = self.svg.getElement( | | +| f'/svg:svg//svg:marker[@id="{marker_id}"]') | | ++----------------------------------------------------+----------------------------------------------------+ +| .. code:: python3 | .. code:: python3 | +| | | +| obj.style['fill'] = pattern.get_id(2) | obj.style['fill'] = pattern | ++----------------------------------------------------+----------------------------------------------------+ + +Checkout `MR +extensions#298 <https://gitlab.com/inkscape/extensions/-/merge_requests/298>`__ +for additional examples of simplifications. + +.. _new_units_api: + +New Units API +------------- + +Added in `MR +extensions#329 <https://gitlab.com/inkscape/extensions/-/merge_requests/329>`__, +`MR +extensions#343 <https://gitlab.com/inkscape/extensions/-/merge_requests/343>`__, +`MR +extensions#415 <https://gitlab.com/inkscape/extensions/-/merge_requests/415>`__ + +The existing functions ``unittouu`` and ``uutounit`` are widely used, +but for different purposes. Different extension authors try to answer +different questions using these function, and, inevitably, some answers +were incorrect (see linked issues in `MR +extensions#329 <https://gitlab.com/inkscape/extensions/-/merge_requests/329>`__). + +In Inkscape 1.2, new methods have been added to make working with +dimensional values easier. These are ``to_dimensionless``, +``to_dimensional``, ``viewport_to_unit`` and ``unit_to_viewport``. The +existing functions ``unittouu`` and ``uutounit`` are not deprecated, but +discouraged; in most cases, the new functions are more reliable. + +- ``to_dimensionless(value)`` fulfills the following task: **Convert + this string from the XML into a number, while processing the unit. + When using this function on any SVG attribute and replace the + original value with the result, the output doesn't change visually.** +- ``viewport_to_unit(value, target_unit="px")`` answers the following + questions: + + - **What is the length (e.g. the length of a rectangle, without a + unit) of an object that has size** ``value`` **on the viewport?** This + is relevant because in Inkscape toolbars / tools, all dimensions + are shown in "viewport units". + - In other words: **What is the SVG representation of entering + ``value`` in the width/height widget of the selection tool (set to + the unit of value)?** Consider ``<svg width="210mm" viewBox="0 0 105 147.5"><rect width="100" height="100"/></svg>`` + , i.e. a "mm-based" SVG with scale=2. When typing ``200`` in the + rectangle tool, set to mm, the XML editor shows ``100`` = + ``100px``. That's what ``viewport_to_unit("200mm") = 100`` does. + + - Note that this is different than + ``viewport_to_unit("200", "mm")``, which would be for a rectangle + with a width (in the width/height widget of the rectangle tool) of + 200 (px), while writing the width in ``mm`` *in the SVG*: \ + ``<rect width="7.00043mm" height="7.00043mm"/>``. + +- ``to_dimensional`` simply converts a float to its equivalent with + attached unit. It's the opposite of ``to_dimensionless``. +- ``unit_to_viewport(value, unit="px")`` answers the following + question: **What does the the width/height widget of the selection + tool (set to** ``unit`` **) show when selecting an element with width + ``value`` as defined in the SVG?** Consider again ``<svg width="210mm" viewBox="0 0 105 147.5"><rect width="100" height="100"/></svg>`` + , i.e. a "mm-based" document with scale=2. To create this rectangle, + one has to type ``viewport_to_unit("100", unit="mm") = 200`` into the + rectangle tool, if the rectangle tool is set to mm. + +With the same spirit, the functions for width/height of the document +have been updated. ``svg.width`` and ``svg.height`` have been +deprecated, and replaced with ``svg.viewbox_width``, +``svg.viewport_width``, ``svg.viewbox_height`` and +``svg.viewport_height``. + +There is also ``svg.scale``, which returns the ratio of the viewport and +viewbox width, and ``svg.inkscape_scale`` which is the scale reported in +the Document properties dialog. + +See :ref:`units` for additional information. + +.. _other_additions_to_inkex: + +Other additions to inkex +------------------------ + +- The path conversion for arcs and stars have been added, so when + extensions create these objects, they are rendered in a browser as + well and can be processed further by the same extension. (`MR + extensions#387 <https://gitlab.com/inkscape/extensions/-/merge_requests/387>`__, + `Issue + extensions#240 <https://gitlab.com/inkscape/extensions/-/issues/240>`__) +- ``ColorExtension``\ s can now process in RGBA space. Previously, + opacity and color were processed independently. By setting the class + variable ``pass_rgba = True``, the ``modify_color`` method gets + passed a color with alpha channel computed from matching property + pairs, e.g. ``fill`` and ``fill-opacity``. (This value takes CSS + styling and style inheritance into account. (`MR + extensions#392 <https://gitlab.com/inkscape/extensions/-/merge_requests/392>`__ + , `Issue + extensions#419 <https://gitlab.com/inkscape/extensions/-/issues/419>`__). +- API functions for the new `multipage + feature <Release_notes/1.2#Page_tool>`__ have been added: `MR + extensions#499 <https://gitlab.com/inkscape/extensions/-/merge_requests/399>`__. + +.. _other_deprecations_to_inkex_1_2 + +Other deprecations to inkex +---------------------------- + +- Pre Inkscape 1.0 way of declaring the dependency on inkex in the ``*.inx`` file has been removed entirely. (It was deprecated in Inkscape 1.0. For details, see :ref:`remove_dependency_listings`) + diff --git a/share/extensions/docs/authors/widgets/bool.png b/share/extensions/docs/authors/widgets/bool.png Binary files differnew file mode 100644 index 0000000..dbf5588 --- /dev/null +++ b/share/extensions/docs/authors/widgets/bool.png diff --git a/share/extensions/docs/authors/widgets/color.png b/share/extensions/docs/authors/widgets/color.png Binary files differnew file mode 100644 index 0000000..1d6e894 --- /dev/null +++ b/share/extensions/docs/authors/widgets/color.png diff --git a/share/extensions/docs/authors/widgets/float.png b/share/extensions/docs/authors/widgets/float.png Binary files differnew file mode 100644 index 0000000..63ac125 --- /dev/null +++ b/share/extensions/docs/authors/widgets/float.png diff --git a/share/extensions/docs/authors/widgets/image.png b/share/extensions/docs/authors/widgets/image.png Binary files differnew file mode 100644 index 0000000..057b1d0 --- /dev/null +++ b/share/extensions/docs/authors/widgets/image.png diff --git a/share/extensions/docs/authors/widgets/integer.png b/share/extensions/docs/authors/widgets/integer.png Binary files differnew file mode 100644 index 0000000..da376db --- /dev/null +++ b/share/extensions/docs/authors/widgets/integer.png diff --git a/share/extensions/docs/authors/widgets/label.png b/share/extensions/docs/authors/widgets/label.png Binary files differnew file mode 100644 index 0000000..fb1e470 --- /dev/null +++ b/share/extensions/docs/authors/widgets/label.png diff --git a/share/extensions/docs/authors/widgets/notebook.png b/share/extensions/docs/authors/widgets/notebook.png Binary files differnew file mode 100644 index 0000000..f21dcec --- /dev/null +++ b/share/extensions/docs/authors/widgets/notebook.png diff --git a/share/extensions/docs/authors/widgets/optiongroup.png b/share/extensions/docs/authors/widgets/optiongroup.png Binary files differnew file mode 100644 index 0000000..a8d9d7d --- /dev/null +++ b/share/extensions/docs/authors/widgets/optiongroup.png diff --git a/share/extensions/docs/authors/widgets/path.png b/share/extensions/docs/authors/widgets/path.png Binary files differnew file mode 100644 index 0000000..3050182 --- /dev/null +++ b/share/extensions/docs/authors/widgets/path.png diff --git a/share/extensions/docs/authors/widgets/separator.png b/share/extensions/docs/authors/widgets/separator.png Binary files differnew file mode 100644 index 0000000..e4e7e2e --- /dev/null +++ b/share/extensions/docs/authors/widgets/separator.png diff --git a/share/extensions/docs/authors/widgets/spacer.png b/share/extensions/docs/authors/widgets/spacer.png Binary files differnew file mode 100644 index 0000000..32ab128 --- /dev/null +++ b/share/extensions/docs/authors/widgets/spacer.png diff --git a/share/extensions/docs/authors/widgets/string.png b/share/extensions/docs/authors/widgets/string.png Binary files differnew file mode 100644 index 0000000..b95ffff --- /dev/null +++ b/share/extensions/docs/authors/widgets/string.png diff --git a/share/extensions/docs/conf.py b/share/extensions/docs/conf.py new file mode 100644 index 0000000..62e2884 --- /dev/null +++ b/share/extensions/docs/conf.py @@ -0,0 +1,93 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +import os +import sys + +sys.path.insert(0, os.path.abspath("../")) + +import datetime + +# -- Project information ----------------------------------------------------- + +project = "inkex documentation" +copyright = f"{datetime.datetime.now().year} The Inkscape Project" +author = "The Inkscape Project" + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.viewcode", + "sphinx.ext.todo", + "sphinx.ext.napoleon", +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = "en" + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "pydata_sphinx_theme" + +html_theme_options = { + "show_toc_level": 2, + "use_edit_page_button": True, + "gitlab_url": "https://gitlab.com/inkscape/extensions", +} + +html_context = { + "gitlab_user": "inkscape", + "gitlab_repo": "extensions", + "gitlab_version": "master", + "doc_path": "docs", +} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +# html_static_path = ["_static"] + +# -- Extension configuration ------------------------------------------------- + +always_document_param_types = True + +# -- Options for todo extension ---------------------------------------------- + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + +autodoc_member_order = "bysource" + +autodoc_preserve_defaults = True + +html_favicon = "favicon.svg" diff --git a/share/extensions/docs/dev/getting-started.rst b/share/extensions/docs/dev/getting-started.rst new file mode 100644 index 0000000..63d8a46 --- /dev/null +++ b/share/extensions/docs/dev/getting-started.rst @@ -0,0 +1,148 @@ +Getting started with developing inkex +===================================== + +.. highlight:: bash + +.. warning:: + + This document is tailored for contributors to the inkex package and core extensions. + + Extension authors should look here: :ref:`authors-tutorial` + +Repository setup +---------------- + +It is possible to synchronize a fork with the extensions repository - whenever a branch in the +mirrored repository is updated, your fork will be updated too (usually with a delay of up to one +hour). See `Settings -> Repository -> Mirroring Repositories` and add a "Pull" mirror. + +.. warning:: + + If you use this method, **do not** add commits to branches that should be synced + (such as `master`). + Depending on the exact settings of the mirroring option, you will either lose your changes, + lose the synchronisation or run into a messed up branch history. + +Always check out submodules as well:: + + git submodule update && git submodule init + +Python setup +------------ + +On every operating system, you need a working Python environment. Currently, inkex is tested +against Python 3.7-3.10. + +inkex manages its dependencies using `poetry <https://python-poetry.org/docs/>`_. It can be installed using:: + + pip install poetry + +Install the dependencies and the pre-commit hook:: + + poetry install + pre-commit install + +Testing changes in Inkscape +--------------------------- + +Most of the time, calling the python file of the extension directly and through unit tests is +sufficient. In some cases, the interaction between Inkscape and the extension should be tested, +though. + +Assuming you have managed to make Inkscape look in the correct folder for the extensions (see hints +for different operating systems below), the python +file of an extension is reloaded every time the extension is run. For changes to the inx file or +the command line parameters of the extension (as defined in the +:func:`~inkex.base.InkscapeExtension.add_arguments` method) you need to restart Inkscape. + +Developing extensions on Windows +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +.. highlight:: batch + +To test extensions with a given Inkscape version, download the 7z archive of that version, +unarchive it and delete the ``inkscape\share\extensions`` folder. Next, create a symlink in that +folder from an administrative command prompt:: + + cd [directory of the unzipped Inkscape folder] + mklink /D share\extensions C:\path\to\your\fork + +If you start ``bin\inkscape`` now, the extensions are loaded from your fork. + +Developing extensions on Linux +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. highlight:: bash + +A very similar path to Windows can be used when working off an appimage build. + +Extract the appimage into a new folder called ``squashfs-root``:: + + /path/to/appimage --appimage-extract + squashfs-root/AppRun --system-data-directory + +This prints the location of the extensions folder. Create a symlink to your repo there and run:: + + squashfs-root/AppRun + +Trying / Changing a merge request locally +----------------------------------------- + +Add this to ``git config -e`` (only once):: + + [remote "upstream"] + url = git@gitlab.com:inkscape/extensions.git + fetch = +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/* + [alias] + mr = !sh -c 'git fetch $1 merge-requests/$2/head:mr-$1-$2 && git checkout mr-$1-$2' - + +Check out the merge request !123:: + + git mr upstream 123 + +Push changes to the source branch ``source-branch-name`` of fork in the namespace (typically the +author's username) ``xyz``:: + + git push git@gitlab.com:xyz/extensions.git mr-origin-123:source-branch-name + + +Adding/Updating dependencies +---------------------------- + +.. highlight:: bash + +The *direct* dependencies of inkex are declared in the ``pyproject.toml`` file. + +There is also a lockfile named ``poetry.lock`` which has *all* the dependencies +(direct, dependencies of direct, dependencies of dependencies of direct and so on till the leaf dependencies) +pinned to specific versions (versions which were compatible the last time lockfile was updated). + +To update all the dependencies in the lockfile to latest compatible versions, enter:: + + poetry lock + +To add/update a particular dependency, add it to ``pyproject.toml`` manually. The dependency should be declared in the +``[tool.poetry.dependencies]`` TOML table, while a dependency required only during development of inkex should be declared in +``[tool.poetry.dev-dependencies]``. + +Then update the lockfile using:: + + poetry lock + +Alternatively, you can add a dependency and update the lockfile in a single command:: + + poetry add "lxml@^4.5.0" --lock + +Both the ``pyproject.toml`` and ``poetry.lock`` are to be committed to the repository. + +.. note:: + + You don't need to install the dependencies to add/update them. So, the commands above don't install anything. + However, if you are using poetry to manage the environment, and want to also install the dependencies, + remove the ``--lock`` options from the commands and use ``poetry update`` instead of ``poetry lock``. + +.. note:: + + Dependencies should be updated according to the `policy <https://wiki.inkscape.org/wiki/Tracking_Dependencies#Distros>`_ defined in Inkscape wiki . + diff --git a/share/extensions/docs/dev/index.rst b/share/extensions/docs/dev/index.rst new file mode 100644 index 0000000..a38cf03 --- /dev/null +++ b/share/extensions/docs/dev/index.rst @@ -0,0 +1,8 @@ +inkex (and core Extensions) development +======================================= + +.. toctree:: + :maxdepth: 2 + + getting-started + Writing unit tests <../authors/unit-tests>
\ No newline at end of file diff --git a/share/extensions/docs/favicon.svg b/share/extensions/docs/favicon.svg new file mode 100644 index 0000000..cf0292a --- /dev/null +++ b/share/extensions/docs/favicon.svg @@ -0,0 +1,159 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Wikimedia Commons, User:Sven. Hand edited. :)--> + +<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="128" + height="128" + viewBox="0 0 96.000001 96.000003" + id="svg2" + version="1.1" + inkscape:version="0.92.2 (unknown)" + sodipodi:docname="addons2.svg" + inkscape:export-filename="/home/doctormo/Desktop/addons.png" + inkscape:export-xdpi="152" + inkscape:export-ydpi="152"> + <metadata + id="metadata57"> + <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> + <defs + id="defs55"> + <clipPath + id="clipPath712"> + <path + id="path714" + inkscape:connector-curvature="0" + d="m 3711.8,1621 c 1.65,2.4 3.19,5 4.64,7.76 l 0.61,0 c 1.34,0 2.67,0.06 3.99,0.19 -2.82,-3.21 -5.89,-5.89 -9.24,-7.95 m -582.76,582.77 c 2.06,3.35 4.74,6.42 7.95,9.24 -0.15,-1.52 -0.21,-3.05 -0.19,-4.6 -2.76,-1.45 -5.36,-2.99 -7.76,-4.64" /> + </clipPath> + <linearGradient + id="linearGradient11554" + gradientUnits="userSpaceOnUse" + inkscape:collect="always" + gradientTransform="matrix(152.32,152.32,152.32,-152.32,223.42,72.625)"> + <stop + id="stop718" + style="stop-color:#c14d9d" + offset="0" /> + <stop + id="stop720" + style="stop-color:#da45a4" + offset="1" /> + </linearGradient> + <clipPath + id="clipPath680"> + <path + id="path682" + inkscape:connector-curvature="0" + d="m 3752.3,753.38 -13.46,0 0,12.73 13.46,-0.007 0,-12.72" /> + </clipPath> + <clipPath + id="clipPath114"> + <path + id="path116" + inkscape:connector-curvature="0" + d="m 3217.1,1932.8 c 19.99,128.64 -54.89,140.42 -95.98,231.75 -5.9,13.11 -7.38,25.56 -3.18,36.77 -1.62,-4.35 -2.39,-8.88 -2.39,-13.56 0.01,-7.4 1.97,-15.18 5.58,-23.21 36.39,-80.89 99.29,-99.38 99.3,-191.94 0,-11.94 -1.05,-25.11 -3.33,-39.81" /> + </clipPath> + <clipPath + id="clipPath98"> + <path + id="path100" + inkscape:connector-curvature="0" + d="m 3175.4,1839.8 c 20.92,24.68 35.84,55.66 41.66,92.98 -5.8,-37.25 -20.66,-68.2 -41.53,-92.87 -0.04,-0.03 -0.09,-0.08 -0.13,-0.11" /> + </clipPath> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient11554" + id="linearGradient16646" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(152.32,152.32,152.32,-152.32,223.42,72.625)" /> + </defs> + <sodipodi:namedview + pagecolor="#525252" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="3102" + inkscape:window-height="1764" + id="namedview53" + showgrid="false" + units="px" + inkscape:zoom="5.6568542" + inkscape:cx="107.83079" + inkscape:cy="42.285295" + inkscape:window-x="98" + inkscape:window-y="36" + inkscape:window-maximized="1" + inkscape:current-layer="svg2" /> + <style + type="text/css" + id="style26"> + .specularity {opacity:0.5;} + .low-specularity {opacity:0.25;} + .full-specularity {opacity:1;} + .black {fill:#000000;} + .white {fill:#ffffff;} + .outline-big {stroke-width:16;stroke:none;opacity:0.1;fill:none;} + .outline-small {stroke-width:8;stroke:none;opacity:0.2;fill:none;} + .stroke-highlight {fill:none;stroke:none;opacity:0.2;} + .base-shadow {fill:black;opacity:75;} + </style> + <style + type="text/css" + id="style26-3" /> + <path + 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:7.83048964;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" + d="M 47.201278,1.6086632 C 38.155881,2.2472546 33.855378,11.539389 27.481957,16.657572 l -16.27509,17.474845 v 41.968521 c 10.12207,0.397232 20.672388,-0.577111 30.467787,0.424582 -5.029107,4.330492 -4.440529,12.84409 1.28608,16.255711 6.716085,4.753575 16.536402,-2.005393 15.059479,-9.927488 0.09942,-2.605925 -2.695467,-4.57784 -3.104211,-6.50616 10.06717,-0.512782 20.245151,-0.03693 30.367366,-0.229028 -1.393736,-6.037406 2.214441,-14.227738 -3.349096,-18.81554 -4.960489,-2.761657 -8.671847,6.601935 -13.214923,1.825178 -3.647705,-3.40543 -0.09748,-11.096685 4.848349,-8.771777 2.616769,2.997298 8.350914,5.459767 10.62162,0.74346 1.89667,-5.283411 0.582542,-12.534013 0.796312,-18.035083 L 74.392318,22.441176 C 67.217974,15.923169 60.990968,8.0254646 52.905839,2.6604307 51.114328,1.8912029 49.149259,1.5293175 47.201278,1.6086632 Z" + id="path18660" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccccccccccccccc" /> + <path + 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:#292929;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.83048916;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" + d="m 47.737292,4.7551571 c -2.455633,-0.00335 -4.890607,0.9015902 -6.685859,2.7390881 L 14.363492,34.131977 V 72.97867 h 26.649623 c 3.830026,0.596821 5.287844,2.802384 2.667737,6.376671 -1.384296,1.217014 -2.326482,2.940582 -2.330801,4.910008 -0.0077,3.759915 3.034292,6.816344 6.794206,6.824597 3.75966,0.0089 6.816358,-3.035612 6.824598,-6.795527 0.0039,-1.581777 -0.649992,-2.985692 -1.565759,-4.15554 -3.943754,-4.99205 -1.382209,-6.718824 2.908216,-7.160209 h 25.599175 v -8.470958 c -0.460943,-4.472918 -1.230254,-6.207509 -4.989289,-2.787977 -1.421701,1.112885 -3.126766,1.899007 -5.048747,1.894767 -4.568836,-0.01028 -7.804473,-3.933832 -7.794443,-8.502669 0.01028,-4.568836 3.388373,-8.266925 7.956966,-8.256904 2.393412,0.0054 4.551613,1.28276 6.030486,2.965033 2.349214,1.948259 3.183464,0.616466 3.845027,-1.671464 V 34.131977 L 54.553962,7.4797108 54.539427,7.463855 C 52.66928,5.6683854 50.194248,4.7585896 47.738614,4.7551571 Z" + id="path5071" + inkscape:connector-curvature="0" /> + <g + id="g676" + transform="matrix(0.01478013,0,0,-0.01478013,-8.9217291,58.409986)" + style="stroke-width:1.10862482"> + <g + id="g678" + clip-path="url(#clipPath680)" + style="stroke-width:1.10862482"> + <path + id="path690" + style="fill:url(#linearGradient16646);stroke-width:1.10862482" + inkscape:connector-curvature="0" + d="m 3752.3,753.38 h -13.46 v 12.73 l 13.46,-0.007 v -12.72" /> + </g> + </g> + <path + inkscape:connector-curvature="0" + style="color:#000000;fill:#292929;fill-opacity:1;stroke-width:0.74702454" + d="m 47.740569,6.0208323 c -2.140885,-0.00428 -4.26097,0.7727567 -5.797302,2.3452439 L 16.383791,34.521732 c -0.184691,0.228716 -0.344181,0.444029 -0.508005,0.661985 h 26.172767 c 1.596627,-0.04836 3.106093,0.205077 4.141681,1.181834 0.521808,0.49225 0.870407,1.302601 0.743586,2.095189 -0.123203,0.769765 -0.578894,1.442472 -1.260804,2.099138 -0.002,0.0025 -6.74e-4,0.006 -0.0027,0.0079 -1.768925,1.953228 -1.021573,5.549029 1.499009,6.451394 l 0.06711,0.02237 0.0632,0.03291 c 2.745641,1.422255 6.626147,-1.569717 5.752553,-4.564145 -0.06658,-0.213566 -0.353228,-0.693745 -0.738315,-1.214735 -0.387985,-0.524971 -0.853945,-1.106784 -1.234477,-1.747747 -0.380525,-0.640928 -0.742991,-1.39634 -0.561961,-2.301814 0.181045,-0.905578 0.966091,-1.607911 2.003061,-2.007012 l 0.08818,-0.03291 0.09213,-0.01842 c 3.015225,-0.58108 16.224885,-0.350826 27.075602,-0.13165 L 53.6629,8.3660762 C 52.042852,6.8107123 49.881454,6.0251131 47.740569,6.0208323 Z" + id="path12081" /> + <path + inkscape:connector-curvature="0" + style="fill:#ffffff;stroke-width:5.34909868" + id="path2317" + d="m 52.118338,10.200681 10.112246,10.270157 c 0.958896,0.979832 0.945582,2.878613 0.409051,3.424655 l -5.020922,-4.016359 -0.98744,5.947484 -4.195201,-2.21461 -6.718031,4.244668 -2.224124,-8.94786 -3.609207,6.244286 h -5.517499 c -2.248856,0 -2.513315,-2.853878 -0.469938,-4.897255 3.569251,-3.852737 7.665518,-7.779674 9.89154,-10.055166 2.237447,-2.2869087 6.135841,-2.2222207 8.329525,0 z" /> +</svg> diff --git a/share/extensions/docs/index.rst b/share/extensions/docs/index.rst new file mode 100644 index 0000000..abfc319 --- /dev/null +++ b/share/extensions/docs/index.rst @@ -0,0 +1,35 @@ +Welcome to inkex's documentation! +================================= + +.. toctree:: + :maxdepth: 1 + :hidden: + + Tutorial <tutorial/index> + authors/index + Inkex Development <dev/index> + API Reference <source/index> + +**Useful links**: +`Source Repository <https://gitlab.com/inkscape/extensions>`_ | +`Issue Tracker <https://gitlab.com/inkscape/extensions/issues>`_ | +`Chat <https://chat.inkscape.org/channel/inkscape_extensions>`_ + +Inkex is: + +- a general-purpose SVG reading/writing/modification package +- an object-oriented interface for access to + many common SVG attributes, such as paths and styles +- the Python package that enables Inkscape extensions + +Furthermore, :mod:`inkex.gui` provides a way to ship GTK interfaces with extensions, and +:mod:`inkex.tester` is a package to facilitate unit testing of extensions. + +Welcome to its documentation! + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/share/extensions/docs/make.bat b/share/extensions/docs/make.bat new file mode 100644 index 0000000..21b58de --- /dev/null +++ b/share/extensions/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=.
+set BUILDDIR=build
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.https://www.sphinx-doc.org/
+ exit /b 1
+)
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+
+:end
+popd
diff --git a/share/extensions/docs/source/index.rst b/share/extensions/docs/source/index.rst new file mode 100644 index 0000000..b8aad2c --- /dev/null +++ b/share/extensions/docs/source/index.rst @@ -0,0 +1,21 @@ +.. inkex documentation master file, created by + sphinx-quickstart on Tue May 18 23:45:21 2021. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +API Reference +============= + +.. toctree:: + :maxdepth: 4 + :caption: Contents: + + inkex + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/share/extensions/docs/tutorial/index.rst b/share/extensions/docs/tutorial/index.rst new file mode 100644 index 0000000..0e9551a --- /dev/null +++ b/share/extensions/docs/tutorial/index.rst @@ -0,0 +1,49 @@ +.. _authors-tutorial: + +Tutorial +======== + +Introduction +------------ + +Extensions are small programs that extend Inkscape’s functionality. They +can provide features for specific tasks, experimentation, or art styles. +They can also add support for special hardware or different export +formats. While many extensions are included with Inkscape, you can also +install extensions written by third parties or write your own. + +This guide aims to provide you with enough information to write your own +extension using the python programming language and a text editor. You +should have the latest version of Inkscape installed. While Inkscape +extensions generally work across platforms, this guide will use Linux as +its default operating system. Linux is not required for writing +extensions, but you may need to modify the location of files on your +computer as you follow along. You may also need to use other “helper” +programs, for example a different text editor, depending on your +operating system. + +When a user selects an extension from the menu within Inkscape, Inkscape +opens a pop-up dialog that presents information to the user and/or +allows the user to enter any parameters that are necessary to use the +extension. An extension can also be configured to run immediately +without an intermediate dialog, for example if it does not have any +adjustable parameters. When the user clicks **Apply** in the dialog, the +parameters are passed to the extension program along with the svg file +and a list of selected objects. The extension program itself then runs, +and the data that it returns will be used to update Inkscape’s svg +canvas or to save data to disk. + +We’ve made this process easier for you by creating a set of template +extensions which you can download as the starting point for this +tutorial. If you are a beginner we recommend that you start with the +Effect Extension Template. Input, Output and other types of extensions +will be covered in the more advanced topics later. + +.. toctree:: + :maxdepth: 1 + + my-first-effect-extension + simple-path-extension + my-first-text-extension + my-first-import-extension + diff --git a/share/extensions/docs/tutorial/my-first-effect-extension.rst b/share/extensions/docs/tutorial/my-first-effect-extension.rst new file mode 100644 index 0000000..7666288 --- /dev/null +++ b/share/extensions/docs/tutorial/my-first-effect-extension.rst @@ -0,0 +1,130 @@ +.. _first-effect-extension: + +My first effect extension +========================= + +Resources +--------- + +- :download:`Template Files <resources/template_effect.zip>` +- :download:`Example solution <resources/make_red_extension.zip>` + +Introduction +------------ +Effect extensions take the svg from Inkscape, modify it in some way and +pass the modified version back to Inkscape to be rendered onto the +canvas. This can be very powerful, allowing everything from randomising +colours to manipulating path elements in external programs. + +We are going to write an effect extension that will simply change the fill +any selected object to red. + +Step One +--------- + +Extract the ``Effect Extension Template`` files into a folder on your +computer. You should have two files, one inx file and one python file. +Move or link these files into your extensions directory as you would +when installing extensions manually. This is the directory listed at +``Edit > Preferences > System: User extensions``. + +Edit the inx file in a text editor and change the name of the extension +to ``Make Red Extension`` and the id to +``org.inkscape.tutorial.make_red_extension`` by changing these lines near +the top: + +.. code:: xml + + <?xml version="1.0" encoding="UTF-8"?> + <inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension"> + <name>Make Red Extension</name> + <id>org.inkscape.tutorial.make_red_extension</id> + [...] + +Toward the end of the .inx file, change the submenu to ``Color`` +specify that this extension will be listed in the ``Color`` submenu +under the ``Extensions`` menu: + +.. code:: xml + + [...] + <effect> + <!--object-type>path</object-type--> + <effects-menu> + <submenu name="Color"/> + </effects-menu> + </effect> + [...] + +Step Two +--------- + +Next, open ``my_effect_extension.py`` in your text editor. You can see +this is an inkex extension because it contains a python class that +inherits from ``inkex.EffectExtension``. Change the class name to +``MakeRedExtension``: + +.. code:: python + + [...] + class MakeRedExtension(inkex.EffectExtension): + [...] + +Reflect this change down in the ``__main__`` section of the code by +changing the class name to ``MakeRedExtension`` there: + +.. code:: python + + [...] + if __name__ == '__main__': + MakeRedExtension().run() + +When a standard inkex-based python effect extension is run, it will call +a method called :func:`~inkex.base.InkscapeExtension.effect` on your extension's class. So, most of the +code you need to write will go there. Edit +``my_effect_extension.py``\ 's ``effect()`` method to look like the +following, **being sure that the indentation is correct so that** +``effect()`` **is recognized as a method of the MakeRedExtension class**: + +.. code:: python + + for elem in self.svg.selection: + elem.style['fill'] = 'red' + elem.style['fill-opacity'] = 1 + elem.style['opacity'] = 1 + + + +Code Explanation +~~~~~~~~~~~~~~~~ + +We want to change the color of all selected objects to red. For this we need to loop +through each of the selected paths. The first line of :func:`inkex.base.InkscapeExtension.effect` +does this. The :attr:`~inkex.elements._svg.SvgDocumentElement.selection` attribute of ``self.svg`` +contains the currently selected objects. + +.. hint:: + ``self.svg`` contains the SVG document in its current state - passed by Inkscape - and + is already parsed for us, so we don't have to manipulate the XML manually. Instead, inkex offers + an object-oriented interface to all the SVG element types. + +Each element has a ``style`` attribute: it's one of the +:attr:`~inkex.elements._base.BaseElement.WRAPPED_ATTRS` of each element, so ``elem.style`` is a +:class:`~inkex.styles.Style` object (you can think of it as a dictionary). And in this dictionary, +we set the value for ``'fill'`` to ``'red'``. We also set the ``'fill-opacity'`` to ``1``, in case +the object was transparent previously. + + +Final Step +------------ + +That’s it! There’s no need to set, save or do anything else as we’ve +modified the style in place. + +Save your python script, and re-launch Inkscape. If inkscape was already +open, close it first. You should find your new extension available in +the ``Effect`` menu. + +Draw some shapes in Inkscape. Select some of the shapes and use the extension. +The fill of all objects should change to red. + diff --git a/share/extensions/docs/tutorial/my-first-import-extension.rst b/share/extensions/docs/tutorial/my-first-import-extension.rst new file mode 100644 index 0000000..6c296bd --- /dev/null +++ b/share/extensions/docs/tutorial/my-first-import-extension.rst @@ -0,0 +1,305 @@ +My first import extension +========================= + +Resources +--------- + +:download:`vanillin.smi <resources/vanillin.smi>` + +Introduction +------------ + +This article will teach you the basics of writing an Import Extension for +Inkscape using the ``inkex`` Extensions API. + +Import Extensions are used to add support for a file format that +Inkscape does not support out of the box. It is rather complex to implement an entire file format, +but often there are already tools available to convert the file to a format that Inkscape can read, +such as SVG or PDF. In this case, the extension depends on external programs that convert that +specific file format to a svg that Inkscape can then read. + +The way these extensions are used is not through the ``Extensions`` menu +but instead these provide options in\ ``File``>\ ``Open`` or +``File``>\ ``Import`` dialog. + +The general flow of a Import Extension is as follows: + +1) You select the specific file format from the File Format drop down + menu of the ``File``>\ ``Open`` or ``File``>\ ``Import``\ dialog. +2) You select one or more files of that specific file format. You click + on ``Open`` button. +3) Inkscape will then either open the svg file in a new window or will + import it depending on which dialog of ``File`` menu was used. + +.. hint:: + + You can entirely skip 1) and 2) and just double click on + the file. If your extension is set up correctly, you won’t notice the + difference between opening a regular file and your file. + +In this article we will create an extension named +``Organic Bond Visualizer``. It will produce the bond structure of an +organic compound given a +`SMILES <https://en.wikipedia.org/wiki/Simplified_molecular-input_line-entry_system>`__ +file. The extension uses an external program called ``indigo-depict`` +which has its GitHub repository +`here <https://github.com/epam/Indigo>`__. (It is a part of the +``indigo-utils`` package in Debian/Ubuntu repositories. For other +platforms you might need to build it from source.) + +.. note:: A note on **PATH** + + Since the extension depends on external programs, it is important that + these external programs can be found by our extensions. For that to + happen, either these programs **should** be on your *system PATH* or an + absolute path for the program should be used in the code. + + Depending on the operating system, the steps required for adding + programs to the PATH might vary. + + You can get away with setting the PATH variable entirely by using an + absolute path for the program but it is almost always a bad idea to + hard-code paths in the code. + +.. hint:: + + This article assumes you create all extension related files in the + User Extensions directory which is listed at + ``Edit``>\ ``Preferences``>\ ``System`` - ``User Extensions:`` in + Inkscape. + +Step 0 : The Boilerplate +------------------------ + +Like any other Inkscape extension, this extension will also have two +files. So, create a ``organic_bond_vis.inx`` file and a +``organic_bond_vis.py`` file. + +- ``organic_bond_vis.inx`` - It will have the necessary information for + Inkscape to be able to recognize your extension as a valid Inkscape + extension. It will also have the info required to present the + extension as an option in ``File``>\ ``Open`` or + ``File``>\ ``Import`` dialog. +- ``organic_bond_vis.py`` - It will have the actual Python code your + extension will execute. + +.. hint:: + + There is another file that is worth mentioning here - the **test** + file which in our case will be ``test_organic_bond_vis.py``. It is + not required to be present for an extension per se, but as a best + practice, the extension code should always be accompanied by test + code. + +Step 1 : Populate the ``*.inx`` file +------------------------------------ + +.. code:: xml + + <?xml version="1.0" encoding="UTF-8"?> + <inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension"> + <name>Organic Bond Visualizer</name> + <id>org.inkscape.input.bondvisualizer</id> + <dependency type="executable" location="path">indigo-depict</dependency> + <input> + <extension>.smi</extension> + <mimetype>chemical/x-daylight-smiles</mimetype> + <filetypename>SMILES(*.smi)</filetypename> + <filetypetooltip>SMILES</filetypetooltip> + </input> + <script> + <command location="inx" interpreter="python">organic_bond_vis.py</command> + </script> + </inkscape-extension> + +The lines below help Inkscape uniquely identify our extension. You +should modify these two lines for your own extension: + +.. code:: xml + + [...] + <name>Organic Bond Visualizer</name> + <id>org.inkscape.input.bondvisualizer</id> + [...] + +Now we declare the dependency of our extension: + +.. code:: xml + + <dependency type="executable" location="path">indigo-depict</dependency> + +The ``<input>`` tag is what specifies that this extension should add a +new format in the list of available file formats Inkscape can +open/import. + +.. code:: xml + + [...] + <input> + <extension>.smi</extension> + <mimetype>chemical/x-daylight-smiles</mimetype> + <filetypename>SMILES(*.smi)</filetypename> + <filetypetooltip>SMILES</filetypetooltip> + </input> + [...] + +Inside the ``<extension>`` tag we declare the suffix of our new format +(including ``.``) + +Some more examples of suffixes could be ``.ps`` , ``.fig``, etc. The +text inside ``<filetypename>`` is what appears in the +``File``>\ ``Open`` or ``File``>\ ``Import`` dialogs. + +Towards the end, we add the name of our ``.py`` file inside the +``<command>`` tag. + +.. code:: xml + + [...] + <script> + <command location="inx" interpreter="python">organic_bond_vis.py</command> + </script> + [...] + +Now + +- Save the file +- Close any open Inkscape windows +- Relaunch Inkscape + +You should now see a ``SMILES(*.smi)`` option in the drop down menu. + +.. figure:: resources/Smiles_Format.gif + :alt: Smiles_Format + + Smiles_Format + +If you were to select the ``vanillin.smi`` file and open it, you would +get an error saying: + +.. figure:: resources/Call_Extension_Failure.png + :alt: Call_Extension_Failure + + Call_Extension_Failure + +This is because we haven’t written anything in the ``.py`` file of our +extension. + +Step 2 : Write the code in ``*.py`` file +---------------------------------------- + +First Things First +~~~~~~~~~~~~~~~~~~ + +To be able to use any extension functionality, you need to import the +``inkex`` module. + +.. code:: python + + import inkex + +There is a specialized class for input extensions that only call an external program to +convert the file. Every Call Extension inherits from the :class:`~inkex.extensions.CallExtension` +class provided by the ``inkex`` API. Let’s name our class ``OrganicBondVisualizer`` (an +arbitrary name) and inherit the :class:`~inkex.extensions.CallExtension` class. + +.. code:: python + + import inkex + + class OrganicBondVisualizer(inkex.CallExtension): + #implement functionality here + pass + +Specify the formats +~~~~~~~~~~~~~~~~~~~ + +We now specify the input file format and output file format. (both +without the ``.``). The output file format by default is ``svg``. + +.. code:: python + + import inkex + from inkex import command + + class OrganicBondVisualizer(inkex.CallExtension): + + input_ext = 'smi' + output_ext = 'svg' + + #implement functionality here + pass + +Override +~~~~~~~~ + +To be able to call an another program, we need to override the :func:`~inkex.extensions.CallExtension.call` +function in our class. We need to import the :mod:`~inkex.command` module as it +contains the actual implementation to call external programs. Inside the +overridden method we call :mod:`~inkex.command` module’s :func:`~inkex.command.call` function. + +.. code:: python + + import inkex + from inkex import command + + class OrganicBondVisualizer(inkex.CallExtension): + + input_ext = 'smi' + output_ext = 'svg' + + def call(self, input_file, output_file): + command.call('indigo-depict', input_file, output_file) + +The first argument for :mod:`~inkex.command`\ ’s :func:`~inkex.command.call` function is the name of +the external program. It can also be a path string like +``'/usr/bin/program'``. Although internally ``inkex`` converts the names +to path strings like these, you should not use them yourself. The reason +being that the user of this extension may not have the command at the +same path as the absolute path specified by us, the extension author. + + **Note**: *Windows* users don’t need to specify ``.exe`` in the name + of the program. + +The ``input_file`` and ``output_file`` are path strings received by the +:func:`~inkex.extensions.CallExtension.call` function from inkex. We then just pass these to +:mod:`~inkex.command`\ ’s :func:`~inkex.command.call` function. + +Make it all happen +~~~~~~~~~~~~~~~~~~ + +We now just add the ``__main__`` part where the extension runs. + +.. code:: python + + import inkex + from inkex import command + + class OrganicBondVisualizer(inkex.CallExtension): + + input_ext = 'smi' + output_ext = 'svg' + + def call(self, input_file, output_file): + command.call('indigo-depict', input_file, output_file) + + if __name__ == '__main__': + OrganicBondVisualizer().run() + +Now save the file. + +Moment of Truth +--------------- + +Now, we should test our extension to see in action. + +- Open a new Inkscape window +- Click on the ``File``>\ ``Import`` dialog +- Select the ``.smi`` file (An example ``.smi`` file is attached above + under `Resources <#resources>`__) and double-click on it. You should + see the following output: + +.. figure:: resources/call_extension_success.gif + :alt: Did_It_Work + + Did_It_Work diff --git a/share/extensions/docs/tutorial/my-first-text-extension.rst b/share/extensions/docs/tutorial/my-first-text-extension.rst new file mode 100644 index 0000000..7fb9a31 --- /dev/null +++ b/share/extensions/docs/tutorial/my-first-text-extension.rst @@ -0,0 +1,223 @@ +My first text extension +======================= + +This article will teach you the basics of writing a Text Extension for +Inkscape using the ``inkex`` Extensions API. + +Introduction +------------ + +Any extension that manipulates text in any way is a Text Extension. Text +Extensions can broadly be categorized in two types based on the type of +manipulation they do to text: + +1. **Manipulating the text itself** - like changing case. +2. **Changing attributes of the text** like font, color, size, etc. + There can also be extensions which are a hybrid of both the above + types. + +In this article we will create an extension named ``Stronger Text``. It +is a *Type 2* Text Extension and it will make the selected text bold and +it will also italicize it. We will also see an example of creating a +*Type 1* Text Extension. + +.. hint:: + + This article assumes you create all files in the User Extensions + directory which is listed at + ``Edit``>\ ``Preferences``>\ ``System`` - ``User Extensions:`` in + Inkscape. + +Step 0 : The Boilerplate +------------------------ + +Like any other Inkscape extension, this extension will also have two files. +So, create a ``stronger_text.inx`` file and a ``stronger_text.py`` file. + +- ``stronger_text.inx``: It will have the necessary information + for Inkscape to be able to recognize your extension as a valid + Inkscape extension. It will also have the declaration of any + interface for your extension. +- ``stronger_text.py``: It will have + the actual Python code your extension will execute. + +.. hint:: + + There is another file that is worth mentioning here - the **test** + file which in our case will be ``test_stronger_text.py``. It is not + required to be present for an extension per se, but as a best + practice, the extension code should always be accompanied by test + code. + +Step 1 : Populate the ``*.inx`` file +------------------------------------ + +Our extension **Stronger Text** will have a very basic ``.inx`` file. + +.. code:: xml + + <?xml version="1.0" encoding="UTF-8"?> + <inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension"> + <name>Stronger Text</name> + <id>org.inkscape.text.strongertext</id> + <effect> + <object-type>all</object-type> + <effects-menu> + <submenu name="Text"> + </submenu> + </effects-menu> + </effect> + <script> + <command location="inx" interpreter="python">stronger_text.py</command> + </script> + </inkscape-extension> + +Explanation +~~~~~~~~~~~ + +The lines below help Inkscape uniquely identify our extension so that it +can be displayed under the **Extensions** menu. You should modify these +two lines for your own extension: + +.. code:: xml + + [...] + <name>Stronger Text</name> + <id>org.inkscape.text.strongertext</id> + [...] + +Towards the end of the ``.inx`` file, we change the submenu to ``Text``. +It specifies that this extension should be listed in the **Text** +submenu under the **Extensions** menu in Inkscape UI: + +.. code:: xml + + [...] + <effect> + <object-type>all</object-type> + <effects-menu> + <submenu name="Text"> + </submenu> + </effects-menu> + </effect> + [...] + +Now - Save the file - Close any open Inkscape windows - Relaunch +Inkscape + +After successfuly completing these steps, you should see the Stronger +Text extension in Inkscape UI. + +.. figure:: resources/Inkscape_Recognizes_Our_Extension.gif + :alt: Inkscape Recognizes Our Extension + + Inkscape Recognizes Our Extension + +Currently it doesn’t do anything as we haven’t written anything in the +``stronger_text.py`` file. + +Step 2 : Write the code in ``*.py`` file +---------------------------------------- + +First Things First +^^^^^^^^^^^^^^^^^^ + +To be able to use any extension functionality, you need to import the +``inkex`` module. + +.. code:: py + + import inkex + +Every Text Extension inherits from the :class:`~inkex.extensions.TextExtension` class provided +by the ``inkex`` API. Let’s name our class ``StrongerText`` (an +arbitrary name) and inherit the :class:`~inkex.extensions.TextExtension` class. + +.. code:: py + + import inkex + + class StrongerText(inkex.TextExtension): + #implement functionality here + pass + +The ``TextExtension`` class provides us with methods to manipulate the +text. + +Our extension ``Stronger Text`` is a *Type 2* extension as it needs to +change the attributes of text. To get access to the attributes of the +text, we need to override the :func:`~inkex.extensions.TextExtension.process_element` method. + +.. code:: py + + import inkex + + class StrongerText(inkex.TextExtension): + def process_element(self, text_node): + text_node.style["font-weight"] = "bold" + text_node.style["font-style"] = "italic" + #text_node.style["attribute-name"] = "value" + + StrongerText().run() + +.. _explanation-1: + +Explanation +~~~~~~~~~~~ + +| ``text_node.style`` provides us with a dictionary (technically it’s an + ``OrderedDict``) which we can use to change the attributes of the text + by using the attribute name as a key. +| When a standard inkex-based Text Extension is run, it will call a + method called :func:`~inkex.extensions.TextExtension.effect` on the ``TextExtension`` class which then + eventually calls our(``StrongerText``\ ’s) ``process_element`` + function. \**\* If your extension is a *Type 1* Text Extension, i.e, + it’s purpose is to take text from Inkscape, transform/manipulate it, + and return it to Inkscape, you just need to override the + :func:`~inkex.extensions.TextExtension.process_chardata` function like so: + +.. code:: py + + import inkex + + class UpperCase(inkex.TextExtension): + def process_chardata(self, text): + # do some more manipulations here if you want + return text.upper() + + UpperCase().run() + +.. _explanation-2: + +Explanation +~~~~~~~~~~~ + +The ``text`` parameter in the :func:`~inkex.extensions.TextExtension.process_chardata` function receives +the text from Inkscape as a Python string. In the :func:`~inkex.extensions.TextExtension.process_chardata` +function itself, we can manipulate the string in any way to our +liking. We then return the manipulated string. + +Infact, if you’ve used the ``UPPERCASE`` extension in Inkscape from +the ``Extensions``>\ ``Text``>\ ``Change Case`` submenu, it is +identical to the Extension we just wrote! + +.. hint:: + + This *Type 1* Extension + will have an almost identical ``.inx`` file with changes in places + like the ``<name>`` and ``<id>`` tags and a separate ``.py`` file with + the above code in it. + +Moment of Truth +--------------- + +Now, we should test our extension to see it in action. - Select some +Text (preferably a font that has bold and italics styles available) - +Click on the **Stronger Text** extension + +The result should appear like this: + +.. figure:: resources/Text_Ext_Moment_of_truth.gif + :alt: A gif showing that the extension works. + + Did It Work? (yes, indeed) diff --git a/share/extensions/docs/tutorial/resources/Call_Extension_Failure.png b/share/extensions/docs/tutorial/resources/Call_Extension_Failure.png Binary files differnew file mode 100644 index 0000000..33629c3 --- /dev/null +++ b/share/extensions/docs/tutorial/resources/Call_Extension_Failure.png diff --git a/share/extensions/docs/tutorial/resources/Inkscape_Recognizes_Our_Extension.gif b/share/extensions/docs/tutorial/resources/Inkscape_Recognizes_Our_Extension.gif Binary files differnew file mode 100644 index 0000000..677c90a --- /dev/null +++ b/share/extensions/docs/tutorial/resources/Inkscape_Recognizes_Our_Extension.gif diff --git a/share/extensions/docs/tutorial/resources/Smiles_Format.gif b/share/extensions/docs/tutorial/resources/Smiles_Format.gif Binary files differnew file mode 100644 index 0000000..ab5bf4b --- /dev/null +++ b/share/extensions/docs/tutorial/resources/Smiles_Format.gif diff --git a/share/extensions/docs/tutorial/resources/Text_Ext_Moment_of_truth.gif b/share/extensions/docs/tutorial/resources/Text_Ext_Moment_of_truth.gif Binary files differnew file mode 100644 index 0000000..3ecc301 --- /dev/null +++ b/share/extensions/docs/tutorial/resources/Text_Ext_Moment_of_truth.gif diff --git a/share/extensions/docs/tutorial/resources/call_extension_success.gif b/share/extensions/docs/tutorial/resources/call_extension_success.gif Binary files differnew file mode 100644 index 0000000..d1ed5c6 --- /dev/null +++ b/share/extensions/docs/tutorial/resources/call_extension_success.gif diff --git a/share/extensions/docs/tutorial/resources/make_red_extension.zip b/share/extensions/docs/tutorial/resources/make_red_extension.zip Binary files differnew file mode 100644 index 0000000..6873a9b --- /dev/null +++ b/share/extensions/docs/tutorial/resources/make_red_extension.zip diff --git a/share/extensions/docs/tutorial/resources/stroke-parity-widget.png b/share/extensions/docs/tutorial/resources/stroke-parity-widget.png Binary files differnew file mode 100644 index 0000000..48d8b9b --- /dev/null +++ b/share/extensions/docs/tutorial/resources/stroke-parity-widget.png diff --git a/share/extensions/docs/tutorial/resources/stroke_parity_extension.zip b/share/extensions/docs/tutorial/resources/stroke_parity_extension.zip Binary files differnew file mode 100644 index 0000000..06b0e7b --- /dev/null +++ b/share/extensions/docs/tutorial/resources/stroke_parity_extension.zip diff --git a/share/extensions/docs/tutorial/resources/template_effect.zip b/share/extensions/docs/tutorial/resources/template_effect.zip Binary files differnew file mode 100644 index 0000000..be5a051 --- /dev/null +++ b/share/extensions/docs/tutorial/resources/template_effect.zip diff --git a/share/extensions/docs/tutorial/resources/vanillin.smi b/share/extensions/docs/tutorial/resources/vanillin.smi new file mode 100644 index 0000000..964c95e --- /dev/null +++ b/share/extensions/docs/tutorial/resources/vanillin.smi @@ -0,0 +1 @@ +COc1cc(C=O)ccc1O diff --git a/share/extensions/docs/tutorial/simple-path-extension.rst b/share/extensions/docs/tutorial/simple-path-extension.rst new file mode 100644 index 0000000..143b6b1 --- /dev/null +++ b/share/extensions/docs/tutorial/simple-path-extension.rst @@ -0,0 +1,162 @@ +A more complex example: reading path data and changing the style +================================================================ + +.. note:: + This tutorial builds on the files created in :ref:`first-effect-extension`. + +Resources +--------- + +- :download:`Example solution <resources/stroke_parity_extension.zip>` + +Introduction +------------------ + +We are going to write an effect extension that will change any path with +an even number of nodes to a user-defined stroke and any path with an odd +number of nodes to a different user-defined stroke color. + +From :ref:`first-effect-extension`, we already know how to create the extension boilerplate +(without parameters), how to iterate over the selection and how to modify the style. + +This extension adds two more things: Paths and Parameters. + +Setting up the inx file +----------------------- + +Duplicate the files from the `make_red_extension`, and change all the filenames, class names +and extension ID to `stroke_parity_extension`. + +Now for the parameters for the colors. We're also going to add a checkbox to remove the fill of the +selected paths. The params are defined after ``<id>`` and before ``<effect>`` in the inx file: + +.. code:: xml + + <param name="remove_fill" type="bool" gui-text="Remove fill">false</param> + <label appearance="header">Stroke color for path based on number of nodes</label> + <param name="tab" type="notebook"> + <page name="even" gui-text="Even"> + <param name="even_color" type="color" gui-text="Even stroke color:">4278190335</param> + </page> + <page name="odd" gui-text="Odd"> + <param name="odd_color" type="color" gui-text="Odd stroke color:">65535</param> + </page> + </param> + +The default colors are defined as content of the ``<param>`` element, and they are passed as +integers in RGBA format, so for a "red" color (i.e. ``#ff000ff``), one has to write +``256^3*255 + 255 = 4278190335``. + +Color widgets are quite large, so the two widgets are added in a notebook (i.e. two tabs). + +You can also change the submenu the extension will be listed in to ``Modify Path``. + +Restart Inkscape. If you click the extension in the menu, it should look something like this: + +.. figure:: resources/stroke-parity-widget.png + +Adding the parameters to the python file +---------------------------------------- + +When Inkscape calls the extension in the current state, an error message is shown:: + + usage: stroke_parity_extension.py [-h] [--output OUTPUT] [--id IDS] + [--selected-nodes SELECTED_NODES] + [INPUT_FILE] + stroke_parity_extension.py: error: unrecognized arguments: --remove_fill=false --tab=even --even_color=4278190335 --odd_color=65535 + +We also have to tell the ``MakeRedExtension`` class how to parse the parameters. This is done in the +:func:`~inkex.base.InkscapeExtension.add_arguments` method. We have four parameters: the two colors, +the checkbox and the currently selected tab. + +.. code:: python + + def add_arguments(self, pars): + pars.add_argument("--even_color", type=inkex.Color, default=inkex.Color("red")) + pars.add_argument("--odd_color", type=inkex.Color, default=inkex.Color("blue")) + pars.add_argument("--remove_fill", type=inkex.Boolean, default=False) + pars.add_argument("--tab", type=str, default="stroke") + +In ``effect``, these parameters are available as e.g. ``self.options.even_color``. + +.. hint:: + + :func:`inkex.Boolean <inkex.utils.Boolean>` and :class:`inkex.Color <inkex.colors.Color>` are + special types that preprocess the parsed parameter, so that ``self.options.even_color`` is an + :class:`inkex.colors.Color` object and not the string ``"4278190335"``. + +Processing the paths +-------------------- + +Modify the ``effect`` method as follows: + +.. code-block:: python + :linenos: + + def effect(self): + for elem in self.svg.selection.filter(inkex.PathElement): + elem.set('inkscape:modified_by_tutorial', 'Yes') + elem.style['stroke-width'] = 2.0 + if len(elem.path) % 2: # odd number + elem.style.set_color(self.options.odd_color, 'stroke') + else: + elem.style.set_color(self.options.even_color, 'stroke') + + if self.options.remove_fill: + elem.style["fill"] = None + +Code Explanation +~~~~~~~~~~~~~~~~ + +Firstly, we need to loop through each of the selected paths. We already now how to do this +from the first tutorial, but we now filter the selection to only contain +:class:`~inkex.elements._polygons.PathElement` objects - since we want to count the number of nodes. +If other objects, such as a text object or rectangle, are selected, they are ignored. So, for each +iteration of the loop, ``elem`` will contain one of the selected path +objects. + +The second line sets an attribute ``inkscape:modified_by_tutorial`` on +the xml element ``elem``. The attribute API will handle the ``inkscape`` +namespace for us, so we can use a simple colon to indicate the +namespace. This is how all non-special attributes are set and gotten. +But on top of this simple API we don’t have to worry about parsing the +path, transform or the style attributes. Instead the inkex API does all +the parsing for us and provides us with a way to change styles, modify +paths and even do transformations without manual parsing. + +Then we set a stroke-width of 2, using the standard style API which is +assigning into a type of ordered dictionary. + +Next we use the Path API to get the path data of the element, using +:attr:`~inkex.elements._base.ShapeElement.path`. This is an :class:`inkex.paths.Path` object, +which is a list of all path commands (such as Moveto, Lineto, Curveto...). We can use the length +of the list to determine the number of segments, which is (for the simple case of open paths) equal +to the number of nodes. + +We then use the Color API to assign the correct stroke color. The parameters are passed in RGBA format, +and we can use the :func:`~inkex.styles.Style.set_color` function to set opacity and stroke at the same time. +Stroke and stroke opacity are two different style properties, so we can’t set them with a simple +assignment. + +Last we set the fill to ``None`` (``"none"`` would work as well) - if the checkbox for this is +checked. + +Testing the extension +--------------------- + +As we've already learned, there’s no need to set, save or do anything else as we’ve +modified the style in place. + +Save your python script, and re-launch Inkscape. If inkscape was already +open, close it first. You should find your new extension available in +the ``Modify Path`` menu. + +Draw some shapes with the pen tool, select some of the shapes and use the extension. +You should see the stroke color change for each of the objects selected. + +.. note:: + For closed paths, the extension gives incorrect results, because the closing "Z" / "z" + command does not add a new node, but is counted by ``len(path)``. + + This can be avoided by manually counting segments except that are not ZoneClose (zoneClose) commands. + |