Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def properlySizeDoc(docElement, options):
# get doc width and height
w = SVGLength(docElement.getAttribute('width'))
h = SVGLength(docElement.getAttribute('height'))
if not options.override_size:
# if width/height are not unitless or px then it is not ok to rewrite them into a viewBox.
# well, it may be OK for Web browsers and vector editors, but not for librsvg.
if options.renderer_workaround:
if ((w.units != Unit.NONE and w.units != Unit.PX) or
(h.units != Unit.NONE and h.units != Unit.PX)):
return
# else we have a statically sized image and we should try to remedy that
# parse viewBox attribute
vbSep = re.split("\\s*\\,?\\s*", docElement.getAttribute('viewBox'), 3)
# if we have a valid viewBox we need to check it
vbWidth,vbHeight = 0,0
if len(vbSep) == 4:
def properlySizeDoc(docElement, options):
# get doc width and height
w = SVGLength(docElement.getAttribute('width'))
h = SVGLength(docElement.getAttribute('height'))
if not options.override_size:
# if width/height are not unitless or px then it is not ok to rewrite them into a viewBox.
# well, it may be OK for Web browsers and vector editors, but not for librsvg.
if options.renderer_workaround:
if ((w.units != Unit.NONE and w.units != Unit.PX) or
(h.units != Unit.NONE and h.units != Unit.PX)):
return
# else we have a statically sized image and we should try to remedy that
# parse viewBox attribute
vbSep = re.split("\\s*\\,?\\s*", docElement.getAttribute('viewBox'), 3)
# if we have a valid viewBox we need to check it
vbWidth,vbHeight = 0,0
def removeDuplicateGradientStops(doc):
global numElemsRemoved
num = 0
for gradType in ['linearGradient', 'radialGradient']:
for grad in doc.getElementsByTagName(gradType):
stops = {}
stopsToRemove = []
for stop in grad.getElementsByTagName('stop'):
# convert percentages into a floating point number
offsetU = SVGLength(stop.getAttribute('offset'))
if offsetU.units == Unit.PCT:
offset = offsetU.value / 100.0
elif offsetU.units == Unit.NONE:
offset = offsetU.value
else:
offset = 0
# set the stop offset value to the integer or floating point equivalent
if int(offset) == offset: stop.setAttribute('offset', str(int(offset)))
else: stop.setAttribute('offset', str(offset))
color = stop.getAttribute('stop-color')
opacity = stop.getAttribute('stop-opacity')
style = stop.getAttribute('style')
if stops.has_key(offset) :
oldStop = stops[offset]
if oldStop[0] == color and oldStop[1] == opacity and oldStop[2] == style:
'stroke-opacity', 'stop-opacity', 'stroke-miterlimit',
'stroke-dashoffset', 'letter-spacing', 'word-spacing',
'kerning', 'font-size-adjust', 'font-size',
'stroke-width']:
val = element.getAttribute(lengthAttr)
if val != '':
valLen = SVGLength(val)
if valLen.units != Unit.INVALID: # not an absolute/relative size or inherit, can be % though
newVal = scourLength(val)
if len(newVal) < len(val):
num += len(val) - len(newVal)
element.setAttribute(lengthAttr, newVal)
# repeat for attributes hidden in styles
if lengthAttr in styles.keys():
val = styles[lengthAttr]
valLen = SVGLength(val)
if valLen.units != Unit.INVALID:
newVal = scourLength(val)
if len(newVal) < len(val):
num += len(val) - len(newVal)
styles[lengthAttr] = newVal
_setStyle(element, styles)
for child in element.childNodes:
if child.nodeType == 1:
num += reducePrecision(child)
return num
del styleMap[uselessFillStyle]
num += 1
# stroke-opacity: 0
if styleMap.has_key('stroke-opacity') :
strokeOpacity = float(styleMap['stroke-opacity'])
if strokeOpacity == 0.0 :
for uselessStrokeStyle in [ 'stroke', 'stroke-width', 'stroke-linejoin', 'stroke-linecap',
'stroke-dasharray', 'stroke-dashoffset' ] :
if styleMap.has_key(uselessStrokeStyle):
del styleMap[uselessStrokeStyle]
num += 1
# stroke-width: 0
if styleMap.has_key('stroke-width') :
strokeWidth = SVGLength(styleMap['stroke-width'])
if strokeWidth.value == 0.0 :
for uselessStrokeStyle in [ 'stroke', 'stroke-linejoin', 'stroke-linecap',
'stroke-dasharray', 'stroke-dashoffset', 'stroke-opacity' ] :
if styleMap.has_key(uselessStrokeStyle):
del styleMap[uselessStrokeStyle]
num += 1
# remove font properties for non-text elements
# I've actually observed this in real SVG content
if not mayContainTextNodes(node):
for fontstyle in [ 'font-family', 'font-size', 'font-stretch', 'font-size-adjust',
'font-style', 'font-variant', 'font-weight',
'letter-spacing', 'line-height', 'kerning',
'text-align', 'text-anchor', 'text-decoration',
'text-rendering', 'unicode-bidi',
'word-spacing', 'writing-mode'] :
Also checks for the attributes actually being lengths, not 'inherit', 'none'
or anything that isn't an SVGLength.
Returns the number of bytes saved after performing these reductions.
"""
num = 0
styles = _getStyle(element)
for lengthAttr in ['opacity', 'flood-opacity', 'fill-opacity',
'stroke-opacity', 'stop-opacity', 'stroke-miterlimit',
'stroke-dashoffset', 'letter-spacing', 'word-spacing',
'kerning', 'font-size-adjust', 'font-size',
'stroke-width']:
val = element.getAttribute(lengthAttr)
if val != '':
valLen = SVGLength(val)
if valLen.units != Unit.INVALID: # not an absolute/relative size or inherit, can be % though
newVal = scourLength(val)
if len(newVal) < len(val):
num += len(val) - len(newVal)
element.setAttribute(lengthAttr, newVal)
# repeat for attributes hidden in styles
if lengthAttr in styles.keys():
val = styles[lengthAttr]
valLen = SVGLength(val)
if valLen.units != Unit.INVALID:
newVal = scourLength(val)
if len(newVal) < len(val):
num += len(val) - len(newVal)
styles[lengthAttr] = newVal
_setStyle(element, styles)
num = 0
if node.nodeType != 1: return 0
# gradientUnits: objectBoundingBox
if node.getAttribute('gradientUnits') == 'objectBoundingBox':
node.removeAttribute('gradientUnits')
num += 1
# spreadMethod: pad
if node.getAttribute('spreadMethod') == 'pad':
node.removeAttribute('spreadMethod')
num += 1
# x1: 0%
if node.getAttribute('x1') != '':
x1 = SVGLength(node.getAttribute('x1'))
if x1.value == 0:
node.removeAttribute('x1')
num += 1
# y1: 0%
if node.getAttribute('y1') != '':
y1 = SVGLength(node.getAttribute('y1'))
if y1.value == 0:
node.removeAttribute('y1')
num += 1
# x2: 100%
if node.getAttribute('x2') != '':
x2 = SVGLength(node.getAttribute('x2'))
if (x2.value == 100 and x2.units == Unit.PCT) or (x2.value == 1 and x2.units == Unit.NONE):
node.removeAttribute('x2')
if node.getAttribute('cx') != '':
cx = SVGLength(node.getAttribute('cx'))
if (cx.value == 50 and cx.units == Unit.PCT) or (cx.value == 0.5 and cx.units == Unit.NONE):
node.removeAttribute('cx')
num += 1
# cy: 50%
if node.getAttribute('cy') != '':
cy = SVGLength(node.getAttribute('cy'))
if (cy.value == 50 and cy.units == Unit.PCT) or (cy.value == 0.5 and cy.units == Unit.NONE):
node.removeAttribute('cy')
num += 1
# r: 50%
if node.getAttribute('r') != '':
r = SVGLength(node.getAttribute('r'))
if (r.value == 50 and r.units == Unit.PCT) or (r.value == 0.5 and r.units == Unit.NONE):
node.removeAttribute('r')
num += 1
# Summarily get rid of some more attributes
attributes = [node.attributes.item(i).nodeName
for i in range(node.attributes.length)]
for attribute in attributes:
if attribute not in tainted:
if attribute in default_attributes.keys():
if node.getAttribute(attribute) == default_attributes[attribute]:
node.removeAttribute(attribute)
num += 1
else:
tainted = taint(tainted, attribute)
# These attributes might also occur as styles
if node.getAttribute('y1') != '':
y1 = SVGLength(node.getAttribute('y1'))
if y1.value == 0:
node.removeAttribute('y1')
num += 1
# x2: 100%
if node.getAttribute('x2') != '':
x2 = SVGLength(node.getAttribute('x2'))
if (x2.value == 100 and x2.units == Unit.PCT) or (x2.value == 1 and x2.units == Unit.NONE):
node.removeAttribute('x2')
num += 1
# y2: 0%
if node.getAttribute('y2') != '':
y2 = SVGLength(node.getAttribute('y2'))
if y2.value == 0:
node.removeAttribute('y2')
num += 1
# fx: equal to rx
if node.getAttribute('fx') != '':
if node.getAttribute('fx') == node.getAttribute('cx'):
node.removeAttribute('fx')
num += 1
# fy: equal to ry
if node.getAttribute('fy') != '':
if node.getAttribute('fy') == node.getAttribute('cy'):
node.removeAttribute('fy')
num += 1