Merge from lp:~ecmanaut/scour/transform. Optimise negative 3-digit rotation angles to the positive form, and angles over positive 270 to the negative form. Also cath more angles outside of the range [-360, 360].
This commit is contained in:
commit
cd42752cad
5 changed files with 52 additions and 14 deletions
38
scour.py
38
scour.py
|
|
@ -1482,11 +1482,11 @@ def mayContainTextNodes(node):
|
||||||
result = True
|
result = True
|
||||||
# Blacklisted elements. Those are guaranteed not to be text elements.
|
# Blacklisted elements. Those are guaranteed not to be text elements.
|
||||||
elif node.nodeName in ['rect', 'circle', 'ellipse', 'line', 'polygon',
|
elif node.nodeName in ['rect', 'circle', 'ellipse', 'line', 'polygon',
|
||||||
'polyline', 'path', 'image', 'stop']:
|
'polyline', 'path', 'image', 'stop']:
|
||||||
result = False
|
result = False
|
||||||
# Group elements. If we're missing any here, the default of True is used.
|
# Group elements. If we're missing any here, the default of True is used.
|
||||||
elif node.nodeName in ['g', 'clipPath', 'marker', 'mask', 'pattern',
|
elif node.nodeName in ['g', 'clipPath', 'marker', 'mask', 'pattern',
|
||||||
'linearGradient', 'radialGradient', 'symbol']:
|
'linearGradient', 'radialGradient', 'symbol']:
|
||||||
result = False
|
result = False
|
||||||
for child in node.childNodes:
|
for child in node.childNodes:
|
||||||
if mayContainTextNodes(child):
|
if mayContainTextNodes(child):
|
||||||
|
|
@ -2110,7 +2110,7 @@ def parseListOfPoints(s):
|
||||||
nums = []
|
nums = []
|
||||||
|
|
||||||
# also, if 100-100 is found, split it into two also
|
# also, if 100-100 is found, split it into two also
|
||||||
# <polygon points="100,-100,100-100,100-100-100,-100-100" />
|
# <polygon points="100,-100,100-100,100-100-100,-100-100" />
|
||||||
for i in xrange(len(ws_nums)):
|
for i in xrange(len(ws_nums)):
|
||||||
negcoords = ws_nums[i].split("-")
|
negcoords = ws_nums[i].split("-")
|
||||||
|
|
||||||
|
|
@ -2328,6 +2328,28 @@ def reducePrecision(element) :
|
||||||
|
|
||||||
return num
|
return num
|
||||||
|
|
||||||
|
def optimizeAngle(angle):
|
||||||
|
"""
|
||||||
|
Because any rotation can be expressed within 360 degrees
|
||||||
|
of any given number, and since negative angles sometimes
|
||||||
|
are one character longer than corresponding positive angle,
|
||||||
|
we shorten the number to one in the range to [-90, 270[.
|
||||||
|
"""
|
||||||
|
# First, we put the new angle in the range ]-360, 360[.
|
||||||
|
# The modulo operator yields results with the sign of the
|
||||||
|
# divisor, so for negative dividends, we preserve the sign
|
||||||
|
# of the angle.
|
||||||
|
if angle < 0: angle %= -360
|
||||||
|
else: angle %= 360
|
||||||
|
# 720 degrees is unneccessary, as 360 covers all angles.
|
||||||
|
# As "-x" is shorter than "35x" and "-xxx" one character
|
||||||
|
# longer than positive angles <= 260, we constrain angle
|
||||||
|
# range to [-90, 270[ (or, equally valid: ]-100, 260]).
|
||||||
|
if angle >= 270: angle -= 360
|
||||||
|
elif angle < -90: angle += 360
|
||||||
|
return angle
|
||||||
|
|
||||||
|
|
||||||
def optimizeTransform(transform):
|
def optimizeTransform(transform):
|
||||||
"""
|
"""
|
||||||
Optimises a series of transformations parsed from a single
|
Optimises a series of transformations parsed from a single
|
||||||
|
|
@ -2401,6 +2423,7 @@ def optimizeTransform(transform):
|
||||||
if len(args) == 2 and args[1] == 0:
|
if len(args) == 2 and args[1] == 0:
|
||||||
del args[1]
|
del args[1]
|
||||||
elif type == 'rotate':
|
elif type == 'rotate':
|
||||||
|
args[0] = optimizeAngle(args[0]) # angle
|
||||||
# Only the angle is required for rotations.
|
# Only the angle is required for rotations.
|
||||||
# If the coordinates are unspecified, it's the origin (0, 0).
|
# If the coordinates are unspecified, it's the origin (0, 0).
|
||||||
if len(args) == 3 and args[1] == args[2] == 0:
|
if len(args) == 3 and args[1] == args[2] == 0:
|
||||||
|
|
@ -2447,14 +2470,7 @@ def optimizeTransform(transform):
|
||||||
elif (currType == prevType == 'rotate'
|
elif (currType == prevType == 'rotate'
|
||||||
and len(prevArgs) == len(currArgs) == 1):
|
and len(prevArgs) == len(currArgs) == 1):
|
||||||
# Only coalesce if both rotations are from the origin.
|
# Only coalesce if both rotations are from the origin.
|
||||||
prevArgs[0] += currArgs[0] # angle
|
prevArgs[0] = optimizeAngle(prevArgs[0] + currArgs[0])
|
||||||
# Put the new angle in the range ]-360, 360[.
|
|
||||||
# The modulo operator yields results with the sign of the
|
|
||||||
# divisor, so for negative dividends, we preserve the sign
|
|
||||||
# of the angle.
|
|
||||||
if prevArgs[0] < 0: prevArgs[0] = prevArgs[0] % -360
|
|
||||||
else: prevArgs[0] = prevArgs[0] % 360
|
|
||||||
|
|
||||||
del transform[i]
|
del transform[i]
|
||||||
elif currType == prevType == 'scale':
|
elif currType == prevType == 'scale':
|
||||||
prevArgs[0] *= currArgs[0] # x
|
prevArgs[0] *= currArgs[0] # x
|
||||||
|
|
|
||||||
18
testscour.py
18
testscour.py
|
|
@ -1243,9 +1243,9 @@ class TransformRotate90(unittest.TestCase):
|
||||||
|
|
||||||
class TransformRotateCCW135(unittest.TestCase):
|
class TransformRotateCCW135(unittest.TestCase):
|
||||||
def runTest(self):
|
def runTest(self):
|
||||||
doc = scour.scourXmlFile('unittests/transform-matrix-is-rotate-neg-135.svg')
|
doc = scour.scourXmlFile('unittests/transform-matrix-is-rotate-225.svg')
|
||||||
self.assertEquals(doc.getElementsByTagName('line')[0].getAttribute('transform'), 'rotate(-135)',
|
self.assertEquals(doc.getElementsByTagName('line')[0].getAttribute('transform'), 'rotate(225)',
|
||||||
'Counter-clockwise rotation matrix not converted to rotate(-135)')
|
'Counter-clockwise rotation matrix not converted to rotate(225)')
|
||||||
|
|
||||||
class TransformRotateCCW45(unittest.TestCase):
|
class TransformRotateCCW45(unittest.TestCase):
|
||||||
def runTest(self):
|
def runTest(self):
|
||||||
|
|
@ -1277,6 +1277,18 @@ class TransformTranslate(unittest.TestCase):
|
||||||
self.assertEquals(doc.getElementsByTagName('line')[0].getAttribute('transform'), 'translate(2 3)',
|
self.assertEquals(doc.getElementsByTagName('line')[0].getAttribute('transform'), 'translate(2 3)',
|
||||||
'Translation matrix not converted to translate(2 3)')
|
'Translation matrix not converted to translate(2 3)')
|
||||||
|
|
||||||
|
class TransformRotationRange719_5(unittest.TestCase):
|
||||||
|
def runTest(self):
|
||||||
|
doc = scour.scourXmlFile('unittests/transform-rotate-trim-range-719.5.svg')
|
||||||
|
self.assertEquals(doc.getElementsByTagName('line')[0].getAttribute('transform'), 'rotate(-.5)',
|
||||||
|
'Transform containing rotate(719.5) not shortened to rotate(-.5)')
|
||||||
|
|
||||||
|
class TransformRotationRangeCCW540_0(unittest.TestCase):
|
||||||
|
def runTest(self):
|
||||||
|
doc = scour.scourXmlFile('unittests/transform-rotate-trim-range-neg-540.0.svg')
|
||||||
|
self.assertEquals(doc.getElementsByTagName('line')[0].getAttribute('transform'), 'rotate(180)',
|
||||||
|
'Transform containing rotate(-540.0) not shortened to rotate(180)')
|
||||||
|
|
||||||
class TransformRotation3Args(unittest.TestCase):
|
class TransformRotation3Args(unittest.TestCase):
|
||||||
def runTest(self):
|
def runTest(self):
|
||||||
doc = scour.scourXmlFile('unittests/transform-rotate-fold-3args.svg')
|
doc = scour.scourXmlFile('unittests/transform-rotate-fold-3args.svg')
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 293 B After Width: | Height: | Size: 293 B |
5
unittests/transform-rotate-trim-range-719.5.svg
Normal file
5
unittests/transform-rotate-trim-range-719.5.svg
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-9 0 9 9">
|
||||||
|
<line stroke="rgba(255,0,0,0.5)" y1="9" x1="9" transform="rotate(719.5)"/>
|
||||||
|
<!-- all rotation angles can be mapped to the shorter range [-90, 270[ -->
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 289 B |
5
unittests/transform-rotate-trim-range-neg-540.0.svg
Normal file
5
unittests/transform-rotate-trim-range-neg-540.0.svg
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-9 0 9 9">
|
||||||
|
<line stroke="rgba(255,0,0,0.5)" y1="9" x1="9" transform="rotate(-540.0) rotate(0)"/>
|
||||||
|
<!-- all rotation angles can be mapped to the shorter range [-90, 270[ -->
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 300 B |
Loading…
Add table
Add a link
Reference in a new issue