181 lines
5.3 KiB
Python
181 lines
5.3 KiB
Python
|
#! /usr/bin/env python3
|
||
|
|
||
|
import os
|
||
|
import sys
|
||
|
import inkex
|
||
|
|
||
|
def log(text):
|
||
|
inkex.utils.debug(text)
|
||
|
|
||
|
|
||
|
def abort(text):
|
||
|
inkex.errormsg(_(text))
|
||
|
exit()
|
||
|
|
||
|
|
||
|
class GeneratePalette(inkex.EffectExtension):
|
||
|
|
||
|
|
||
|
def add_arguments(self, pars):
|
||
|
pars.add_argument('--name', help='Palette name')
|
||
|
pars.add_argument('--property', help='Color property')
|
||
|
pars.add_argument('--default', type=inkex.Boolean, help='Default grays')
|
||
|
pars.add_argument('--sort', help='Sort type')
|
||
|
pars.add_argument('--replace', type=inkex.Boolean, dest='replace', help='Replace existing')
|
||
|
|
||
|
|
||
|
def get_palettes_path(self):
|
||
|
if sys.platform.startswith('win'):
|
||
|
path = os.path.join(os.environ['APPDATA'], 'inkscape', 'palettes')
|
||
|
else:
|
||
|
path = os.environ.get('XDG_CONFIG_HOME', '~/.config')
|
||
|
path = os.path.join(path, 'inkscape', 'palettes')
|
||
|
|
||
|
return os.path.expanduser(path)
|
||
|
|
||
|
|
||
|
def get_file_path(self):
|
||
|
name = str(self.options.name).replace(' ', '-')
|
||
|
return "%s/%s.gpl" % (self.palettes_path, name)
|
||
|
|
||
|
|
||
|
def get_default_colors(self):
|
||
|
colors = [
|
||
|
" 0 0 0 Black",
|
||
|
" 26 26 26 90% Gray",
|
||
|
" 51 51 51 80% Gray",
|
||
|
" 77 77 77 70% Gray",
|
||
|
"102 102 102 60% Gray",
|
||
|
"128 128 128 50% Gray",
|
||
|
"153 153 153 40% Gray",
|
||
|
"179 179 179 30% Gray",
|
||
|
"204 204 204 20% Gray",
|
||
|
"230 230 230 10% Gray",
|
||
|
"236 236 236 7.5% Gray",
|
||
|
"242 242 242 5% Gray",
|
||
|
"249 249 249 2.5% Gray",
|
||
|
"255 255 255 White"
|
||
|
]
|
||
|
|
||
|
return colors if self.options.default else []
|
||
|
|
||
|
|
||
|
def get_node_prop(self, node, property):
|
||
|
attr = node.attrib.get('style')
|
||
|
style = dict(inkex.Style.parse_str(attr))
|
||
|
|
||
|
return style.get(property, 'none')
|
||
|
|
||
|
|
||
|
def get_node_index(self, item):
|
||
|
node = item[1]
|
||
|
id = node.attrib.get('id')
|
||
|
|
||
|
return self.options.ids.index(id)
|
||
|
|
||
|
|
||
|
def get_node_x(self, item):
|
||
|
node = item[1]
|
||
|
return node.bounding_box().center_x
|
||
|
|
||
|
|
||
|
def get_node_y(self, item):
|
||
|
node = item[1]
|
||
|
return node.bounding_box().center_y
|
||
|
|
||
|
|
||
|
def get_formatted_color(self, color):
|
||
|
rgb = inkex.Color(color).to_rgb()
|
||
|
|
||
|
if self.options.sort == 'hsl':
|
||
|
key = inkex.Color(color).to_hsl()
|
||
|
key = "{:03d}{:03d}{:03d}".format(*key)
|
||
|
else:
|
||
|
key = "{:03d}{:03d}{:03d}".format(*rgb)
|
||
|
|
||
|
rgb = "{:3d} {:3d} {:3d}".format(*rgb)
|
||
|
color = str(color).upper()
|
||
|
name = str(inkex.Color(color).to_named()).upper()
|
||
|
|
||
|
if name != color:
|
||
|
name = "%s (%s)" % (name.capitalize(), color)
|
||
|
|
||
|
return "%s %s %s" % (key, rgb, name)
|
||
|
|
||
|
|
||
|
def get_selected_colors(self):
|
||
|
colors = []
|
||
|
selected = list(self.svg.selected.items())
|
||
|
|
||
|
if self.options.sort == 'y_location':
|
||
|
selected.sort(key=self.get_node_x)
|
||
|
selected.sort(key=self.get_node_y)
|
||
|
elif self.options.sort == 'x_location':
|
||
|
selected.sort(key=self.get_node_y)
|
||
|
selected.sort(key=self.get_node_x)
|
||
|
else:
|
||
|
selected.sort(key=self.get_node_index)
|
||
|
|
||
|
for id, node in selected:
|
||
|
if self.options.property in ['fill', 'both']:
|
||
|
fill = self.get_node_prop(node, 'fill')
|
||
|
|
||
|
if inkex.colors.is_color(fill):
|
||
|
if fill != 'none' and fill not in colors:
|
||
|
colors.append(fill)
|
||
|
|
||
|
if self.options.property in ['stroke', 'both']:
|
||
|
stroke = self.get_node_prop(node, 'stroke')
|
||
|
|
||
|
if inkex.colors.is_color(stroke):
|
||
|
if stroke != 'none' and stroke not in colors:
|
||
|
colors.append(stroke)
|
||
|
|
||
|
colors = list(map(self.get_formatted_color, colors))
|
||
|
|
||
|
if self.options.sort == 'hsl' or self.options.sort == 'rgb':
|
||
|
colors.sort()
|
||
|
|
||
|
return list(map(lambda x : x[11:], colors))
|
||
|
|
||
|
|
||
|
def write_palette(self):
|
||
|
file = open(self.file_path, 'w')
|
||
|
try:
|
||
|
file.write("GIMP Palette\n")
|
||
|
file.write("Name: %s\n" % self.options.name)
|
||
|
file.write("#\n# Generated with Inkscape Generate Palette\n#\n")
|
||
|
|
||
|
for color in self.default_colors:
|
||
|
file.write("%s\n" % color)
|
||
|
|
||
|
for color in self.selected_colors:
|
||
|
if color[:11] not in list(map(lambda x : x[:11], self.default_colors)):
|
||
|
file.write("%s\n" % color)
|
||
|
finally:
|
||
|
file.close()
|
||
|
|
||
|
|
||
|
def effect(self):
|
||
|
self.palettes_path = self.get_palettes_path()
|
||
|
self.file_path = self.get_file_path()
|
||
|
self.default_colors = self.get_default_colors()
|
||
|
self.selected_colors = self.get_selected_colors()
|
||
|
|
||
|
if not self.options.replace and os.path.exists(self.file_path):
|
||
|
abort('Palette already exists!')
|
||
|
|
||
|
if not self.options.name:
|
||
|
abort('Please enter a palette name.')
|
||
|
|
||
|
if len(self.options.ids) < 2:
|
||
|
abort('Please select at least 2 objects.')
|
||
|
|
||
|
if not len(self.selected_colors):
|
||
|
abort('No colors found in selected objects!')
|
||
|
|
||
|
self.write_palette()
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
GeneratePalette().run()
|