Commit graph

64 commits

Author SHA1 Message Date
Niels Thykier
7abb6af7b5
Rename testX.py to test_X.py to make py.test work out of the box
This rename makes py.test/py.test-3 find the test suite out of the
box.  Example command lines:

       # Running the test suite (optionally include "-v")
       $ py.test-3
       # Running the test suite with coverage enabled (and branch
       # coverage).
       $ py.test-3 --cov=scour --cov-report=html --cov-branch

Signed-off-by: Niels Thykier <niels@thykier.net>
2020-05-17 17:45:25 +00:00
Niels Thykier
dd2155e576 Merge sibling <g> nodes with identical attributes
In some cases, gnuplot generates a very suboptimal SVG content of the
following pattern:

        <g color="black" fill="none" stroke="currentColor">
        <path d="m82.5 323.3v-4.1" stroke="#000"/>
        </g>
        <g color="black" fill="none" stroke="currentColor">
        <path d="m116.4 323.3v-4.1" stroke="#000"/>
        </g>
        ... repeated 10+ more times here ...
        <g color="black" fill="none" stroke="currentColor">
        <path d="m65.4 72.8v250.5h420v-250.5h-420z" stroke="#000"/>
        </g>

A more optimal pattern would be:

        <g color="black" fill="none" stroke="#000">
        <path d="m82.5 323.3v-4.1"/>
        <path d="m116.4 323.3v-4.1"/>
        ... 10+ more paths here ...
        <path d="m65.4 72.8v250.5h420v-250.5h-420z"/>
        </g>

This patch enables that optimization by handling the merging of two
sibling <g> entries that have identical attributes.  In the above
example that does not solve the rewrite from "currentColor" to "#000"
for the stroke attribute.  However, the existing code already handles
that automatically after the <g> elements have been merged.

This change provides comparable results to --create-groups as shown by
the following diagram while being a distinct optimization:

       +----------------------------+-------+--------+
       |           Test             | Size  |  in %  |
       +----------------------------+-------+--------+
       | baseline                   | 17961 |  100%  |
       | baseline + --create-groups | 17418 |  97.0% |
       | patched                    | 16939 |  94.3% |
       | patched + --create-groups  | 16855 |  93.8% |
       +----------------------------+-------+--------+

The image used in the size table above was generated based on the
instructions from https://bugs.debian.org/858039#10 with gnuplot 5.2
patchlevel 2.  Beyond the test-based "--create-groups", the following
scour command-line parameters were used:
      --enable-id-stripping --enable-comment-stripping \
      --shorten-ids --indent=none

Note that the baseline was scour'ed repeatedly to stablize the image
size.

Signed-off-by: Niels Thykier <niels@thykier.net>
2020-05-17 19:37:32 +02:00
Patrick Storz
f65ca60809 Fix deprecation warning 2020-05-17 17:10:26 +02:00
Patrick Storz
4fe2655f86
Merge pull request #187 from nthykier/fix-gh-186-shorten-id-recycle-used-ids
Enable shortenIDs to recycle existing IDs
2020-05-17 16:48:18 +02:00
Niels Thykier
58b75c314a Add test case for #198/#202
Signed-off-by: Niels Thykier <niels@thykier.net>
2020-05-17 16:29:08 +02:00
Niels Thykier
f61b4d36d6 Add test case for #203
Signed-off-by: Niels Thykier <niels@thykier.net>
2020-05-17 16:13:45 +02:00
Eduard Braun
651694a6c0 Add unittests for whitespace handling in text node
Also expand/fix the test for line endings
2018-07-03 22:53:05 +02:00
Patrick Storz
8c95d950af
Merge pull request #192 from nthykier/gh-189-order-vs-SVGLength
Work around an exception in removeDefaultAttributeValue() caused by some rarely used filter attributes that allow an optional second value which SVGLength does not handle properly
2018-06-30 19:03:15 +02:00
Patrick Storz
9f4a707bb7
Merge pull request #178 from nthykier/gh-163-path-rewrite
Correct handling of "m0 0" vs. "z" commands
2018-06-29 19:11:53 +02:00
Niels Thykier
8a2892b458 Avoid crashing on stdDeviation attribute
Signed-off-by: Niels Thykier <niels@thykier.net>
2018-04-21 06:39:08 +00:00
Niels Thykier
18e57cddae Avoid crashing on "scale(1)" (short for "scale(1, 1)")
The scale function on the transform attribute has a short form, where
only the first argument is used.  But optimizeTransform would always
assume that there were two when checking for the identity scale.

Closes: #190
Signed-off-by: Niels Thykier <niels@thykier.net>
2018-04-18 05:41:35 +00:00
Niels Thykier
a459d629c1 removeDefaultAttributeValue: Special-case order attribute
Scour tried to handle "order" attribute as a SVGLength.  However, the
"order" attribute *can* consist of two integers according to the
[SVG 1.1 Specification] and SVGLength is not designed to handle that.

