Fix Bug 541889: Properly parse polygon/polyline points missing whitespace/comma for negative attributes

This commit is contained in:
JSCHILL1 2010-03-25 17:48:15 -07:00
parent fd82967bbc
commit 05e73f11c3
8 changed files with 72 additions and 13 deletions

View file

@ -1786,12 +1786,43 @@ def parseListOfPoints(s):
Returns a list of containing an even number of coordinate strings Returns a list of containing an even number of coordinate strings
""" """
i = 0
points = []
# (wsp)? comma-or-wsp-separated coordinate pairs (wsp)? # (wsp)? comma-or-wsp-separated coordinate pairs (wsp)?
# coordinate-pair = coordinate comma-or-wsp coordinate # coordinate-pair = coordinate comma-or-wsp coordinate
# coordinate = sign? integer # coordinate = sign? integer
nums = re.split("\\s*\\,?\\s*", s.strip()) # comma-wsp: (wsp+ comma? wsp*) | (comma wsp*)
ws_nums = re.split("\\s*\\,?\\s*", s.strip())
nums = []
# also, if 100-100 is found, split it into two also
# <polygon points="100,-100,100-100,100-100-100,-100-100" />
for i in range(len(ws_nums)):
negcoords = re.split("\\-", ws_nums[i]);
# this string didn't have any negative coordinates
if len(negcoords) == 1:
nums.append(negcoords[0])
# we got negative coords
else:
for j in range(len(negcoords)):
# first number could be positive
if j == 0:
if negcoords[0] != '':
nums.append(negcoords[0])
# otherwise all other strings will be negative
else:
# unless we accidentally split a number that was in scientific notation
# and had a negative exponent (500.00e-1)
prev = nums[len(nums)-1]
if prev[len(prev)-1] == 'e' or prev[len(prev)-1] == 'E':
nums[len(nums)-1] = prev + '-' + negcoords[j]
else:
nums.append( '-'+negcoords[j] )
# now resolve into SVGLength values
i = 0 i = 0
points = []
while i < len(nums): while i < len(nums):
x = SVGLength(nums[i]) x = SVGLength(nums[i])
# if we had an odd number of points, return empty # if we had an odd number of points, return empty
@ -1820,14 +1851,14 @@ def cleanPolygon(elem):
if startx == endx and starty == endy: if startx == endx and starty == endy:
pts = pts[:-2] pts = pts[:-2]
numPointsRemovedFromPolygon += 1 numPointsRemovedFromPolygon += 1
elem.setAttribute('points', scourCoordinates(pts)) elem.setAttribute('points', scourCoordinates(pts,True))
def cleanPolyline(elem): def cleanPolyline(elem):
""" """
Scour the polyline points attribute Scour the polyline points attribute
""" """
pts = parseListOfPoints(elem.getAttribute('points')) pts = parseListOfPoints(elem.getAttribute('points'))
elem.setAttribute('points', scourCoordinates(pts)) elem.setAttribute('points', scourCoordinates(pts,True))
def serializePath(pathObj): def serializePath(pathObj):
""" """

View file

@ -38,7 +38,6 @@ class ElementSelector(unittest.TestCase):
class ElementSelectorWithProperty(unittest.TestCase): class ElementSelectorWithProperty(unittest.TestCase):
def runTest(self): def runTest(self):
r = parseCssString('foo { bar: baz}') r = parseCssString('foo { bar: baz}')
print r
self.assertEquals( len(r), 1, 'Element selector not returned') self.assertEquals( len(r), 1, 'Element selector not returned')
self.assertEquals( r[0]['selector'], 'foo', 'Selector for foo not returned') self.assertEquals( r[0]['selector'], 'foo', 'Selector for foo not returned')
self.assertEquals( len(r[0]['properties']), 1, 'Property list for foo did not have 1') self.assertEquals( len(r[0]['properties']), 1, 'Property list for foo did not have 1')

View file

