User:Quibik/SvgGradientSimplify.py
# SVG Gradient Simplifier
#
# This script cleans up the linear gradients in an SVG file by applying the matrix transforms that may be present in the gradients.
# For example:
# <linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="-320.3149" y1="694.9482" x2="-319.3149" y2="694.9482" gradientTransform="matrix(-46.5269 252.9134 252.9134 46.5269 -190547.0313 48709.5078)">
# is changed into
# <linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="117.940" y1="31.363" x2="71.413" y2="284.276">
# The rest of the file is not modified in any way.
#
# Author: Quibik <http://commons.wikimedia.org/wiki/User:Quibik>
# Last modified: 2010-11-25
# Licensing: released into the public domain (attribution is still welcome, of course :)
from sys import argv
import re
def usage():
print("This script cleans up the linear gradients in an SVG file by applying the matrix transforms that may be present in the gradients.\n\n"
"Parameters:\n"
"\t"+argv[0].split('\\')[-1]+" <input file> [<output file>]\n"
"If no output file is specified, the input file will be overwritten.")
return
def simplify_gradient(p1, p2, matrix):
# apply an affine transformation to a point in 2D space
def transform(pos, matrix):
return [matrix[4] + matrix[0]*pos[0] + matrix[2]*pos[1], matrix[5] + matrix[1]*pos[0] + matrix[3]*pos[1]]
return [transform(p1, matrix), transform(p2, matrix)]
def main():
# get the input and output filenames from the command line
if len(argv) == 2:
input_file_name = output_file_name = argv[1]
elif len(argv) == 3:
input_file_name = argv[1]
output_file_name = argv[2]
else:
usage()
exit()
# read in the whole input file
data = ""
with open(input_file_name, 'r') as f:
data = f.read()
# an iterator of all linearGradient nodes
matchiter = re.finditer(r'<linearGradient[^<>]+>', data)
# output file content will be stored here
newdata = ""
# the end position of the previous match in the input file
lastend = 0
modifycount = 0
for m in matchiter:
# add data outside the linearGradient node to output
newdata += data[lastend:m.start()]
lastend = m.end()
node = m.group(0)
# read in data fraom the attributes inside the node
matrix = re.search('gradientTransform\s*=\s*["\']\s*matrix\(([^)]+)\)\s*["\']', node)
x1 = re.search('x1\s*=\s*["\']([^"\']+)["\']', node)
y1 = re.search('y1\s*=\s*["\']([^"\']+)["\']', node)
x2 = re.search('x2\s*=\s*["\']([^"\']+)["\']', node)
y2 = re.search('y2\s*=\s*["\']([^"\']+)["\']', node)
if not (matrix and x1 and y1 and x2 and y2):
newdata += node
continue
# convert strings to numbers
matrix = re.split('[,\s]+', matrix.group(1))
matrix = [float(x) for x in matrix]
x1 = float(x1.group(1).replace('px', ''))
y1 = float(y1.group(1).replace('px', ''))
x2 = float(x2.group(1).replace('px', ''))
y2 = float(y2.group(1).replace('px', ''))
# the important part: applying the transformation matrix to the coordinates
newp1, newp2 = simplify_gradient([x1, y1], [x2, y2], matrix)
# update the attributes
node = re.sub('\s+gradientTransform\s*=\s*["\']\s*matrix\([^)]+\)\s*["\']', '', node)
node = re.sub('x1\s*=\s*["\'][^"\']+["\']', 'x1="' + "{0:0.3f}".format(newp1[0])+'"', node)
node = re.sub('y1\s*=\s*["\'][^"\']+["\']', 'y1="' + "{0:0.3f}".format(newp1[1])+'"', node)
node = re.sub('x2\s*=\s*["\'][^"\']+["\']', 'x2="' + "{0:0.3f}".format(newp2[0])+'"', node)
node = re.sub('y2\s*=\s*["\'][^"\']+["\']', 'y2="' + "{0:0.3f}".format(newp2[1])+'"', node)
# write the node to output
newdata += node
modifycount += 1
newdata += data[lastend:]
# write the new data to the output file
with open(output_file_name, 'w') as f:
f.write(str(newdata))
print("Done! Modified "+str(modifycount)+" gradient definitions.")
if __name__ == "__main__":
main()
Content Disclaimer
Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.
- The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
- There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
- It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
- Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
- Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.