With this change, we now pretend that "order" is a string, which side
steps this issue.

[SVG 1.1 Specification]: https://www.w3.org/TR/SVG11/single-page.html#filters-feConvolveMatrixElementOrderAttribute

Closes: #189
Signed-off-by: Niels Thykier <niels@thykier.net>
2018-04-17 19:48:37 +00:00
Niels Thykier
d6406a3470 shortenIDs: Avoid pointless renames of IDs
With the current code, scour could do a pointless remap of an ID,
where there is no benefit in it.  Consider:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 <defs>
  <rect id="a" width="80" height="50" fill="red"/>
  <rect id="b" width="80" height="50" fill="blue"/>
 </defs>
 <use xlink:href="#a"/>
 <use xlink:href="#b"/>
 <use xlink:href="#b"/>
</svg>
```

In this example, there is no point in swapping the IDs - even if "#b"
is used more often than "#a", they have the same length.  Besides a
performance win on an already scour'ed image, it also mean scour will
behave like a function with a fixed-point (i.e. scour eventually stops
altering the image).

To solve this, we no longer check whether an we find exactly the same
ID.  Instead, we look at the length of the new ID compared to the
original.  This gives us a slight complication as we can now "reserve"
a "future" ID to avoid the rename.

Thanks to Eduard "Ede_123" Braun for providing the test case.

Signed-off-by: Niels Thykier <niels@thykier.net>
2018-04-15 17:34:24 +00:00
Eduard Braun
103dcc0a48
Fix handling of boolean flags in elliptical path commands (#183)
* properly parse paths without space after boolean flags (fixes #161)
* omit space after boolean flag to shave off a few bytes when not using renderer workarounds
2018-04-08 15:32:47 +02:00
Niels Thykier
38274f75bc Implement a basic rewrite of redundant commands
This basic implementation can drop and rewrite some cases of "m0 0"
and "z" without triggering the issues experienced in #163.  It works
by analysing the path backwards and tracking "z" and "m" commands.

Signed-off-by: Niels Thykier <niels@thykier.net>
2018-03-11 08:33:50 +00:00
Niels Thykier
a2c94c96fb Disable the "m0 0"-optimization as it is wrong in some cases
The "m0 0" rewrite gets some cases wrong, like:

         m150 240h200m0 0 150 150v-300z

Scour rewrote that into the following
         m150 240h200l150 150v-300z

However, these two paths do not produce an identical figure at all.
The first is a line followed by a triangle while the second is a
quadrilateral.

While there are some instances we can rewrite (that scour will no
longer rewrite), these will require an analysis over multiple commands
to determine whether the rewrite is safe.  This will reappear in the
next commit.

Closes: #163
Signed-off-by: Niels Thykier <niels@thykier.net>
2018-03-11 08:25:46 +00:00
Niels Thykier
843706be39 Catch specific exception rather than anything
The bare "except" also catches exceptions like "NameError" and
"SystemExit", which we really should not catch.  In scour.py, use the
most specific exception (NotFoundErr) and in the tests just catch any
"regular" exception.

Reported by flake8.

Signed-off-by: Niels Thykier <niels@thykier.net>
2018-02-17 11:47:36 +01:00
Michael Witten
b20a0698cc tests: Add unit tests for preservation of quotes in CSS styles
These tests will ensure that issues #21 and #56 do not return.
2017-09-03 18:07:27 +02:00
Michael Witten
0a146b7fef tests: Add unit tests for the escaping of quote characters in attribute values 2017-09-03 18:07:27 +02:00
Eduard Braun
cc592c8e8a Improve and fix behaviour when collapsing straight paths segments (#146)
* Do not collapse straight path segments in paths that have intermediate markers (see #145). The intermediate nodes might be unnecessary for the shape of the path, but their markers would be lost.
* Collapse subpaths of moveto `m` and lineto `l` commands if they have the same direction (before we only collapsed horizontal/vertical `h`/`v` lineto commands)
* Attempt to collapse lineto `l` commands into a preceding moveto `m` command (these are then called "implicit lineto commands")
* Preserve empty path segments if they have `stroke-linecap` set to `round` or `square`. They render no visible line but a tiny dot or square.
2017-05-18 00:53:25 +02:00
Eduard Braun
98e3040645 Add unittest for --set-c-precision (7cb0d36d72) 2017-02-25 19:44:18 +01:00
Eduard Braun
090884a70f Don't force whitespace for elliptical paths (fixes #89)
This was only required in an early draft of the SVG spec (an error that was corrected later, see [1,2])

[1] https://github.com/scour-project/scour/issues/89#issuecomment-244216600
[2] https://github.com/scour-project/scour/issues/89#issuecomment-244337118
2017-02-25 19:44:18 +01:00
Eduard Braun
ffeb76c894 Unittests: remove temporary file 'testscour_temp.svg' after running tests 2017-02-22 22:13:04 +01:00
Eduard Braun
f7d6406d38 Work around https://github.com/travis-ci/travis-ci/issues/3080 as pypy throws if 'ping' can't be executed 2017-02-22 22:07:17 +01:00
Eduard Braun
0ffefcd8bb Unittests for --enable-viewboxing 2017-02-19 16:10:01 +01:00
Eduard Braun
f5a61eeeb3 Even better fix for 8f87118725
(previous solution still did not work for numbers like 123.4 with precision < 3)
2017-02-19 00:57:00 +01:00
Eduard Braun
a69efb3a55 Add unittests for b00b374e64 and 8f87118725 2017-02-18 19:36:19 +01:00
Eduard Braun
6cf8c2b7d9 call sanitizeOptions() in start() to prevent a third-party breakage 2016-11-27 18:52:39 +01:00
Eduard Braun
de1441fd58 Exclude (system specific) absolute paths from test file and add a unittest that creates/tests absolute paths on-the-fly 2016-09-23 23:16:19 +02:00
Eduard Braun
902e112a96 Add unittests for embedding rasters (and --disable-embed-rasters) 2016-09-23 23:14:56 +02:00
Eduard Braun
45a2869a17 Add unittests for --protect-ids-_ options 2016-09-18 18:29:13 +02:00
Eduard Braun
829b630d64 Add unittests which emulate calling the scour module from command line 2016-09-18 17:13:00 +02:00
Eduard Braun
47cfb9aa0e Add unittest for --strip-xml-space 2016-09-18 17:13:00 +02:00
Eduard Braun
d9198d7872 Order imports as suggested by PEP 8 2016-09-15 21:56:36 +02:00
Eduard Braun
99363c9089 Fix all issues detected by pyflakes 2016-09-15 21:31:34 +02:00
Eduard Braun
82df0d2327 More PEP 8 cleanup
(solves all issues reported by `pycodestyle`)
2016-09-15 21:02:15 +02:00
Eduard Braun
fc356815a2 Some reformatting and manually break all long lines at column 119 2016-09-15 01:54:19 +02:00
Eduard Braun
0f1974c1e2 Consistent whitespace across source files according to PEP 8
(mostly automated by using autopep8, fixes #69)
2016-09-15 00:35:13 +02:00
Eduard Braun
082b579410 We don't want spaces in the serialized value of style attributes.
Add a unittest that should catch this and other issues with parsing/serializing the `style` attribute
2016-09-11 14:01:04 +02:00
Eduard Braun
10e687b887 Add unittests for 1cde426009 and 641d2db08a392e4a7df20c700e1accb9cd8d1341 2016-09-11 00:16:17 +02:00
Eduard Braun
1aa5722c6a Fix conversion of cubic Bézier "curveto" commands into "shorthand/smooth curveto" commands. (#110)
When the preceeding path segment is a Bézier curve, too, the first control point of the shorthand defaults to the mirrored version of the second control point of this preceeding path segment. Scour always assumed (0,0) as the control point in this case which could result in modified path data (e.g. #91).
2016-09-06 01:43:36 +02:00
Eduard Braun
ec855211de Fix replacement of duplicate gradients if "fill/stroke" contains fallbacks (#109)
(fixes #79)
2016-09-05 22:44:55 +02:00
Eduard Braun
0c63344ea4 Add a check to prevent we make path data longer by "optimization" 2016-08-31 07:06:42 +02:00
Eduard Braun
21e6c7491b Fix a unittest that failed due to the increased accuracy of paths after 29e005bf7b 2016-08-31 06:32:05 +02:00
Eitot
aa48c90d56 Add options to remove descriptive elements (#102)
* --remove-titles (removes <title>)
* --remove-descriptions (removes <desc>)
* --remove-descriptive-elements (removes <title>, <desc> and <metadata>)
2016-08-29 21:05:12 +02:00
Eduard Braun
842123a393 Fix improper comparison of numeric default attribute values with textvalues resulting in wrongly removed attributes (#101)
For example for `orient="auto"` SVGLength() returns (value=0, units=Unit.INVALID); since the default value for `orient` is zero it was removed as there was check for a valid unit.
2016-08-29 06:37:28 +02:00
Eduard Braun
5844076258 Only attempt to group elements that the content model allows to be children of a <g> when --create-groups is specified. (#98)
(before it could happen that e.g. `tspan` elements were grouped, which is invalid; fixes issues #96 and #97)
2016-08-29 02:33:13 +02:00
Eduard Braun
cbda5dcd86 Add unittests for #66 2016-08-26 23:45:44 +02:00
Eduard Braun
386d5d8656 Allow elements to be found via Document.getElementById() in the minidom document returned by scourXmlFile() (#68) 2016-08-25 21:13:09 +02:00
Eduard Braun
4f23ea7a34 Print usage information if no input file was specified (and no data is available from stdin) (#65)
fixes #34
2016-08-23 21:16:14 +02:00