Skip to content

Commit 75c5f7f

Browse files
committed
logo: Generate launcher icons, as Zulip logo plus "BETA"
This script is adapted lightly from the one with the same name in zulip-mobile. The SVGs that describe the design are also lightly adapted from what we have in zulip-mobile for debug builds. (Which say "DEBUG" rather than "BETA".) Fixes: #390
1 parent c667aec commit 75c5f7f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+342
-90
lines changed
-544 Bytes
Binary file not shown.
Binary file not shown.
-442 Bytes
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 60 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,122 +1,92 @@
11
{
2-
"images" : [
2+
"images": [
33
{
4-
"size" : "20x20",
5-
"idiom" : "iphone",
6-
"filename" : "Icon-App-20x20@2x.png",
7-
"scale" : "2x"
4+
"size": "60x60",
5+
"idiom": "iphone",
6+
"filename": "Icon-60x60@3x.png",
7+
"scale": "3x"
88
},
99
{
10-
"size" : "20x20",
11-
"idiom" : "iphone",
12-
"filename" : "Icon-App-20x20@3x.png",
13-
"scale" : "3x"
10+
"size": "60x60",
11+
"idiom": "iphone",
12+
"filename": "Icon-60x60@2x.png",
13+
"scale": "2x"
1414
},
1515
{
16-
"size" : "29x29",
17-
"idiom" : "iphone",
18-
"filename" : "Icon-App-29x29@1x.png",
19-
"scale" : "1x"
16+
"size": "83.5x83.5",
17+
"idiom": "ipad",
18+
"filename": "Icon-83.5x83.5@2x.png",
19+
"scale": "2x"
2020
},
2121
{
22-
"size" : "29x29",
23-
"idiom" : "iphone",
24-
"filename" : "Icon-App-29x29@2x.png",
25-
"scale" : "2x"
22+
"size": "76x76",
23+
"idiom": "ipad",
24+
"filename": "Icon-76x76@2x.png",
25+
"scale": "2x"
2626
},
2727
{
28-
"size" : "29x29",
29-
"idiom" : "iphone",
30-
"filename" : "Icon-App-29x29@3x.png",
31-
"scale" : "3x"
28+
"size": "1024x1024",
29+
"idiom": "ios-marketing",
30+
"filename": "Icon-1024x1024@1x.png",
31+
"scale": "1x"
3232
},
3333
{
34-
"size" : "40x40",
35-
"idiom" : "iphone",
36-
"filename" : "Icon-App-40x40@2x.png",
37-
"scale" : "2x"
34+
"size": "40x40",
35+
"idiom": "iphone",
36+
"filename": "Icon-40x40@3x.png",
37+
"scale": "3x"
3838
},
3939
{
40-
"size" : "40x40",
41-
"idiom" : "iphone",
42-
"filename" : "Icon-App-40x40@3x.png",
43-
"scale" : "3x"
40+
"size": "40x40",
41+
"idiom": "iphone",
42+
"filename": "Icon-40x40@2x.png",
43+
"scale": "2x"
4444
},
4545
{
46-
"size" : "60x60",
47-
"idiom" : "iphone",
48-
"filename" : "Icon-App-60x60@2x.png",
49-
"scale" : "2x"
46+
"size": "40x40",
47+
"idiom": "ipad",
48+
"filename": "Icon-40x40@2x.png",
49+
"scale": "2x"
5050
},
5151
{
52-
"size" : "60x60",
53-
"idiom" : "iphone",
54-
"filename" : "Icon-App-60x60@3x.png",
55-
"scale" : "3x"
52+
"size": "29x29",
53+
"idiom": "iphone",
54+
"filename": "Icon-29x29@3x.png",
55+
"scale": "3x"
5656
},
5757
{
58-
"size" : "20x20",
59-
"idiom" : "ipad",
60-
"filename" : "Icon-App-20x20@1x.png",
61-
"scale" : "1x"
58+
"size": "29x29",
59+
"idiom": "iphone",
60+
"filename": "Icon-29x29@2x.png",
61+
"scale": "2x"
6262
},
6363
{
64-
"size" : "20x20",
65-
"idiom" : "ipad",
66-
"filename" : "Icon-App-20x20@2x.png",
67-
"scale" : "2x"
64+
"size": "29x29",
65+
"idiom": "ipad",
66+
"filename": "Icon-29x29@2x.png",
67+
"scale": "2x"
6868
},
6969
{
70-
"size" : "29x29",
71-
"idiom" : "ipad",
72-
"filename" : "Icon-App-29x29@1x.png",
73-
"scale" : "1x"
70+
"size": "20x20",
71+
"idiom": "iphone",
72+
"filename": "Icon-20x20@3x.png",
73+
"scale": "3x"
7474
},
7575
{
76-
"size" : "29x29",
77-
"idiom" : "ipad",
78-
"filename" : "Icon-App-29x29@2x.png",
79-
"scale" : "2x"
76+
"size": "20x20",
77+
"idiom": "iphone",
78+
"filename": "Icon-20x20@2x.png",
79+
"scale": "2x"
8080
},
8181
{
82-
"size" : "40x40",
83-
"idiom" : "ipad",
84-
"filename" : "[email protected]",
85-
"scale" : "1x"
86-
},
87-
{
88-
"size" : "40x40",
89-
"idiom" : "ipad",
90-
"filename" : "[email protected]",
91-
"scale" : "2x"
92-
},
93-
{
94-
"size" : "76x76",
95-
"idiom" : "ipad",
96-
"filename" : "[email protected]",
97-
"scale" : "1x"
98-
},
99-
{
100-
"size" : "76x76",
101-
"idiom" : "ipad",
102-
"filename" : "[email protected]",
103-
"scale" : "2x"
104-
},
105-
{
106-
"size" : "83.5x83.5",
107-
"idiom" : "ipad",
108-
"filename" : "[email protected]",
109-
"scale" : "2x"
110-
},
111-
{
112-
"size" : "1024x1024",
113-
"idiom" : "ios-marketing",
114-
"filename" : "[email protected]",
115-
"scale" : "1x"
82+
"size": "20x20",
83+
"idiom": "ipad",
84+
"filename": "[email protected]",
85+
"scale": "2x"
11686
}
11787
],
118-
"info" : {
119-
"version" : 1,
120-
"author" : "xcode"
88+
"info": {
89+
"version": 1,
90+
"author": "xcode"
12191
}
12292
}
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

tools/generate-logos

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
#!/usr/bin/env bash
2+
set -eu
3+
4+
# Generate the many different versions of our logo we need across the app.
5+
#
6+
# This script is not run as part of the build, in order to avoid introducing
7+
# its somewhat specialized dependencies as requirements for normal
8+
# development. Instead, we keep its outputs checked into the repo.
9+
10+
# Because this script isn't meant to be run routinely, we let it be a bit
11+
# rough-and-ready in its interface. But it should error early if it's
12+
# missing anything it needs.
13+
#
14+
# Much of the knowledge it encodes -- what contexts call for which
15+
# graphical variation of the logo, in what sizes and what format --
16+
# was compiled at https://github.com/zulip/zulip-mobile/issues/4200
17+
# before being turned into this executable form (first for zulip-mobile).
18+
19+
# TIP: Everything in this script has the handy property that its
20+
# outputs are reproducible. That means that if you run it and
21+
# `git status` shows that it's changed any of the files in the
22+
# tree... then either the source images, or something in the
23+
# script itself, has changed since the run reflected in your
24+
# current tree.
25+
26+
this_dir=${BASH_SOURCE[0]%/*}
27+
. "${this_dir}"/lib/ensure-coreutils.sh
28+
root_dir=$(readlink -f "${this_dir}"/..)
29+
30+
tmpdir=$(mktemp -d)
31+
32+
die() {
33+
echo >&2 "$1"
34+
exit 1
35+
}
36+
37+
inkscape --version >/dev/null 2>&1 \
38+
|| die "Need inkscape -- try 'apt install inkscape'."
39+
40+
cwebp -version >/dev/null 2>&1 \
41+
|| die "Need cwebp -- try 'apt install webp'."
42+
43+
jq --version >/dev/null 2>&1 \
44+
|| die "Need jq -- try 'apt install jq'."
45+
46+
47+
# This should point to a zulip.git worktree.
48+
zulip_root="${root_dir%/*}"/zulip
49+
50+
# White Z in gradient-colored circle.
51+
src_icon_circle="${zulip_root}"/static/images/logo/zulip-icon-circle.svg
52+
53+
# White Z in gradient-colored circle with BETA banner.
54+
# Contains a link to the equivalent of ${src_icon_circle}.
55+
src_icon_circle_beta="${root_dir}"/tools/zulip-icon-circle-beta.svg
56+
57+
# White Z in gradient-colored square, full-bleed.
58+
# src_icon_square="${zulip_root}"/static/images/logo/zulip-icon-square.svg
59+
60+
# White Z in gradient-colored square, full-bleed, with BETA banner.
61+
# Contains a link to the equivalent of ${src_icon_square}.
62+
src_icon_square_beta="${root_dir}"/tools/zulip-icon-square-beta.svg
63+
64+
65+
[ -r "${src_icon_circle}" ] \
66+
|| die "Expected Zulip worktree at: ${zulip_root}"
67+
68+
69+
make_one_ios_app_icon() {
70+
# SET BY CALLER: contents iconset
71+
local size_pt="$1" scale="$2" idiom="$3"
72+
local size_px="${4-$(( size_pt * scale ))}"
73+
74+
local output_basename=Icon-"${size_pt}x${size_pt}@${scale}x".png
75+
local output="${iconset}"/"${output_basename}"
76+
if [ ! -f "${output}" ]; then
77+
inkscape "${src_icon_square_beta}" -w "${size_px}" --export-png="${output}"
78+
fi
79+
80+
printf >>"${contents}" \
81+
' { "size": "%s", "idiom": "%s", "filename": "%s", "scale": "%s" }\n' \
82+
"${size_pt}x${size_pt}" "${idiom}" "${output_basename}" "${scale}x"
83+
}
84+
85+
make_ios_app_icon() {
86+
local iconset=ios/Runner/Assets.xcassets/AppIcon.appiconset
87+
rm -rf "${iconset}"
88+
mkdir -p "${iconset}"
89+
90+
local contents="${tmpdir}"/Contents.json.in
91+
rm -f "${contents}"
92+
93+
# Handy command for a compact view of what's in the contents:
94+
# $ jq '.images[] | "\(.size) \(.scale) \(.idiom)"' -r \
95+
# <"${iconset}"/Contents.json
96+
97+
# From "App Icon Sizes" at:
98+
# https://developer.apple.com/design/human-interface-guidelines/ios/icons-and-images/app-icon/
99+
make_one_ios_app_icon 60 3 iphone
100+
make_one_ios_app_icon 60 2 iphone
101+
make_one_ios_app_icon 83.5 2 ipad 167
102+
make_one_ios_app_icon 76 2 ipad
103+
make_one_ios_app_icon 1024 1 ios-marketing
104+
105+
# From "Spotlight, Settings, and Notification Icons"
106+
# in the same iOS doc
107+
make_one_ios_app_icon 40 3 iphone
108+
make_one_ios_app_icon 40 2 iphone
109+
make_one_ios_app_icon 40 2 ipad
110+
make_one_ios_app_icon 29 3 iphone
111+
make_one_ios_app_icon 29 2 iphone
112+
make_one_ios_app_icon 29 2 ipad
113+
make_one_ios_app_icon 20 3 iphone
114+
make_one_ios_app_icon 20 2 iphone
115+
make_one_ios_app_icon 20 2 ipad
116+
117+
jq <"${contents}" \
118+
-s '{ "images": ., "info": { "version": 1, "author": "xcode" } }' \
119+
>"${iconset}"/Contents.json
120+
}
121+
122+
make_ios() {
123+
make_ios_app_icon
124+
}
125+
126+
127+
make_webp() {
128+
local input="$1" size="$2" output="$3"
129+
inkscape "${input}" -w "${size}" --export-png="${tmpdir}"/tmp.png
130+
# `cwebp -z 9` means lossless, and max/slowest compression
131+
cwebp -z 9 "${tmpdir}"/tmp.png -o "${output}"
132+
}
133+
134+
make_one_android_icon() {
135+
# SET BY CALLER: src sourceset restype name
136+
local size_px="$1" density="$2"
137+
local output=android/app/src/"${sourceset}"/res/"${restype}"-"${density}"/"${name}".webp
138+
mkdir -p "${output%/*}"
139+
make_webp "${src}" "${size_px}" "${output}"
140+
}
141+
142+
make_android_icon() {
143+
local src="$1" size_dp="$2" sourceset="$3" restype="$4" name="$5"
144+
145+
rm -f android/app/src/"${sourceset}"/res/*/"${name}".*
146+
147+
# Scale factors from:
148+
# https://developer.android.com/training/multiscreen/screendensities#TaskProvideAltBmp
149+
make_one_android_icon "${size_dp}" mdpi
150+
make_one_android_icon $(( size_dp * 3 / 2 )) hdpi
151+
make_one_android_icon $(( size_dp * 2 )) xhdpi
152+
make_one_android_icon $(( size_dp * 3 )) xxhdpi
153+
make_one_android_icon $(( size_dp * 4 )) xxxhdpi
154+
}
155+
156+
make_android() {
157+
# Launcher icon goes in a mipmap:
158+
# https://developer.android.com/training/multiscreen/screendensities#mipmap
159+
make_android_icon "${src_icon_circle_beta}" 48 main mipmap ic_launcher
160+
}
161+
162+
make_ios
163+
164+
make_android
165+
166+
cat <<'EOF'
167+
168+
Done!
169+
170+
If `git status` shows any changes in this script's outputs, be sure to
171+
commit those alongside your changes to the script itself.
172+
EOF

0 commit comments

Comments
 (0)