connectsvg.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #!/usr/bin/python
  2. # -*- coding:utf-8 -*-
  3. ##
  4. # This file is part of connectSVG.
  5. #
  6. # connectSVG is free software: you can redistribute it and/or modify it
  7. # under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License,
  9. # or (at your option) any later version.
  10. #
  11. # connectSVG is distributed in the hope that it will be useful, but WITHOUT ANY
  12. # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  13. # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  14. # details.
  15. #
  16. # You should have received a copy of the GNU General Public License along
  17. # with connectSVG. If not, see <https://www.gnu.org/licenses/>.
  18. ##
  19. VERSION = [0,0]
  20. VERSION_STR = f"{VERSION[0]}.{VERSION[1]}"
  21. VERSION_REPR = f"connectSVG {VERSION_STR}"
  22. from svgpathtools import svg2paths, wsvg
  23. import sys
  24. import logging
  25. import argparse
  26. ##
  27. # Arguments parsing
  28. ##
  29. parser = argparse.ArgumentParser(
  30. prog="connectSVG",
  31. description="Connect and order the paths in a svg file and wite the new svg")
  32. parser.add_argument('infile',
  33. help="The svg to connect")
  34. parser.add_argument('outfile',
  35. nargs="?",
  36. default=None,
  37. help="""The name of the file to write in. If omited the program will
  38. write in the same file it reads""")
  39. parser.add_argument('-b', '--break-uncontinuous',
  40. action='store_true',
  41. help="Only break the uncontinuous paths")
  42. parser.add_argument('-t', '--tolerance',
  43. type=float,
  44. default=0.0000000000005,
  45. help="""Set the radius in which 2 points are taken as the same.
  46. This parameter is not considered if the connection is disabled.
  47. (default 0.0000000000005)""")
  48. connectGroup = parser.add_mutually_exclusive_group()
  49. connectGroup.add_argument('-c', '--connect',
  50. action='store_true',
  51. help="Only connect the paths")
  52. connectGroup.add_argument('--no-connect',
  53. action='store_true',
  54. help="Do everything except connecting paths")
  55. orderGroup = parser.add_mutually_exclusive_group()
  56. orderGroup.add_argument('-o', '--order',
  57. action='store_true',
  58. help="Only order the paths")
  59. orderGroup.add_argument('--no-order',
  60. action='store_true',
  61. help="Do everything except ordering the paths")
  62. parser.add_argument('-V', '--version',
  63. action='version',
  64. version=VERSION_REPR,
  65. help="Show program version")
  66. parser.add_argument('-v', '--verbose',
  67. action='store_const',
  68. const=logging.INFO,
  69. default=100,
  70. help="Print more log")
  71. parser.add_argument('-vv', '--vverbose',
  72. action='store_const',
  73. const=logging.DEBUG,
  74. default=100,
  75. help="Print the maximum of log")
  76. parser.add_argument('--verbose-file',
  77. action='store_const',
  78. const=logging.DEBUG,
  79. default=100,
  80. help="Print the maximum of log in the log file")
  81. args = parser.parse_args()
  82. ##
  83. # Setup logging
  84. ##
  85. FILE_MIN_LEVEL = min(logging.INFO, args.verbose_file)
  86. STDOUT_MIN_LEVEL = min(logging.ERROR, args.verbose, args.vverbose)
  87. logging.addLevelName(logging.NOTSET, '?')
  88. logging.addLevelName(logging.DEBUG, 'D')
  89. logging.addLevelName(logging.INFO, 'I')
  90. logging.addLevelName(logging.WARNING, 'W')
  91. logging.addLevelName(logging.ERROR, 'E')
  92. logging.addLevelName(logging.CRITICAL, 'C')
  93. log = logging.getLogger('connectsvg')
  94. log.setLevel(min(FILE_MIN_LEVEL, STDOUT_MIN_LEVEL))
  95. fh = logging.FileHandler('connectSVG.log')
  96. fh.setLevel(FILE_MIN_LEVEL)
  97. log.addHandler(fh)
  98. fhFormat = logging.Formatter('%(levelname)s/%(asctime)s (%(module)s) : %(message)s', '%Y-%m-%d %H:%M:%S,%03d')
  99. fh.setFormatter(fhFormat)
  100. sh = logging.StreamHandler(sys.stdout)
  101. sh.setLevel(STDOUT_MIN_LEVEL)
  102. log.addHandler(sh)
  103. shFormat = logging.Formatter('%(levelname)s - %(message)s')
  104. sh.setFormatter(shFormat)
  105. ##
  106. # Program
  107. ##
  108. log.info("Starting connectSVG")
  109. try :
  110. log.info("Reading file")
  111. paths, attributes = svg2paths(args.infile)
  112. log.info("Processing %s", args.infile)
  113. if not args.order :
  114. log.info("Breaking uncontinuous paths")
  115. from breakUncontinuous import breakUncontinuous
  116. paths, attributes = breakUncontinuous(paths, attributes)
  117. if not (args.no_connect or args.order or args.break_uncontinuous) :
  118. log.info("Connecting paths")
  119. import connectPaths
  120. connectPaths.TOLERANCE = args.tolerance
  121. paths, attributes = connectPaths.connectPaths(paths, attributes)
  122. if not (args.connect or args.no_order or args.break_uncontinuous) :
  123. log.info("Ordering paths")
  124. from orderPaths import orderPaths
  125. paths, attributes = orderPaths(paths, attributes)
  126. outfile = args.outfile if args.outfile else args.infile
  127. log.info("Writing in %s", outfile)
  128. wsvg(paths, attributes=attributes, filename=outfile)
  129. except FileNotFoundError :
  130. log.critical('The given file is not found')
  131. except Exception as e :
  132. log.critical("Un uncaught error has occured:", exc_info=e)
  133. log.info("Terminating connectSVG without writing")
  134. else :
  135. log.info("connectSVG has finished")