NonSci output option and InkScape extension added by Aleon

This commit is contained in:
Marcus Lindvall 2023-01-31 11:02:40 +01:00
parent 0609c59676
commit a124f9f415
6 changed files with 269 additions and 12 deletions

View file

@ -1,7 +1,7 @@
all: clean install
install:
python setup.py install
python3 setup.py install
clean:
rm -rf build
@ -14,21 +14,21 @@ clean:
find . -name "*__pycache__" -type d -prune -exec rm -rf {} \;
publish: clean
python setup.py register
python setup.py sdist upload
python3 setup.py register
python3 setup.py sdist upload
check: test flake8
test:
python test_scour.py
python3 test_scour.py
test_version:
PYTHONPATH=. python -m scour.scour --version
PYTHONPATH=. python3 -m scour.scour --version
test_help:
PYTHONPATH=. python -m scour.scour --help
PYTHONPATH=. python3 -m scour.scour --help
flake8:
flake8 --max-line-length=119

View file

@ -18,20 +18,22 @@ Scour is open-source and licensed under [Apache License 2.0](https://github.com/
Scour was originally developed by Jeff "codedread" Schiller and Louis Simard in in 2010.
The project moved to GitLab in 2013 an is now maintained by Tobias "oberstet" Oberstein and Patrick "Ede_123" Storz.
This fork was created by Alexander Olsson ([alex@aleon.se](mailto:alex@aleon.se?subject=Scour)) at Aleon Apps.
## Installation
Scour requires [Python](https://www.python.org) 2.7 or 3.4+. Further, for installation, [pip](https://pip.pypa.io) should be used.
To install the [latest release](https://pypi.python.org/pypi/scour) of Scour from PyPI:
To install this fork:
```console
pip install scour
sudo make
```
To install the [latest trunk](https://github.com/codedread/scour) version (which might be broken!) from GitHub:
## Extension
Place the modified extension files in the Inkscape extension directory
```console
pip install https://github.com/codedread/scour/archive/master.zip
sudo cp extension/* /usr/share/inkscape/extensions/
```
## Usage
@ -61,3 +63,10 @@ Maximum scrubbing and a compressed SVGZ file:
scour -i input.svg -o output.svgz --enable-viewboxing --enable-id-stripping \
--enable-comment-stripping --shorten-ids --indent=none
```
Remove scientific notation from path data:
```console
scour -i input.svg -o output.svgz --nonsci-output
```

132
extension/output_scour.inx Normal file
View file

@ -0,0 +1,132 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>Optimized SVG Output</name>
<id>org.inkscape.output.scour_inkscape</id>
<param name="tab" type="notebook">
<page name="Options" gui-text="Options">
<param gui-text="Number of significant digits for coordinates:"
gui-description="Specifies the number of significant digits that should be output for coordinates. Note that significant digits are *not* the number of decimals but the overall number of digits in the output. For example if a value of &quot;3&quot; is specified, the coordinate 3.14159 is output as 3.14 while the coordinate 123.675 is output as 124."
name="set-precision" type="int" min="1">5</param>
<spacer/>
<param gui-text="Shorten color values"
gui-description="Convert all color specifications to #RRGGBB (or #RGB where applicable) format."
name="simplify-colors" type="bool">true</param>
<param gui-text="Convert CSS attributes to XML attributes"
gui-description="Convert styles from style tags and inline style=&quot;&quot; declarations into XML attributes."
name="style-to-xml" type="bool">true</param>
<spacer/>
<param gui-text="Collapse groups"
gui-description="Remove useless groups, promoting their contents up one level. Requires &quot;Remove unused IDs&quot; to be set."
name="group-collapsing" type="bool">true</param>
<param gui-text="Create groups for similar attributes"
gui-description="Create groups for runs of elements having at least one attribute in common (e.g. fill-color, stroke-opacity, ...)."
name="create-groups" type="bool">true</param>
<spacer/>
<param gui-text="Keep editor data"
gui-description="Don't remove editor-specific elements and attributes. Currently supported: Inkscape, Sodipodi and Adobe Illustrator."
name="keep-editor-data" type="bool">false</param>
<param gui-text="Remove scientific notation"
gui-description="Remove scientific notation from path data."
name="nonsci-output" type="bool">false</param>
<param gui-text="Keep unreferenced definitions"
gui-description="Keep element definitions that are not currently used in the SVG"
name="keep-unreferenced-defs" type="bool">false</param>
<spacer/>
<param gui-text="Work around renderer bugs"
gui-description="Works around some common renderer bugs (mainly libRSVG) at the cost of a slightly larger SVG file."
name="renderer-workaround" type="bool">true</param>
</page>
<page name="Output" gui-text="SVG Output">
<label appearance="header">Document options</label>
<param gui-text="Remove the XML declaration"
gui-description="Removes the XML declaration (which is optional but should be provided, especially if special characters are used in the document) from the file header."
name="strip-xml-prolog" type="bool">false</param>
<param gui-text="Remove metadata"
gui-description="Remove metadata tags along with all the contained information, which may include license and author information, alternate versions for non-SVG-enabled browsers, etc."
name="remove-metadata" type="bool">false</param>
<param gui-text="Remove comments"
gui-description="Remove all XML comments from output."
name="enable-comment-stripping" type="bool">false</param>
<param gui-text="Embed raster images"
gui-description="Resolve external references to raster images and embed them as Base64-encoded data URLs."
name="embed-rasters" type="bool">true</param>
<param gui-text="Enable viewboxing"
gui-description="Set page size to 100%/100% (full width and height of the display area) and introduce a viewBox specifying the drawings dimensions."
name="enable-viewboxing" type="bool">false</param>
<spacer/>
<label appearance="header">Pretty-printing</label>
<param gui-text="Format output with line-breaks and indentation"
gui-description="Produce nicely formatted output including line-breaks. If you do not intend to hand-edit the SVG file you can disable this option to bring down the file size even more at the cost of clarity."
name="line-breaks" type="bool">true</param>
<param gui-text="Indentation characters:"
gui-description="The type of indentation used for each level of nesting in the output. Specify &quot;None&quot; to disable indentation. This option has no effect if &quot;Format output with line-breaks and indentation&quot; is disabled."
name="indent" type="optiongroup" appearance="combo">
<option value="space">Space</option>
<option value="tab">Tab</option>
<option context="Indent" value="none">None</option>
</param>
<param gui-text="Depth of indentation:"
gui-description="The depth of the chosen type of indentation. E.g. if you choose &quot;2&quot; every nesting level in the output will be indented by two additional spaces/tabs."
name="nindent" type="int">1</param>
<param gui-text="Strip the &quot;xml:space&quot; attribute from the root SVG element"
gui-description="This is useful if the input file specifies &quot;xml:space='preserve'&quot; in the root SVG element which instructs the SVG editor not to change whitespace in the document at all (and therefore overrides the options above)."
name="strip-xml-space" type="bool">false</param>
</page>
<page name="IDs" gui-text="IDs">
<param gui-text="Remove unused IDs"
gui-description="Remove all unreferenced IDs from elements. Those are not needed for rendering."
name="enable-id-stripping" type="bool">true</param>
<spacer/>
<param gui-text="Shorten IDs"
gui-description="Minimize the length of IDs using only lowercase letters, assigning the shortest values to the most-referenced elements. For instance, &quot;linearGradient5621&quot; will become &quot;a&quot; if it is the most used element."
name="shorten-ids" type="bool">false</param>
<param gui-text="Prefix shortened IDs with:"
gui-description="Prepend shortened IDs with the specified prefix."
name="shorten-ids-prefix" type="string"></param>
<spacer/>
<param gui-text="Preserve manually created IDs not ending with digits"
gui-description="Descriptive IDs which were manually created to reference or label specific elements or groups (e.g. #arrowStart, #arrowEnd or #textLabels) will be preserved while numbered IDs (as they are generated by most SVG editors including Inkscape) will be removed/shortened."
name="protect-ids-noninkscape" type="bool">true</param>
<param gui-text="Preserve the following IDs:"
gui-description="A comma-separated list of IDs that are to be preserved."
name="protect-ids-list" type="string"></param>
<param gui-text="Preserve IDs starting with:"
gui-description="Preserve all IDs that start with the specified prefix (e.g. specify &quot;flag&quot; to preserve &quot;flag-mx&quot;, &quot;flag-pt&quot;, etc.)."
name="protect-ids-prefix" type="string"></param>
</page>
<page name="About" gui-text="About">
<hbox>
<image>output_scour.svg</image>
<spacer/>
<vbox>
<spacer/>
<label>Optimized SVG Output is provided by</label>
<label appearance="header" indent="1">Scour - An SVG Scrubber</label>
<spacer/>
<label>For details please refer to</label>
<label appearance="url" indent="1">https://github.com/scour-project/scour</label>
</vbox>
</hbox>
<spacer size="expand"/>
<hbox>
<label>This version of the extension is designed for</label>
<label>Scour 0.31+</label>
</hbox>
<param name="scour-version" type="string" gui-hidden="true">0.31</param> <!-- this parameter is checked programmatically in the extension to show a warning -->
<param gui-text="Show warnings for older versions of Scour"
name="scour-version-warn-old" type="bool">true</param>
</page>
</param>
<output>
<extension>.svg</extension>
<mimetype>image/svg+xml</mimetype>
<filetypename>Optimized SVG (*.svg)</filetypename>
<filetypetooltip>Scalable Vector Graphics</filetypetooltip>
</output>
<script>
<command location="inx" interpreter="python">output_scour.py</command>
</script>
</inkscape-extension>

100
extension/output_scour.py Normal file
View file

@ -0,0 +1,100 @@
#!/usr/bin/env python
"""
Run the scour module on the svg output.
"""
import inkex
from inkex.localization import inkex_gettext as _
try:
from packaging.version import Version
except ImportError:
raise inkex.DependencyError(
_(
"""Failed to import module 'packaging'.
Please make sure it is installed (e.g. using 'pip install packaging'
or 'sudo apt-get install python3-packaging') and try again.
"""
)
)
try:
import scour
from scour.scour import scourString
except ImportError:
raise inkex.DependencyError(
_(
"""Failed to import module 'scour'.
Please make sure it is installed (e.g. using 'pip install scour'
or 'sudo apt-get install python3-scour') and try again.
"""
)
)
class ScourInkscape(inkex.OutputExtension):
"""Scour Inkscape Extension"""
# Scour options
def add_arguments(self, pars):
pars.add_argument("--tab")
pars.add_argument("--simplify-colors", type=inkex.Boolean, dest="simple_colors")
pars.add_argument("--style-to-xml", type=inkex.Boolean)
pars.add_argument(
"--group-collapsing", type=inkex.Boolean, dest="group_collapse"
)
pars.add_argument("--create-groups", type=inkex.Boolean, dest="group_create")
pars.add_argument("--enable-id-stripping", type=inkex.Boolean, dest="strip_ids")
pars.add_argument("--shorten-ids", type=inkex.Boolean)
pars.add_argument("--shorten-ids-prefix")
pars.add_argument("--embed-rasters", type=inkex.Boolean)
pars.add_argument(
"--keep-unreferenced-defs", type=inkex.Boolean, dest="keep_defs"
)
pars.add_argument("--keep-editor-data", type=inkex.Boolean)
pars.add_argument("--nonsci-output", type=inkex.Boolean)
pars.add_argument("--remove-metadata", type=inkex.Boolean)
pars.add_argument("--strip-xml-prolog", type=inkex.Boolean)
pars.add_argument("--set-precision", type=int, dest="digits")
pars.add_argument("--indent", dest="indent_type")
pars.add_argument("--nindent", type=int, dest="indent_depth")
pars.add_argument("--line-breaks", type=inkex.Boolean, dest="newlines")
pars.add_argument(
"--strip-xml-space", type=inkex.Boolean, dest="strip_xml_space_attribute"
)
pars.add_argument("--protect-ids-noninkscape", type=inkex.Boolean)
pars.add_argument("--protect-ids-list")
pars.add_argument("--protect-ids-prefix")
pars.add_argument("--enable-viewboxing", type=inkex.Boolean)
pars.add_argument(
"--enable-comment-stripping", type=inkex.Boolean, dest="strip_comments"
)
pars.add_argument("--renderer-workaround", type=inkex.Boolean)
# options for internal use of the extension
pars.add_argument("--scour-version")
pars.add_argument("--scour-version-warn-old", type=inkex.Boolean)
def save(self, stream):
# version check if enabled in options
if self.options.scour_version_warn_old:
scour_version = scour.__version__
scour_version_min = self.options.scour_version
if Version(scour_version) < Version(scour_version_min):
raise inkex.AbortExtension(
f"""
The extension 'Optimized SVG Output' is designed for Scour {scour_version_min} or later but you're
using the older version Scour {scour_version}.
Note: You can permanently disable this message on the 'About' tab of the extension window."""
)
del self.options.scour_version
del self.options.scour_version_warn_old
# do the scouring
stream.write(scourString(self.svg.tostring(), self.options).encode("utf8"))
if __name__ == "__main__":
ScourInkscape().run()

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 33 KiB

View file

@ -2918,6 +2918,7 @@ def scourCoordinates(data, options, force_whitespace=False, control_points=[], f
for coord in data:
is_control_point = c in control_points
scouredCoord = scourUnitlessLength(coord,
nonsci_output=options.nonsci_output,
renderer_workaround=options.renderer_workaround,
is_control_point=is_control_point)
# don't output a space if this number starts with a dot (.) or minus sign (-); we only need a space if
@ -2964,7 +2965,8 @@ def scourLength(length):
return scourUnitlessLength(length.value) + Unit.str(length.units)
def scourUnitlessLength(length, renderer_workaround=False, is_control_point=False): # length is of a numeric type
def scourUnitlessLength(length, nonsci_output=False, renderer_workaround=False, is_control_point=False): # length is of a numeric type
"""
Scours the numeric part of a length only. Does not accept units.
@ -3001,6 +3003,12 @@ def scourUnitlessLength(length, renderer_workaround=False, is_control_point=Fals
nonsci = '-' + nonsci[2:] # remove the 0, leave the minus and dot
return_value = nonsci
# Prevent scientific notation, interferes with some label maker software
if nonsci_output:
return return_value
# Gather the scientific notation version of the coordinate which
# can only be shorter if the length of the number is at least 4 characters (e.g. 1000 = 1e3).
if len(nonsci) > 3:
@ -3958,6 +3966,9 @@ _option_group_optimization.add_option("--keep-editor-data",
action="store_true", dest="keep_editor_data", default=False,
help="won't remove Inkscape, Sodipodi, Adobe Illustrator "
"or Sketch elements and attributes")
_option_group_optimization.add_option("--nonsci-output",
action="store_true", dest="nonsci_output", default=False,
help="Remove scientific notation from path data")
_option_group_optimization.add_option("--keep-unreferenced-defs",
action="store_true", dest="keep_defs", default=False,
help="won't remove elements within the defs container that are unreferenced")