testsAndMisc/python_pkg/app_icons/README.md
Krzysztof kuhy Rudnicki 27f44cad4b Add shared launcher-icon generator for the Flutter apps
Every Flutter app still shipped the stock Flutter "beach" launcher icon, and
none had an adaptive-icon descriptor at all. Rather than hand-drawing five
one-off icons, define the family once and let each app contribute only an
accent colour and a glyph.

The family: a charcoal #1B1D21 field carrying one glyph in that app's own
theme seed colour, at a single stroke weight. Glyphs are optically centred
automatically - render.centre_offset rasterises a glyph alone, measures its
ink box, and translates (never scales) the fragment, so a row of icons lines
up while every icon keeps the exact family stroke weight.

safe_box_overflow warns when a glyph exceeds the 560px adaptive-icon safe
box; it caught three real overflows that a launcher mask would have clipped.

The registry points dufs_client at ~/dufs-cloud/app: ~/dufs_client was a
stale, remote-less checkout with an identical package name, since deleted.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 16:55:48 +02:00

68 lines
2.6 KiB
Markdown

# app_icons — shared launcher icons for the Flutter apps
One icon family across every Flutter/Dart app: a charcoal `#1B1D21` field with
a single glyph in that app's own theme accent, drawn at one stroke weight and
optically centred so a row of them lines up.
## Commands
```bash
# what is registered
PYTHONPATH=~/testsAndMisc python3 -m python_pkg.app_icons list
# contact sheet for visual review: full size / circle-masked / 48dp
PYTHONPATH=~/testsAndMisc python3 -m python_pkg.app_icons preview -o /tmp/sheet.png
# write assets into every app repo and rebuild the Android mipmaps
PYTHONPATH=~/testsAndMisc python3 -m python_pkg.app_icons generate --android
# one app, plus the hicolor PNGs for a Linux desktop target
PYTHONPATH=~/testsAndMisc python3 -m python_pkg.app_icons \
generate --app todo --android --linux-out ~/todo/linux/icons
```
## What gets written
Per app, into `<repo>/assets/icon/`:
| Layer | Purpose |
| --- | --- |
| `icon` | Charcoal field + glyph. Legacy square launcher icon and Linux icon. |
| `icon_foreground` | Glyph only, transparent. Adaptive-icon foreground layer. |
| `icon_monochrome` | Glyph only, white. Android 13+ themed icons. |
Both an `.svg` source and a 1024px `.png` are written for each, so a build
never needs `rsvg-convert`. `flutter_launcher_icons` then turns the PNGs into
the density buckets and `mipmap-anydpi-v26/ic_launcher.xml`.
## Design constraints that bite
- **Negative space ≥ half the stroke weight.** Strokes closer than that merge
into a solid blob at launcher size. A fork whose tines sat exactly one stroke
width apart rendered as a tulip.
- **Ink must stay inside the 560px safe box.** Android masks adaptive icons to
roughly the inner 66% of the canvas. `generate` warns when a glyph overflows.
- **Stroked outlines can read wrong.** A stroked three-tine fork reads as a
trident; a filled fork-and-knife pair reads as cutlery. Prefer a filled
silhouette when the outline is ambiguous.
- Glyph positioning inside the fragment is irrelevant — `render.centre_offset`
measures the rendered ink and recentres it. Only the extents matter.
## Adding an app
See the `app-icon` skill (`~/.claude/skills/app-icon/SKILL.md`) for the full
procedure. In short: add a glyph to `glyphs.py`, register the app in
`apps.py`, wire `flutter_launcher_icons` into its `pubspec.yaml`, generate,
review the contact sheet, then verify on the phone.
## Tests
```bash
cd ~/testsAndMisc
python3 -m pytest python_pkg/app_icons --cov=python_pkg.app_icons \
--cov-report=term-missing
```
External tools (`rsvg-convert`, `magick`, `dart`) are mocked; the suite needs
none of them installed.