From 9f38caabaa2273e8d521b70ae7b46ba877ec6b4b Mon Sep 17 00:00:00 2001 From: JSCHILL1 Date: Sat, 25 Apr 2009 02:09:08 -0500 Subject: [PATCH] Removal of stroke:none. Prevent groups from being collapsed if title/desc present. Add option to prevent groups from being collapsed. Unit tests. Started release notes HTML. --- release-notes.html | 88 ++++++++++++++++++++++++++++ scour.py | 28 ++++++--- testscour.py | 26 +++++++- unittests/groups-with-title-desc.svg | 12 ++++ 4 files changed, 145 insertions(+), 9 deletions(-) create mode 100644 release-notes.html create mode 100644 unittests/groups-with-title-desc.svg diff --git a/release-notes.html b/release-notes.html new file mode 100644 index 0000000..74310e2 --- /dev/null +++ b/release-notes.html @@ -0,0 +1,88 @@ + + + + Scour Release Notes + + + +
+
+

Version 0.09

+
+ + + +
+ +
+
+

Version 0.08

+
+ + +
+ +
+
+

Version 0.07

+
+ + +
+ +
+
+

Version 0.06

+
+ + +
+ +
+
+

Version 0.05 and earlier

+
+ + + +
+ + + \ No newline at end of file diff --git a/scour.py b/scour.py index 6ae23b6..a2b139d 100755 --- a/scour.py +++ b/scour.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Scour -# Version 0.08 +# Version 0.09 # # Copyright 2009 Jeff Schiller # @@ -30,7 +30,6 @@ # * Specify a limit to the precision of all positional elements. # * Clean up Definitions # * Collapse duplicate gradient definitions -# * Remove gradients that are only referenced by one other gradient # * Clean up CSS # * Convert RGB colours from RGB(r,g,b) to #RRGGBB format # * Convert RGB colours from #RRGGBB to #RGB if possible @@ -50,6 +49,9 @@ # Next Up: # + fix bug when removing stroke styles # + Remove gradients that are only referenced by one other gradient +# + added option to prevent group collapsing +# + prevent groups with title/desc children from being collapsed +# + remove stroke=none attribute # - Remove unnecessary units of precision on attributes # - Remove unnecessary units of precision on path coordinates # - Convert all colors to #RRGGBB format @@ -295,8 +297,8 @@ def removeNamespacedElements(node, namespaces): return num # this walks further and further down the tree, removing groups -# which do not have any attributes and promoting their children -# up one level +# which do not have any attributes or a title/desc child and +# promoting their children up one level def removeNestedGroups(node): global numElemsRemoved num = 0 @@ -304,7 +306,13 @@ def removeNestedGroups(node): groupsToRemove = [] for child in node.childNodes: if child.nodeName == 'g' and child.namespaceURI == NS['SVG'] and len(child.attributes) == 0: - groupsToRemove.append(child) + # only collapse group if it does not have a title or desc as a direct descendant + for grandchild in child.childNodes: + if grandchild.nodeType == 1 and grandchild.namespaceURI == NS['SVG'] and \ + grandchild.nodeName in ['title','desc']: + break + else: + groupsToRemove.append(child) for g in groupsToRemove: while g.childNodes.length > 0: @@ -530,6 +538,7 @@ def repairStyle(node): if styleMap.has_key(strokestyle) : del styleMap[strokestyle] num += 1 + del styleMap['stroke'] # if fill:none, then remove all fill-related properties (fill-rule, etc) # TODO: should also detect if fill-opacity=0 @@ -757,8 +766,9 @@ def scourString(in_string, options=[]): referencedIDs = findReferencedElements(doc.documentElement, {}) bContinueLooping = (removeUnreferencedIDs(referencedIDs, identifiedElements) > 0) - while removeNestedGroups(doc.documentElement) > 0: - pass + if not '--disable-group-collapsing' in options: + while removeNestedGroups(doc.documentElement) > 0: + pass while removeDuplicateGradientStops(doc) > 0: pass @@ -812,7 +822,8 @@ def printSyntaxAndQuit(): print 'If the output file is not specified, stdout is used.\n' print 'If an option is not available below that means it occurs automatically' print 'when scour is invoked. Available OPTIONS:\n' - print ' --enable-id-stripping : Scour will remove all un-referenced ID attributes' + print ' --enable-id-stripping : Scour will remove all un-referenced ID attributes' + print ' --disable-group-collapsing : Scour will not collapse elements' print '' quit() @@ -826,6 +837,7 @@ def parseCLA(): output = sys.stdout options = [] validOptions = [ + '--disable-group-collapsing', '--enable-id-stripping', ] diff --git a/testscour.py b/testscour.py index 040687e..0d3e1ed 100755 --- a/testscour.py +++ b/testscour.py @@ -163,6 +163,24 @@ class RemoveUselessNestedGroups(unittest.TestCase): self.assertEquals(len(doc.getElementsByTagNameNS(SVGNS, 'g')), 1, 'Useless nested groups not removed' ) +class DoNotRemoveUselessNestedGroups(unittest.TestCase): + def runTest(self): + doc = scour.scourXmlFile('unittests/nested-useless-groups.svg', ['--disable-group-collapsing']) + self.assertEquals(len(doc.getElementsByTagNameNS(SVGNS, 'g')), 2, + 'Useless nested groups were removed despite --disable-group-collapsing' ) + +class DoNotRemoveNestedGroupsWithTitle(unittest.TestCase): + def runTest(self): + doc = scour.scourXmlFile('unittests/groups-with-title-desc.svg') + self.assertEquals(len(doc.getElementsByTagNameNS(SVGNS, 'g')), 2, + 'Nested groups with title was removed' ) + +class DoNotRemoveNestedGroupsWithDesc(unittest.TestCase): + def runTest(self): + doc = scour.scourXmlFile('unittests/groups-with-title-desc.svg') + self.assertEquals(len(doc.getElementsByTagNameNS(SVGNS, 'g')), 2, + 'Nested groups with desc was removed' ) + class RemoveDuplicateLinearGradientStops(unittest.TestCase): def runTest(self): doc = scour.scourXmlFile('unittests/duplicate-gradient-stops.svg') @@ -303,8 +321,14 @@ class RemoveStrokeDashoffsetWhenStrokeWidthZero(unittest.TestCase): doc = scour.scourXmlFile('unittests/stroke-nowidth.svg') self.assertEquals(doc.getElementsByTagNameNS(SVGNS, 'path')[0].getAttribute('stroke-dashoffset'), '', 'stroke-dashoffset attribute not emptied when width zero' ) - + class RemoveStrokeWhenStrokeNone(unittest.TestCase): + def runTest(self): + doc = scour.scourXmlFile('unittests/stroke-none.svg') + self.assertEquals(doc.getElementsByTagNameNS(SVGNS, 'path')[0].getAttribute('stroke'), '', + 'stroke attribute not emptied when no stroke' ) + +class RemoveStrokeWidthWhenStrokeNone(unittest.TestCase): def runTest(self): doc = scour.scourXmlFile('unittests/stroke-none.svg') self.assertEquals(doc.getElementsByTagNameNS(SVGNS, 'path')[0].getAttribute('stroke-width'), '', diff --git a/unittests/groups-with-title-desc.svg b/unittests/groups-with-title-desc.svg new file mode 100644 index 0000000..4f56126 --- /dev/null +++ b/unittests/groups-with-title-desc.svg @@ -0,0 +1,12 @@ + + + Group 1 + + + + + Group 1 + + + + \ No newline at end of file