Skip to content

Commit c695ff8

Browse files
committed
new application icon
1 parent 9ba0fd5 commit c695ff8

File tree

13 files changed

+814
-0
lines changed

13 files changed

+814
-0
lines changed

icons/devdocs-desktop.png

-1.45 KB
Binary file not shown.
52.3 KB
Loading
4.5 KB
Loading
707 Bytes
Loading
1.17 KB
Loading
10.4 KB
Loading
1.53 KB
Loading
1.42 KB
Loading
22.9 KB
Loading
1.98 KB
Loading
3.2 KB
Loading

icons/render-bitmaps.py

+224
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
#!/usr/bin/python3
2+
#
3+
# Legal Stuff:
4+
#
5+
# This file is part of the Paper Icon Theme and is free software; you can redistribute it and/or modify it under
6+
# the terms of the GNU Lesser General Public License as published by the Free Software
7+
# Foundation; version 3.
8+
#
9+
# This file is part of the Paper Icon Theme and is distributed in the hope that it will be useful, but WITHOUT
10+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11+
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12+
# details.
13+
#
14+
# You should have received a copy of the GNU General Public License along with
15+
# this program; if not, see <https://www.gnu.org/licenses/lgpl-3.0.txt>
16+
#
17+
#
18+
# Thanks to the GNOME icon developers for the original version of this script
19+
20+
import os
21+
import sys
22+
import xml.sax
23+
import subprocess
24+
import argparse
25+
26+
INKSCAPE = '/usr/bin/inkscape'
27+
OPTIPNG = '/usr/bin/optipng'
28+
MAINDIR = 'hicolor'
29+
SRC = 'src'
30+
SIZES = {
31+
16: [16, 96],
32+
24: [24, 96],
33+
32: [32, 96],
34+
48: [48, 96],
35+
64: [48, 128],
36+
96: [512, 18],
37+
128: [512, 24],
38+
256: [512, 48],
39+
512: [512, 96],
40+
1024: [512, 192]
41+
}
42+
43+
inkscape_process = None
44+
45+
def main(args, SRC):
46+
47+
def optimize_png(png_file):
48+
if os.path.exists(OPTIPNG):
49+
process = subprocess.Popen([OPTIPNG, '-quiet', '-o7', png_file])
50+
process.wait()
51+
52+
def wait_for_prompt(process, command=None):
53+
if command is not None:
54+
process.stdin.write((command+'\n').encode('utf-8'))
55+
56+
# This is kinda ugly ...
57+
# Wait for just a '>', or '\n>' if some other char appearead first
58+
output = process.stdout.read(1)
59+
if output == b'>':
60+
return
61+
62+
output += process.stdout.read(1)
63+
while output != b'\n>':
64+
output += process.stdout.read(1)
65+
output = output[1:]
66+
67+
def start_inkscape():
68+
process = subprocess.Popen([INKSCAPE, '--shell'], bufsize=0, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
69+
wait_for_prompt(process)
70+
return process
71+
72+
def inkscape_render_rect(icon_file, rect, dpi, output_file):
73+
global inkscape_process
74+
if inkscape_process is None:
75+
inkscape_process = start_inkscape()
76+
77+
cmd = [icon_file,
78+
'--export-dpi', str(dpi),
79+
'-i', rect,
80+
'-e', output_file]
81+
wait_for_prompt(inkscape_process, ' '.join(cmd))
82+
optimize_png(output_file)
83+
84+
class ContentHandler(xml.sax.ContentHandler):
85+
ROOT = 0
86+
SVG = 1
87+
LAYER = 2
88+
OTHER = 3
89+
TEXT = 4
90+
def __init__(self, path, force=False, filter=None):
91+
self.stack = [self.ROOT]
92+
self.inside = [self.ROOT]
93+
self.path = path
94+
self.rects = []
95+
self.state = self.ROOT
96+
self.chars = ""
97+
self.force = force
98+
self.filter = filter
99+
100+
def endDocument(self):
101+
pass
102+
103+
def startElement(self, name, attrs):
104+
if self.inside[-1] == self.ROOT:
105+
if name == "svg":
106+
self.stack.append(self.SVG)
107+
self.inside.append(self.SVG)
108+
return
109+
elif self.inside[-1] == self.SVG:
110+
if (name == "g" and ('inkscape:groupmode' in attrs) and ('inkscape:label' in attrs)
111+
and attrs['inkscape:groupmode'] == 'layer' and attrs['inkscape:label'].startswith('Baseplate')):
112+
self.stack.append(self.LAYER)
113+
self.inside.append(self.LAYER)
114+
self.context = None
115+
self.icon_name = None
116+
self.rects = []
117+
return
118+
elif self.inside[-1] == self.LAYER:
119+
if name == "text" and ('inkscape:label' in attrs) and attrs['inkscape:label'] == 'context':
120+
self.stack.append(self.TEXT)
121+
self.inside.append(self.TEXT)
122+
self.text='context'
123+
self.chars = ""
124+
return
125+
elif name == "text" and ('inkscape:label' in attrs) and attrs['inkscape:label'] == 'icon-name':
126+
self.stack.append(self.TEXT)
127+
self.inside.append(self.TEXT)
128+
self.text='icon-name'
129+
self.chars = ""
130+
return
131+
elif name == "rect":
132+
self.rects.append(attrs)
133+
134+
self.stack.append(self.OTHER)
135+
136+
137+
def endElement(self, name):
138+
stacked = self.stack.pop()
139+
if self.inside[-1] == stacked:
140+
self.inside.pop()
141+
142+
if stacked == self.TEXT and self.text is not None:
143+
assert self.text in ['context', 'icon-name']
144+
if self.text == 'context':
145+
self.context = self.chars
146+
elif self.text == 'icon-name':
147+
self.icon_name = self.chars
148+
self.text = None
149+
elif stacked == self.LAYER:
150+
assert self.icon_name
151+
assert self.context
152+
153+
if self.filter is not None and not self.icon_name in self.filter:
154+
return
155+
156+
print (self.context, self.icon_name)
157+
158+
rects = {}
159+
160+
for rect in self.rects:
161+
width = int(rect['width'])
162+
rects[width] = rect
163+
164+
for size, value in SIZES.items():
165+
src, dpi = value
166+
rect = rects[src]
167+
id = rect['id']
168+
size_str = "%sx%s" % (size, size)
169+
170+
dir = os.path.join(MAINDIR, size_str, self.context)
171+
outfile = os.path.join(dir, self.icon_name+'.png')
172+
if not os.path.exists(dir):
173+
os.makedirs(dir)
174+
# Do a time based check!
175+
if self.force or not os.path.exists(outfile):
176+
inkscape_render_rect(self.path, id, dpi, outfile)
177+
sys.stdout.write('.')
178+
else:
179+
stat_in = os.stat(self.path)
180+
stat_out = os.stat(outfile)
181+
if stat_in.st_mtime > stat_out.st_mtime:
182+
inkscape_render_rect(self.path, id, dpi, outfile)
183+
sys.stdout.write('.')
184+
else:
185+
sys.stdout.write('-')
186+
sys.stdout.flush()
187+
188+
sys.stdout.write('\n')
189+
sys.stdout.flush()
190+
191+
def characters(self, chars):
192+
self.chars += chars.strip()
193+
194+
195+
if not args.svg:
196+
if not os.path.exists(MAINDIR):
197+
os.mkdir(MAINDIR)
198+
print ('')
199+
print ('Rendering from SVGs in', SRC)
200+
print ('')
201+
for file in os.listdir(SRC):
202+
if file[-4:] == '.svg':
203+
file = os.path.join(SRC, file)
204+
handler = ContentHandler(file)
205+
xml.sax.parse(open(file), handler)
206+
print ('')
207+
else:
208+
file = os.path.join(SRC, args.svg + '.svg')
209+
210+
if os.path.exists(os.path.join(file)):
211+
handler = ContentHandler(file, True, filter=args.filter)
212+
xml.sax.parse(open(file), handler)
213+
else:
214+
# icon not in this directory, try the next one
215+
pass
216+
217+
parser = argparse.ArgumentParser(description='Render icons from SVG to PNG')
218+
219+
parser.add_argument('svg', type=str, nargs='?', metavar='SVG', help="Optional SVG names (without extensions) to render. If not given, render all icons")
220+
parser.add_argument('filter', type=str, nargs='?', metavar='FILTER', help="Optional filter for the SVG file")
221+
222+
args = parser.parse_args()
223+
SRC = os.path.join('.', SRC)
224+
main(args, SRC)

0 commit comments

Comments
 (0)