summaryrefslogtreecommitdiff
path: root/support/inkscape/inkscape.py
blob: 876b0a79bea982e669ca00ee36d0dff8bffe193f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import os
import xml.etree.ElementTree as etree
from lib import util


def get_inkscape_layers(svg_path):
	document = etree.parse(svg_path)
	
	def iter_layers():
		nodes = document.findall(
			'{http://www.w3.org/2000/svg}g[@{http://www.inkscape.org/namespaces/inkscape}groupmode="layer"]')
		
		for i in nodes:
			inkscape_name = i.get('{http://www.inkscape.org/namespaces/inkscape}label').strip()
			
			if inkscape_name.endswith(']'):
				export_name, args = inkscape_name[:-1].rsplit('[', 1)
				
				export_name = export_name.strip()
				args = args.strip()
				
				use_paths = 'p' in args
			else:
				use_paths = False
				export_name = inkscape_name
			
			yield Layer(inkscape_name, export_name, use_paths)
	
	return list(iter_layers())


def _inkscape(svg_path, verbs):
	def iter_args():
		yield os.environ['INKSCAPE']
		
		for i in verbs:
			yield '--verb'
			yield i
		
		yield svg_path
	
	util.command(list(iter_args()))


class Layer(object):
	def __init__(self, inkscape_name, export_name, use_paths):
		self.inkscape_name = inkscape_name
		self.export_name = export_name
		self.use_paths = use_paths


class InkscapeCommandLine(object):
	def __init__(self, path):
		self._path = path
		self._layers = get_inkscape_layers(path)
		self._current_layer_index = None
		self._verbs = []
	
	def apply_to_document(self, *verb):
		self._verbs.extend(verb)
	
	def apply_to_layer(self, layer, *verb):
		self._go_to_layer(layer)
		self.apply_to_document(*verb)
	
	def select_all_in_layer(self, layer):
		self.apply_to_layer(layer, 'EditSelectAll')
	
	def apply_to_layer_content(self, layer, *verbs):
		self.select_all_in_layer(layer)
		self.apply_to_document(*verbs)
	
	def _go_to_layer(self, layer, with_selection = False):
		if self._current_layer_index is None:
			# Initialize to a known state.
			self._current_layer_index = len(self._layers) - 1
			self._go_to_layer(self._layers[0])
		
		target_index = self._layers.index(layer)
		
		while True:
			if self._current_layer_index < target_index:
				self.apply_to_document('LayerMoveToNext' if with_selection else 'LayerNext')
				self._current_layer_index += 1
			elif self._current_layer_index > target_index:
				self.apply_to_document('LayerMoveToPrev' if with_selection else 'LayerPrev')
				self._current_layer_index -= 1
			else:
				break
	
	def duplicate_layer(self, layer):
		self.apply_to_layer(layer, 'LayerDuplicate')
		
		# Inkscape 0.91 places a duplicated layer above (after) the selected one and selects the new layer.
		new_layer = Layer(layer.inkscape_name + ' copy', layer.export_name, layer.use_paths)
		self._current_layer_index += 1
		self._layers.insert(self._current_layer_index, new_layer)
		
		return new_layer
	
	def delete_layer(self, layer):
		self.apply_to_layer(layer, 'LayerDelete')
		
		# Inkscape 0.91 selects the layer above (after) the deleted layer.
		del self._layers[self._current_layer_index]
	
	def clear_layer(self, layer):
		self.select_all_in_layer(layer)
		self.apply_to_document('EditDelete')
	
	def move_content(self, source_layer, target_layer):
		self.select_all_in_layer(source_layer)
		self._go_to_layer(target_layer, True)
	
	def run(self):
		_inkscape(self._path, self._verbs)
	
	@property
	def layers(self):
		return list(self._layers)