@ -654,7 +654,7 @@ class ConvertStraightCurvesToLines(unittest.TestCase):
self.assertEquals(p.getAttribute('d'), 'M10,10l40,40,40-40z', self.assertEquals(p.getAttribute('d'), 'M10,10l40,40,40-40z',
'Did not convert straight curves into lines') 'Did not convert straight curves into lines')
class RemoveUnnecessaryPolgonEndPoint(unittest.TestCase): class RemoveUnnecessaryPolygonEndPoint(unittest.TestCase):
def runTest(self): def runTest(self):
p = scour.scourXmlFile('unittests/polygon.svg').getElementsByTagNameNS(SVGNS, 'polygon')[0] p = scour.scourXmlFile('unittests/polygon.svg').getElementsByTagNameNS(SVGNS, 'polygon')[0]
self.assertEquals(p.getAttribute('points'), '50,50,150,50,150,150,50,150', self.assertEquals(p.getAttribute('points'), '50,50,150,50,150,150,50,150',
@ -666,18 +666,31 @@ class DoNotRemovePolgonLastPoint(unittest.TestCase):
self.assertEquals(p.getAttribute('points'), '200,50,300,50,300,150,200,150', self.assertEquals(p.getAttribute('points'), '200,50,300,50,300,150,200,150',
'Last point of polygon removed' ) 'Last point of polygon removed' )
class ScourPolygonCoordinates(unittest.TestCase): class ScourPolygonCoordsSciNo(unittest.TestCase):
def runTest(self): def runTest(self):
p = scour.scourXmlFile('unittests/polygon-coord.svg').getElementsByTagNameNS(SVGNS, 'polygon')[0] p = scour.scourXmlFile('unittests/polygon-coord.svg').getElementsByTagNameNS(SVGNS, 'polygon')[0]
self.assertEquals(p.getAttribute('points'), '1E+4-50', self.assertEquals(p.getAttribute('points'), '1E+4,50',
'Polygon coordinates not scoured') 'Polygon coordinates not scoured')
class ScourPolylineCoordinates(unittest.TestCase): class ScourPolylineCoordsSciNo(unittest.TestCase):
def runTest(self): def runTest(self):
p = scour.scourXmlFile('unittests/polyline-coord.svg').getElementsByTagNameNS(SVGNS, 'polyline')[0] p = scour.scourXmlFile('unittests/polyline-coord.svg').getElementsByTagNameNS(SVGNS, 'polyline')[0]
self.assertEquals(p.getAttribute('points'), '1E+4-50', self.assertEquals(p.getAttribute('points'), '1E+4,50',
'Polyline coordinates not scoured') 'Polyline coordinates not scoured')
class ScourPolygonNegativeCoords(unittest.TestCase):
def runTest(self):
p = scour.scourXmlFile('unittests/polygon-coord-neg.svg').getElementsByTagNameNS(SVGNS, 'polygon')[0]
# points="100,-100,100-100,100-100-100,-100-100,200" />
self.assertEquals(p.getAttribute('points'), '100,-100,100,-100,100,-100,-100,-100,-100,200',
'Negative polygon coordinates not properly parsed')
class ScourPolylineNegativeCoords(unittest.TestCase):
def runTest(self):
p = scour.scourXmlFile('unittests/polyline-coord-neg.svg').getElementsByTagNameNS(SVGNS, 'polyline')[0]
self.assertEquals(p.getAttribute('points'), '100,-100,100,-100,100,-100,-100,-100,-100,200',
'Negative polyline coordinates not properly parsed')
class DoNotRemoveGroupsWithIDsInDefs(unittest.TestCase): class DoNotRemoveGroupsWithIDsInDefs(unittest.TestCase):
def runTest(self): def runTest(self):
f = scour.scourXmlFile('unittests/important-groups-in-defs.svg') f = scour.scourXmlFile('unittests/important-groups-in-defs.svg')

View file

@ -0,0 +1,4 @@
<?xml version='1.0' encoding='utf-8'?>
<svg xmlns="http://www.w3.org/2000/svg">
<polygon points="100,-100,100-100,100-100-100,-100-100,200" />
</svg>

After

Width:  |  Height:  |  Size: 155 B

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg"> <svg xmlns="http://www.w3.org/2000/svg">
<polygon fill="blue" points="10000,-50" /> <polygon fill="blue" points="10000,50" />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 146 B

After

Width:  |  Height:  |  Size: 145 B

Before After
Before After

View file

@ -0,0 +1,4 @@
<?xml version='1.0' encoding='utf-8'?>
<svg xmlns="http://www.w3.org/2000/svg">
<polyline points="100,-100,100-100,100-100-100,-100-100,200" />
</svg>

After

Width:  |  Height:  |  Size: 156 B

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg"> <svg xmlns="http://www.w3.org/2000/svg">
<polyline fill="blue" points="10000,-50" /> <polyline fill="blue" points="10000,50" />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 147 B

After

Width:  |  Height:  |  Size: 146 B

Before After
Before After

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<path id="L" stroke="#000000" d="M0,0 100,100"/>
<g id="G"><use xlink:href="#L"/> <path stroke="#000000" d="M0,100 100,0"/></g>
</defs>
<use xlink:href="#G"/>
</svg>

After

Width:  |  Height:  |  Size: 345 B