Empty SVG groups grow up the exported files

Discussions about the development of the TechDraw workbench
User avatar
flachyjoe
Posts: 571
Joined: Sat Mar 31, 2012 12:00 pm
Location: Limoges, France

Empty SVG groups grow up the exported files

Postby flachyjoe » Mon May 07, 2018 2:01 pm

Hi,
I notice some SVG files produced by TechDraw have many empty groups : a <g> item without any geometry inside.
ie.

Code: Select all

[...]
     stroke-linejoin="bevel"
     id="g111675">
    <g
       fill="none"
       stroke="#000000"
       stroke-opacity="1"
       stroke-width="1"
       stroke-linecap="square"
       stroke-linejoin="bevel"
       transform="matrix(1,0,0,1,0,0)"
       font-family=".SF NS Text"
       font-size="45.8611"
       font-weight="400"
       font-style="normal"
       id="g75837" />
    <g
       fill="none"
[...]
Such dust can be cleaned with this search RegExp in a text editor :

Code: Select all

<g[^<>]*/>
- Flachy Joe -
alias FFW @ irc.freenode.net #freecad et #freecad-fr
"Puisqu’on ne peut changer la direction du vent, il faut apprendre à orienter les voiles." Anonyme
wandererfan
Posts: 2371
Joined: Tue Nov 06, 2012 5:42 pm

Re: Empty SVG groups grow up the exported files

Postby wandererfan » Thu May 10, 2018 3:46 pm

flachyjoe wrote:
Mon May 07, 2018 2:01 pm
I notice some SVG files produced by TechDraw have many empty groups : a <g> item without any geometry inside.
Not sure we can do much about this. The file is created automagically by the QtSvg module.
ulrich1a
Posts: 1872
Joined: Sun Jul 07, 2013 12:08 pm

Re: Empty SVG groups grow up the exported files

Postby ulrich1a » Thu May 10, 2018 4:09 pm

The program scour does a good job in optimizing the size of a SVG-file: https://github.com/scour-project/scour

What could be done in FreeCAD, is to open the file and do some cleaning and save the cleaned file automatically.
The other option is to write a SVG-exporter.

Ulrich
User avatar
flachyjoe
Posts: 571
Joined: Sat Mar 31, 2012 12:00 pm
Location: Limoges, France

Re: Empty SVG groups grow up the exported files

Postby flachyjoe » Sat Feb 16, 2019 5:55 pm

Hi,
I spent a few time to write a cleaner witch remove empty groups and concatenate identical adjacent ones.
When edit with Inkscape for example, we got one group per view. It's really useful.
A improvement will concatenate non-adjacent similar groups.

Code: Select all

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  clean_fc_svg.py
#  
#  Copyright 2019 Florian Foinant <ffw_at_2f2v.fr>
#  
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#  
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#  MA 02110-1301, USA.

def main(args):
	if len(args)!=3 :
		print "Clean a FreeCAD exported SVG file"
		print "Usage : python clean_fc_svg.py input.svg output.svg"
		return 1
	
	input_svg = open(args[1],'r').read()
	
	import re
	#remove empty groups
	input_svg = re.sub('<g[^<>]*/>\n ','',input_svg)
	
	#parse the xml
	import lxml.etree as ET
	ET.register_namespace("svg", "http://www.w3.org/2000/svg")
	parser = ET.XMLParser(remove_blank_text=True)
	
	root = ET.fromstring(input_svg, parser)
	tree = ET.ElementTree(root)

	#concatenate identical adjacent groups
	last_grp = None
	parent_grp = None
	for grp in root.iter('{http://www.w3.org/2000/svg}g') :
		if len(grp) == 1 :
			if not last_grp is None and cmp(grp.attrib,last_grp.attrib)==0 :
				last_grp.append(grp[0])
				if parent_grp is not None :
					parent_grp.remove(grp)
			else :
				last_grp = grp
		else :
			parent_grp = grp

	#Save the cleaned XML
	tree.write(args[2], encoding='utf8', xml_declaration=True, pretty_print=True)
	return 0

if __name__ == '__main__':
	import sys
	sys.exit(main(sys.argv))
- Flachy Joe -
alias FFW @ irc.freenode.net #freecad et #freecad-fr
"Puisqu’on ne peut changer la direction du vent, il faut apprendre à orienter les voiles." Anonyme
User avatar
flachyjoe
Posts: 571
Joined: Sat Mar 31, 2012 12:00 pm
Location: Limoges, France

Re: Empty SVG groups grow up the exported files

Postby flachyjoe » Sun Feb 17, 2019 10:04 am

Updated with the announced improvement :

Code: Select all

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  clean_fc_svg.py
#  
#  Copyright 2019 Florian Foinant <ffw_at_2f2v.fr>
#  
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#  
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#  MA 02110-1301, USA.
#  
def main(args):
	if len(args)!=3 :
		print "Clean a FreeCAD exported SVG file"
		print "Usage : python clean_fc_svg.py input.svg output.svg"
		return 1

	try :
		input_svg = open(args[1],'r').read()
	except IOError :
		print "No such file:", args[1]
		return 1

	#parse the xml
	import lxml.etree as ET
	ET.register_namespace("svg", "http://www.w3.org/2000/svg")
	parser = ET.XMLParser(remove_blank_text=True)

	root = ET.fromstring(input_svg, parser)
	
	grps = [g for g in root.iter('{http://www.w3.org/2000/svg}g')]
	print 'Start : %i groups' % len(grps)

	#concatenate identical groups and remove empty ones
	parent_grp = root
	empty_count=0
	identic_count=0
	for grp in grps :
		if len(grp) == 0 :
			parent_grp.remove(grp)
			empty_count += 1
		elif len(grp) == 1 :
			for known in grps :
				if grp != known :
					if cmp(grp.attrib,known.attrib)==0 :
						known.append(grp[0])
						parent_grp.remove(grp)
						identic_count += 1
						break
				else :
					break
		else :
			parent_grp = grp
	
	print 'End : %i groups' % len([g for g in root.iter('{http://www.w3.org/2000/svg}g')]), ', %i empty and %i identical removed' % (empty_count, identic_count)

	#Save the cleaned XML
	tree = ET.ElementTree(root)
	tree.write(args[2], encoding='utf8', xml_declaration=True, pretty_print=True)
	return 0

if __name__ == '__main__':
	import sys
	sys.exit(main(sys.argv))

With my test file :

Code: Select all

flachy@joe:~/EnCours/tests FC$ python clean_fc_svg.py test.svg clean.svg
Start : 1136 groups
End : 27 groups , 674 empty and 435 identical removed
- Flachy Joe -
alias FFW @ irc.freenode.net #freecad et #freecad-fr
"Puisqu’on ne peut changer la direction du vent, il faut apprendre à orienter les voiles." Anonyme