diff --git a/Makefile b/Makefile index 09389b5..532618a 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/README.md b/README.md index ace6711..c5c0bc8 100644 --- a/README.md +++ b/README.md @@ -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 +``` + diff --git a/extension/output_scour.inx b/extension/output_scour.inx new file mode 100644 index 0000000..b6ce893 --- /dev/null +++ b/extension/output_scour.inx @@ -0,0 +1,132 @@ + + + Optimized SVG Output + org.inkscape.output.scour_inkscape + + + + 5 + + true + true + + true + true + + false + false + false + + true + + + + false + false + false + true + false + + + true + + + + + + 1 + false + + + true + + false + + + true + + + + + + output_scour.svg + + + + + + + + + + + + + + + + 0.31 + true + + + + + .svg + image/svg+xml + Optimized SVG (*.svg) + Scalable Vector Graphics + + + + diff --git a/extension/output_scour.py b/extension/output_scour.py new file mode 100644 index 0000000..eebfb8a --- /dev/null +++ b/extension/output_scour.py @@ -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() diff --git a/extension/output_scour.svg b/extension/output_scour.svg new file mode 100644 index 0000000..8f1b941 --- /dev/null +++ b/extension/output_scour.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/scour/scour.py b/scour/scour.py index 9d19906..8c907de 100644 --- a/scour/scour.py +++ b/scour/scour.py @@ -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")