From 9bec4cc4d0bda8fb02af6c7c5c5c32d60d6b1e01 Mon Sep 17 00:00:00 2001 From: JSCHILL1 Date: Sat, 1 Aug 2009 07:23:24 -0500 Subject: [PATCH] Only convert color names to #RRGGBB if it will actually be shorter --- release-notes.html | 10 +++++++ scour.py | 37 ++++++++++++++++------- testscour.py | 38 ++++++++++++++++++++++-- unittests/color-formats.svg | 2 +- unittests/remove-duplicate-gradients.svg | 18 +++++++++++ 5 files changed, 92 insertions(+), 13 deletions(-) create mode 100644 unittests/remove-duplicate-gradients.svg diff --git a/release-notes.html b/release-notes.html index c752b03..d5b4800 100644 --- a/release-notes.html +++ b/release-notes.html @@ -9,6 +9,16 @@

Copyright 2009, Jeff Schiller

+
+
+

Version 0.17

+
+

July 30th, 2009

+ +
+

Version 0.16

diff --git a/scour.py b/scour.py index f0ae43e..68c3b5e 100755 --- a/scour.py +++ b/scour.py @@ -38,6 +38,7 @@ # This would require my own serialization of the DOM objects (not impossible) # Next Up: +# - remove duplicate gradients # - scour polyline coordinates just like path coordinates # - if after reducing precision we have duplicate path segments, then remove the duplicates and # leave it as a straight line segment @@ -69,7 +70,7 @@ except ImportError: Decimal = FixedPoint APP = 'scour' -VER = '0.16' +VER = '0.17' COPYRIGHT = 'Copyright Jeff Schiller, 2009' NS = { 'SVG': 'http://www.w3.org/2000/svg', @@ -673,7 +674,7 @@ def collapseSinglyReferencedGradients(doc): for stop in stopsToAdd: refElem.appendChild(stop) - # adopt the gradientUnits, spreadMethod, gradientTransform attributess if + # adopt the gradientUnits, spreadMethod, gradientTransform attributes if # they are unspecified on refElem for attr in ['gradientUnits','spreadMethod','gradientTransform']: if refElem.getAttribute(attr) == '' and not elem.getAttribute(attr) == '': @@ -699,10 +700,19 @@ def collapseSinglyReferencedGradients(doc): # now delete elem elem.parentNode.removeChild(elem) numElemsRemoved += 1 - num += 1 - + num += 1 return num + +def removeDuplicateGradients(doc): + global numElemsRemoved + num = 0 + for gradType in ['linearGradient', 'radialGradient']: + for grad in doc.getElementsByTagNameNS(NS['SVG'], gradType): + pass + + return num + def repairStyle(node, options): num = 0 if node.nodeType == 1 and len(node.getAttribute('style')) > 0 : @@ -906,7 +916,7 @@ def convertColor(value): def convertColors(element) : """ - Recursively converts all color properties into #RRGGBB format + Recursively converts all color properties into #RRGGBB format if shorter """ numBytes = 0 @@ -924,11 +934,14 @@ def convertColors(element) : # now convert all the color formats for attr in attrsToConvert: - val = element.getAttribute(attr) - oldBytes = len(val) - if val != '': - element.setAttribute(attr, convertColor(val)) - numBytes += (oldBytes - len(element.getAttribute(attr))) + oldColorValue = element.getAttribute(attr) + if oldColorValue != '': + newColorValue = convertColor(oldColorValue) + oldBytes = len(oldColorValue) + newBytes = len(newColorValue) + if oldBytes > newBytes: + element.setAttribute(attr, newColorValue) + numBytes += (oldBytes - len(element.getAttribute(attr))) # now recurse for our child elements for child in element.childNodes : @@ -1604,6 +1617,10 @@ def scourString(in_string, options=None): # remove gradients that are only referenced by one other gradient while collapseSinglyReferencedGradients(doc) > 0: pass + + # remove duplicate gradients + while removeDuplicateGradients(doc) > 0: + pass # clean path data for elem in doc.documentElement.getElementsByTagNameNS(NS['SVG'], 'path') : diff --git a/testscour.py b/testscour.py index 72986e2..3dbeac0 100755 --- a/testscour.py +++ b/testscour.py @@ -583,7 +583,7 @@ class TranslateColorNamesIntoHex(unittest.TestCase): class TranslateExtendedColorNamesIntoHex(unittest.TestCase): def runTest(self): elem = scour.scourXmlFile('unittests/color-formats.svg').getElementsByTagNameNS(SVGNS, 'solidColor')[0] - self.assertEquals( elem.getAttribute('solid-color'), '#800000', + self.assertEquals( elem.getAttribute('solid-color'), '#FAFAD2', 'Not converting extended color names into hex') class TranslateLongHexColorIntoShortHex(unittest.TestCase): @@ -591,7 +591,13 @@ class TranslateLongHexColorIntoShortHex(unittest.TestCase): elem = scour.scourXmlFile('unittests/color-formats.svg').getElementsByTagNameNS(SVGNS, 'ellipse')[0] self.assertEquals( elem.getAttribute('fill'), '#FFF', 'Not converting long hex color into short hex') - + +class DoNotConvertShortColorNames(unittest.TestCase): + def runTest(self): + elem = scour.scourXmlFile('unittests/dont-convert-short-color-names.svg').getElementsByTagNameNS(SVGNS, 'rect')[0] + self.assertEquals( 'red', elem.getAttribute('fill'), + 'Converted short color name to longer hex string') + class AllowQuotEntitiesInUrl(unittest.TestCase): def runTest(self): grads = scour.scourXmlFile('unittests/quot-in-url.svg').getElementsByTagNameNS(SVGNS, 'linearGradient') @@ -658,6 +664,34 @@ class AlwaysKeepClosePathSegments(unittest.TestCase): self.assertEquals(p.getAttribute('d'), 'M10,10h100v100h-100z', 'Path with closepath not preserved') +class RemoveDuplicateLinearGradients(unittest.TestCase): + def runTest(self): + svgdoc = scour.scourXmlFile('unittests/remove-duplicate-gradients.svg') + lingrads = svgdoc.getElementsByTagNameNS(SVGNS, 'linearGradient') + self.assertEquals(1, lingrads.length, + 'Duplicate linear gradient not removed') + +class RereferenceForLinearGradient(unittest.TestCase): + def runTest(self): + svgdoc = scour.scourXmlFile('unittests/remove-duplicate-gradients.svg') + rects = svgdoc.getElementsByTagNameNS(SVGNS, 'rect') + self.assertEquals(rects[0].getAttribute('fill'), rects[1].getAttribute('stroke'), + 'Rect not changed after removing duplicate linear gradient') + +class RemoveDuplicateRadialGradients(unittest.TestCase): + def runTest(self): + svgdoc = scour.scourXmlFile('unittests/remove-duplicate-gradients.svg') + radgrads = svgdoc.getElementsByTagNameNS(SVGNS, 'radialGradient') + self.assertEquals(1, radgrads.length, + 'Duplicate radial gradient not removed') + +class RereferenceForRadialGradient(unittest.TestCase): + def runTest(self): + svgdoc = scour.scourXmlFile('unittests/remove-duplicate-gradients.svg') + rects = svgdoc.getElementsByTagNameNS(SVGNS, 'rect') + self.assertEquals(rects[2].getAttribute('stroke'), rects[3].getAttribute('fill'), + 'Rect not changed after removing duplicate radial gradient') + # TODO; write a test for embedding rasters # TODO: write a test for --disable-embed-rasters # TODO: write tests for --keep-editor-data diff --git a/unittests/color-formats.svg b/unittests/color-formats.svg index a128bd2..d059a68 100644 --- a/unittests/color-formats.svg +++ b/unittests/color-formats.svg @@ -3,7 +3,7 @@ - + diff --git a/unittests/remove-duplicate-gradients.svg b/unittests/remove-duplicate-gradients.svg new file mode 100644 index 0000000..c529d59 --- /dev/null +++ b/unittests/remove-duplicate-gradients.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file