-
Notifications
You must be signed in to change notification settings - Fork 147
/
gen.py
executable file
·216 lines (175 loc) · 7.07 KB
/
gen.py
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#!/usr/bin/env python3
"""
Copyright (C) 2019 Numix Project
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License (version 3+) as
published by the Free Software Foundation. You should have received
a copy of the GNU General Public License along with this program.
If not, see <http://www.gnu.org/licenses/>.
"""
# Sorting out modules
from argparse import ArgumentParser
from io import BytesIO
from json import load
from os import listdir, makedirs, path, symlink
from shutil import copy2
from subprocess import PIPE, Popen, call
try:
from gi import require_version
require_version("Rsvg", "2.0")
from gi.repository import Rsvg
from cairo import ImageSurface, Context, FORMAT_ARGB32
use_inkscape = False
except (ImportError, AttributeError, ValueError):
# Assigns true if Inkscape found, false otherwise
use_inkscape = not call(["which", "inkscape"], stdout=PIPE, stderr=PIPE)
if not use_inkscape:
exit("Can't load CairoSVG nor Inkscape")
# Loading the JSON data file
try:
with open("data.json") as data:
icons = load(data)
except FileNotFoundError:
exit("Please clone the whole repository and try again.")
# Parsing build arguments
parser = ArgumentParser(prog="Numix-core")
try:
# Exclude files and tag directories from the list of themes
themes = [dir for dir in listdir("icons") if "." not in dir]
except FileNotFoundError:
exit("No icons folder found. Please reclone and try again.")
parser.add_argument("--theme", "-t",
help="Theme you want to build.",
choices=themes)
platform, platforms = "", ["android", "linux", "osx"]
parser.add_argument("--platform", "-p",
help="Platform you like to build the theme for.",
choices=platforms)
args = parser.parse_args()
# User selects the theme
if not args.theme:
msg = "Please use --theme argument with one of the following: "
exit(msg + ", ".join(themes))
else:
theme = args.theme
# Each theme may support different sizes
sizes = listdir("icons/" + theme)
# User selects the platform
if not args.platform:
msg = "Please use --platform argument with one of the following: "
exit(msg + ", ".join(platforms))
else:
platform = args.platform
def mkdir(directory):
"""Create a directory if it doesn't exists."""
if not path.exists(directory):
makedirs(directory)
def convert_svg2png(infile, outfile, w, h):
"""
Converts svg files to png using CairoSVG or Inkscape
@file_path : String; the svg file absolute path
@dest_path : String; the png file absolute path
"""
if use_inkscape:
cmd = Popen([
"inkscape", "-z", infile, "-o", outfile,
"-w", str(w), "-h", str(h)
], stdout=PIPE, stderr=PIPE)
cmd.communicate()
else:
handle = Rsvg.Handle()
svg = handle.new_from_file(infile)
dim = svg.get_dimensions()
img = ImageSurface(FORMAT_ARGB32, w, h)
ctx = Context(img)
ctx.scale(w / dim.width, h / dim.height)
svg.render_cairo(ctx)
png_io = BytesIO()
img.write_to_png(png_io)
with open(outfile, "wb") as fout:
fout.write(png_io.getvalue())
svg.close()
png_io.close()
img.finish()
# Android Generation Code
if platform == "android":
print("\nGenerating Android theme...")
# Define and create theme locations
theme_name = "com.numix.icons_" + theme
android_dir = theme_name + "/MainActivity22/app/src/main/res/"
app_filter = android_dir + "xml/appfilter.xml"
theme_dir = android_dir + "drawable-xxhdpi/"
mkdir(theme_dir)
mkdir(path.dirname(app_filter))
# app_filter file contains Android meta data for the theme
app_filter_content = '<?xml version="1.0" encoding="utf-8"?>\n'
app_filter_content += '<resources>\n'
for icon_name, icon in icons.items():
for component_info in icon.get("android", []):
# Check icon source exists before it's used
source = "icons/{0}/48/{1}.svg".format(theme, format(icon_name))
if not path.exists(source):
continue
# Render icon to resources directory
drawable_name = icon_name.replace(".", "_").replace("-", "_")
output = "{0}/{1}.png".format(theme_dir, drawable_name)
convert_svg2png(source, output, 192, 192)
# Add icons app_filter data (afd) to the app_filter file
afd = '\t<item component="ComponentInfo{{{0}}}" drawable="{1}"/>\n'
app_filter_content += afd.format(component_info, drawable_name)
app_filter_content += '</resources>'
with open(app_filter, "w") as app_filter_obj:
app_filter_obj.write(app_filter_content)
# Linux Generation Code
elif platform == "linux":
print("\nGenerating Linux theme...")
# Define and create theme locations
linux_dir = "numix-icon-theme-{0}/Numix-{1}".format(theme, theme.title())
for size in sizes:
mkdir("{0}/{1}/apps".format(linux_dir, size))
for icon_name, icon in icons.items():
if not icon.get("linux"):
continue
for size in sizes:
# Check icon source exists before it's used
source = "icons/{0}/{1}/{2}.svg".format(theme, size, icon_name)
if not path.exists(source):
continue
# Create root SVG icon
root = icon["linux"]["root"] + ".svg"
output = "{0}/{1}/apps/".format(linux_dir, size)
copy2(source, output + root)
# Symlinks to root icon
for link in icon["linux"].get("symlinks", []):
output_symlink = output + link + ".svg"
try:
symlink(root, output_symlink)
except FileExistsError:
continue
# OSX Generation Code
elif platform == "osx":
print("\nGenerating OSX theme...")
# OSX generation depends on libicns function png2icns
no_icns = call(["which", "png2icns"], stdout=PIPE, stderr=PIPE)
if no_icns:
exit("You will need png2icns in order to generate OSX theme")
# Define and create theme locations
osx_dir = "numix-{0}.icns".format(theme)
for sub_dir in ["icns", "pngs", "vectors"]:
mkdir("{0}/{1}".format(osx_dir, sub_dir))
for icon_name, icon in icons.items():
for output_icon in icon.get("osx", []):
# Check icon source exists before it's used
source = "icons/{0}/48/{1}.svg".format(theme, icon_name)
if not path.exists(source):
continue
# Icon output locations
svg_icon = "{0}/vectors/{1}.svg".format(osx_dir, output_icon)
png_icon = "{0}/pngs/{1}.png".format(osx_dir, output_icon)
icn_icon = "{0}/icns/{1}.icn".format(osx_dir, output_icon)
# Create icon in SVG, PNG, and ICNS formats
copy2(source, svg_icon)
convert_svg2png(source, png_icon, 1024, 1024)
call(["png2icns", icn_icon, png_icon], stdout=PIPE, stderr=PIPE)
# Clean Up
print("Done!\n")