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.

  1. 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:
  2. 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.
  3. 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.
  4. 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.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.