icons: regenerate every platform icon from the canonical Goblin sources
All app icons now derive from two sources, end to end:
img/goblin-icon.png gradient app icon (yellow gradient + black mascot)
img/goblin-mark-black.svg black mascot mark (vector) — Android adaptive fg
- scripts/gen_icons.sh rewritten: one run regenerates the desktop/egui window
icon (img/icon.png), the Linux AppImage AppDir icon, all Android launcher +
adaptive-foreground mipmaps, the WiX installer icon, and the macOS .icns.
Dropped the dead goblin-mask*.png pipeline (the adaptive foreground is now the
SVG mark composited by the OS over #FFD60A), so the script no longer references
files that were removed.
- scripts/make-icns.py: new, dependency-free multi-resolution .icns builder
(iconutil/png2icns aren't always present; ImageMagick alone emits one size).
- wix/Product.ico REPLACED with the Goblin logo (was a stale icon).
- Regenerated macOS AppIcon.icns, Linux goblin.png, all Android mipmaps,
img/icon.png. Tracked the goblin-mark-{black,white}.svg sources.
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 2.1 MiB After Width: | Height: | Size: 37 KiB |
@@ -0,0 +1,48 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||||
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="600.000000pt" height="601.000000pt" viewBox="0 0 600.000000 601.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet">
|
||||||
|
<g transform="translate(0.000000,601.000000) scale(0.050000,-0.050000)"
|
||||||
|
fill="#000000" stroke="none">
|
||||||
|
<path d="M195 11784 c-515 -1551 98 -2966 1520 -3514 171 -66 171 -72 2 -72
|
||||||
|
-415 0 -893 215 -1273 572 -178 167 -181 163 -77 -83 478 -1130 1770 -1734
|
||||||
|
2963 -1384 283 83 309 101 420 292 376 648 1038 1116 1763 1245 l143 26 100
|
||||||
|
202 c887 1780 -911 3344 -3076 2675 l-170 -52 220 -14 c480 -32 818 -114 1118
|
||||||
|
-273 258 -137 548 -414 624 -597 l32 -76 -87 76 c-435 375 -938 524 -1557 461
|
||||||
|
-273 -28 -340 -39 -740 -120 -893 -182 -1449 24 -1756 650 l-98 200 -71 -214z"/>
|
||||||
|
<path d="M9720 10053 c0 -146 -256 -556 -441 -705 -381 -308 -766 -380 -1559
|
||||||
|
-290 -1178 133 -2048 -270 -2488 -1152 -57 -115 -92 -149 -92 -89 0 78 123
|
||||||
|
415 199 548 43 74 73 135 67 135 -25 0 -397 -184 -512 -253 -962 -578 -1594
|
||||||
|
-1675 -1594 -2767 0 -209 -2 -210 -154 -95 -393 297 -523 388 -751 525 -321
|
||||||
|
192 -571 311 -843 400 -290 95 -302 94 -242 -15 52 -95 166 -372 191 -465 9
|
||||||
|
-33 34 -121 56 -195 48 -161 120 -508 194 -935 118 -684 437 -1371 795 -1715
|
||||||
|
185 -178 324 -239 594 -262 144 -13 150 -15 147 -63 -1 -27 -14 -174 -28 -326
|
||||||
|
-83 -902 258 -1568 1037 -2024 139 -81 161 -80 127 4 -37 96 -85 369 -96 546
|
||||||
|
l-10 170 46 -60 c328 -431 869 -753 1497 -891 351 -77 1285 -67 1426 15 9 5
|
||||||
|
-104 50 -250 98 -653 218 -1499 778 -1704 1129 -43 73 -54 78 188 -79 230
|
||||||
|
-149 543 -303 750 -369 783 -249 1542 -242 2332 20 l274 91 106 -83 c298 -236
|
||||||
|
798 -328 1259 -231 197 42 196 38 32 169 -156 124 -344 356 -443 546 l-60 116
|
||||||
|
70 52 c544 408 783 906 627 1300 l-41 102 170 138 c442 355 584 624 813 1537
|
||||||
|
186 742 257 952 452 1328 l118 227 -145 -14 c-693 -68 -1425 -411 -1729 -810
|
||||||
|
-99 -130 -112 -127 -165 44 -54 175 -217 511 -308 636 -64 88 -70 91 -224 117
|
||||||
|
-419 70 -947 328 -1223 597 -98 96 -153 192 -70 122 41 -35 332 -177 487 -238
|
||||||
|
97 -38 146 -55 348 -118 335 -105 983 -129 1280 -47 1070 294 1688 1238 1761
|
||||||
|
2691 16 304 7 325 -82 190 -88 -134 -504 -535 -669 -645 -618 -412 -1228 -507
|
||||||
|
-1895 -296 -192 60 -199 77 -67 163 428 277 628 871 480 1428 -20 75 -38 98
|
||||||
|
-38 48z m-682 -4962 c306 -158 601 -1396 416 -1747 -118 -224 -283 -345 -526
|
||||||
|
-387 -455 -78 -577 227 -456 1143 96 725 320 1118 566 991z m-3115 -156 c371
|
||||||
|
-172 699 -815 799 -1565 34 -251 19 -307 -108 -422 -575 -519 -1624 -162
|
||||||
|
-1931 657 -265 709 593 1630 1240 1330z m5261 -120 c20 -377 -135 -912 -290
|
||||||
|
-995 -70 -38 -72 -35 -157 230 l-64 200 -24 -90 c-50 -192 -144 -340 -215
|
||||||
|
-340 -111 0 -316 804 -228 893 53 53 200 -130 226 -283 l14 -80 36 105 c100
|
||||||
|
293 222 333 332 109 l54 -110 35 105 c89 260 271 427 281 256z m-8491 -284
|
||||||
|
l75 -230 52 160 c89 272 210 336 295 154 126 -268 210 -757 142 -825 -44 -44
|
||||||
|
-163 120 -247 340 -12 33 -19 24 -39 -50 -89 -330 -286 -346 -374 -30 l-22 80
|
||||||
|
-35 -125 c-54 -196 -223 -428 -275 -377 -37 37 -29 448 11 608 70 276 219 524
|
||||||
|
314 524 17 0 56 -87 103 -229z m4164 -2698 c137 -310 856 -372 1401 -121 175
|
||||||
|
81 194 76 89 -23 -356 -336 -878 -447 -1310 -278 -224 88 -517 339 -517 443 0
|
||||||
|
53 140 267 212 324 l58 46 14 -152 c8 -84 31 -191 53 -239z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.2 KiB |
@@ -0,0 +1,48 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||||
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="600.000000pt" height="601.000000pt" viewBox="0 0 600.000000 601.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet">
|
||||||
|
<g transform="translate(0.000000,601.000000) scale(0.050000,-0.050000)"
|
||||||
|
fill="#ffffff" stroke="none">
|
||||||
|
<path d="M195 11784 c-515 -1551 98 -2966 1520 -3514 171 -66 171 -72 2 -72
|
||||||
|
-415 0 -893 215 -1273 572 -178 167 -181 163 -77 -83 478 -1130 1770 -1734
|
||||||
|
2963 -1384 283 83 309 101 420 292 376 648 1038 1116 1763 1245 l143 26 100
|
||||||
|
202 c887 1780 -911 3344 -3076 2675 l-170 -52 220 -14 c480 -32 818 -114 1118
|
||||||
|
-273 258 -137 548 -414 624 -597 l32 -76 -87 76 c-435 375 -938 524 -1557 461
|
||||||
|
-273 -28 -340 -39 -740 -120 -893 -182 -1449 24 -1756 650 l-98 200 -71 -214z"/>
|
||||||
|
<path d="M9720 10053 c0 -146 -256 -556 -441 -705 -381 -308 -766 -380 -1559
|
||||||
|
-290 -1209 137 -2026 -255 -2519 -1208 -78 -151 -82 -156 -72 -77 18 140 128
|
||||||
|
450 210 592 43 74 73 135 67 135 -25 0 -397 -184 -512 -253 -966 -580 -1594
|
||||||
|
-1674 -1594 -2777 0 -104 -4 -190 -10 -190 -5 0 -65 43 -132 95 -650 503
|
||||||
|
-1118 775 -1606 935 -290 95 -302 94 -242 -15 52 -95 166 -372 191 -465 9 -33
|
||||||
|
34 -121 56 -195 48 -161 120 -508 194 -935 118 -684 437 -1371 795 -1715 185
|
||||||
|
-178 324 -239 594 -262 144 -13 150 -15 147 -63 -1 -27 -14 -174 -28 -326 -83
|
||||||
|
-902 258 -1568 1037 -2024 139 -81 161 -80 127 4 -37 96 -85 369 -96 546 l-10
|
||||||
|
170 46 -60 c328 -431 869 -753 1497 -891 351 -77 1285 -67 1426 15 9 5 -104
|
||||||
|
50 -250 98 -649 217 -1341 668 -1680 1096 -81 102 -88 147 -11 78 157 -142
|
||||||
|
653 -406 925 -493 783 -249 1542 -242 2332 20 l274 91 106 -83 c298 -236 798
|
||||||
|
-328 1259 -231 197 42 196 38 32 169 -156 124 -344 356 -443 546 l-60 116 70
|
||||||
|
52 c544 408 783 906 627 1300 l-41 102 170 138 c442 355 584 624 813 1537 186
|
||||||
|
742 257 952 452 1328 l118 227 -145 -14 c-693 -68 -1425 -411 -1729 -810 -99
|
||||||
|
-130 -112 -127 -165 44 -54 175 -217 511 -308 636 -64 88 -70 91 -224 117
|
||||||
|
-314 52 -637 184 -956 390 -260 168 -509 436 -280 302 127 -74 302 -160 430
|
||||||
|
-211 97 -38 146 -55 348 -118 335 -105 983 -129 1280 -47 961 264 1554 1048
|
||||||
|
1729 2286 28 199 45 685 23 677 -9 -4 -73 -77 -141 -163 -650 -810 -1594
|
||||||
|
-1147 -2451 -873 -251 80 -246 76 -171 121 395 240 638 767 578 1253 -25 209
|
||||||
|
-77 395 -77 278z m-682 -4962 c306 -158 601 -1396 416 -1747 -118 -224 -283
|
||||||
|
-345 -526 -387 -455 -78 -577 227 -456 1143 96 725 320 1118 566 991z m-3115
|
||||||
|
-156 c371 -172 699 -815 799 -1565 34 -251 19 -307 -108 -422 -575 -519 -1624
|
||||||
|
-162 -1931 657 -265 709 593 1630 1240 1330z m5261 -120 c20 -377 -135 -912
|
||||||
|
-290 -995 -70 -38 -72 -35 -157 230 l-64 200 -24 -90 c-50 -192 -144 -340
|
||||||
|
-215 -340 -111 0 -316 804 -228 893 53 53 200 -130 226 -283 l14 -80 36 105
|
||||||
|
c100 293 222 333 332 109 l54 -110 35 105 c89 260 271 427 281 256z m-8491
|
||||||
|
-284 l75 -230 52 160 c89 272 210 336 295 154 126 -268 210 -757 142 -825 -44
|
||||||
|
-44 -163 120 -247 340 -12 33 -19 24 -39 -50 -89 -330 -286 -346 -374 -30
|
||||||
|
l-22 80 -35 -125 c-54 -196 -223 -428 -275 -377 -37 37 -29 448 11 608 70 276
|
||||||
|
219 524 314 524 17 0 56 -87 103 -229z m4164 -2698 c137 -311 883 -373 1408
|
||||||
|
-116 162 78 171 64 42 -61 -317 -305 -854 -408 -1271 -244 -223 87 -516 338
|
||||||
|
-516 442 0 53 140 267 212 324 l58 46 14 -152 c8 -84 31 -191 53 -239z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
@@ -1,32 +1,45 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Generate all Goblin app icons from img/goblin-icon.png (app icon)
|
# Regenerate EVERY platform's app icon from two canonical sources:
|
||||||
# and img/goblin-mask.png (black mascot art on transparency).
|
# img/goblin-icon.png the gradient app icon (yellow gradient + black mascot)
|
||||||
# Requires ImageMagick (magick).
|
# img/goblin-mark-black.svg the black mascot mark, vector, transparent bg
|
||||||
|
# (mirror of site/assets/goblin-mark-black.svg)
|
||||||
|
#
|
||||||
|
# Square icons (desktop window, Linux AppImage, Android launcher, Windows .ico,
|
||||||
|
# macOS .icns) come from the gradient PNG. The Android *adaptive* foreground is
|
||||||
|
# the black mascot on transparency, composited by the OS over the yellow
|
||||||
|
# background color (res/values/ic_launcher_background.xml = #FFD60A) — which
|
||||||
|
# reproduces the gradient icon's look.
|
||||||
|
#
|
||||||
|
# Requires ImageMagick (magick) and python3 (for the .icns container).
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
cd "$(dirname "$0")/.."
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
ICON=img/goblin-icon.png
|
ICON=img/goblin-icon.png
|
||||||
MASK=img/goblin-mask.png
|
MARK=img/goblin-mark-black.svg
|
||||||
RES=android/app/src/main/res
|
RES=android/app/src/main/res
|
||||||
|
|
||||||
# Desktop window icon + in-app embeds.
|
# --- Desktop window icon (egui, src/main.rs) + Linux AppImage AppDir icon ---
|
||||||
magick "$ICON" -resize 256x256 img/icon.png
|
magick "$ICON" -resize 256x256 PNG32:img/icon.png
|
||||||
magick "$ICON" -resize 512x512 img/goblin-icon-512.png
|
cp img/icon.png linux/Goblin.AppDir/goblin.png
|
||||||
magick "$MASK" -channel RGB -fill white -colorize 100 img/goblin-mask-white.png
|
|
||||||
magick img/goblin-mask-white.png -resize 128x128 img/goblin-mask-128.png
|
|
||||||
magick img/goblin-mask-white.png -resize 64x64 img/goblin-mask-64.png
|
|
||||||
|
|
||||||
# Android launcher icons.
|
# --- Android launcher icons (gradient square) + adaptive foreground (mascot) ---
|
||||||
declare -A SIZES=( [mdpi]=48 [hdpi]=72 [xhdpi]=96 [xxhdpi]=144 [xxxhdpi]=192 )
|
declare -A SIZES=( [mdpi]=48 [hdpi]=72 [xhdpi]=96 [xxhdpi]=144 [xxxhdpi]=192 )
|
||||||
declare -A FG_SIZES=( [mdpi]=108 [hdpi]=162 [xhdpi]=216 [xxhdpi]=324 [xxxhdpi]=432 )
|
declare -A FG_SIZES=( [mdpi]=108 [hdpi]=162 [xhdpi]=216 [xxhdpi]=324 [xxxhdpi]=432 )
|
||||||
for d in mdpi hdpi xhdpi xxhdpi xxxhdpi; do
|
for d in mdpi hdpi xhdpi xxhdpi xxxhdpi; do
|
||||||
s=${SIZES[$d]}; fg=${FG_SIZES[$d]}
|
s=${SIZES[$d]}; fg=${FG_SIZES[$d]}
|
||||||
# mascot occupies ~52% of the adaptive canvas (safe zone is 66%)
|
# Mascot fills ~60% of the adaptive canvas — inside the ~61% safe zone, so no
|
||||||
art=$(( fg * 52 / 100 ))
|
# launcher mask (circle/squircle) ever clips it.
|
||||||
magick "$ICON" -resize ${s}x${s} "$RES/mipmap-$d/ic_launcher.png"
|
art=$(( fg * 60 / 100 ))
|
||||||
magick "$ICON" -resize ${s}x${s} "$RES/mipmap-$d/ic_launcher_round.png"
|
magick "$ICON" -resize "${s}x${s}" PNG32:"$RES/mipmap-$d/ic_launcher.png"
|
||||||
magick "$MASK" -resize ${art}x${art} -background none \
|
magick "$ICON" -resize "${s}x${s}" PNG32:"$RES/mipmap-$d/ic_launcher_round.png"
|
||||||
-gravity center -extent ${fg}x${fg} "$RES/mipmap-$d/ic_launcher_foreground.png"
|
magick -background none "$MARK" -resize "${art}x${art}" \
|
||||||
|
-gravity center -extent "${fg}x${fg}" PNG32:"$RES/mipmap-$d/ic_launcher_foreground.png"
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "icons generated"
|
# --- Windows installer + file-type icon (WiX wix/Product.ico) ---
|
||||||
|
magick "$ICON" -define icon:auto-resize=256,128,64,48,32,24,16 wix/Product.ico
|
||||||
|
|
||||||
|
# --- macOS app bundle icon (Goblin.app) ---
|
||||||
|
python3 scripts/make-icns.py "$ICON" macos/Goblin.app/Contents/Resources/AppIcon.icns
|
||||||
|
|
||||||
|
echo "icons generated from $ICON + $MARK"
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Build a macOS .icns from a square PNG, dependency-free.
|
||||||
|
|
||||||
|
macOS has `iconutil` and Linux distros have `png2icns`, but neither is reliably
|
||||||
|
present, and ImageMagick's own .icns writer only emits a single size. So we
|
||||||
|
assemble the multi-resolution PNG-payload .icns container by hand (the format
|
||||||
|
macOS 10.7+ accepts): the `icns` magic + big-endian length, then one entry per
|
||||||
|
OSType, each carrying an 8-bit PNG. ImageMagick (`magick`) does the resizing.
|
||||||
|
|
||||||
|
Usage: make-icns.py <source.png> <out.icns>
|
||||||
|
"""
|
||||||
|
|
||||||
|
import struct
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# OSType -> pixel size. PNG-payload entries. Sizes above the source are
|
||||||
|
# Lanczos-upscaled (soft but acceptable for the few large Dock/Finder slots).
|
||||||
|
SLOTS = [
|
||||||
|
(b"icp4", 16),
|
||||||
|
(b"icp5", 32),
|
||||||
|
(b"icp6", 64),
|
||||||
|
(b"ic07", 128),
|
||||||
|
(b"ic08", 256),
|
||||||
|
(b"ic11", 32), # 16@2x
|
||||||
|
(b"ic12", 64), # 32@2x
|
||||||
|
(b"ic13", 256), # 128@2x
|
||||||
|
(b"ic09", 512), # 512
|
||||||
|
(b"ic14", 512), # 256@2x
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def render(src, size):
|
||||||
|
out = "/tmp/_icns_%d.png" % size
|
||||||
|
subprocess.run(
|
||||||
|
["magick", src, "-resize", "%dx%d" % (size, size),
|
||||||
|
"-filter", "Lanczos", "-depth", "8", "PNG32:%s" % out],
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
return open(out, "rb").read()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) != 3:
|
||||||
|
sys.exit("usage: make-icns.py <source.png> <out.icns>")
|
||||||
|
src, out = sys.argv[1], sys.argv[2]
|
||||||
|
cache, entries = {}, []
|
||||||
|
for ostype, size in SLOTS:
|
||||||
|
if size not in cache:
|
||||||
|
cache[size] = render(src, size)
|
||||||
|
data = cache[size]
|
||||||
|
entries.append(ostype + struct.pack(">I", 8 + len(data)) + data)
|
||||||
|
body = b"".join(entries)
|
||||||
|
with open(out, "wb") as f:
|
||||||
|
f.write(b"icns" + struct.pack(">I", 8 + len(body)) + body)
|
||||||
|
print("wrote %s (%d entries)" % (out, len(entries)))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 364 KiB |