app icon: nine-tailed kitsune (owner's ArtCraft drawing), Dock/taskbar/launcher wiring, palette docs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Brandon Thomas 2026-10-02 09:47:45 -04:00
parent 1fc68c7411
commit 148b1b4411
19 changed files with 85 additions and 77 deletions

View File

@ -16,6 +16,19 @@ mod services;
use photocraft_engine::Session; use photocraft_engine::Session;
use photocraft_ui_egui::PhotocraftApp; use photocraft_ui_egui::PhotocraftApp;
/// Matches the `.desktop` file and hicolor icon name, so Wayland docks pick up the icon.
const APP_ID: &str = "ai.storyteller.photocraft";
/// Window, taskbar and (when running unbundled) Dock icon. macOS gets the padded 1024 px render
/// on Apple's icon grid; elsewhere the tighter 256 px hicolor render reads better at small sizes.
fn app_icon() -> egui::IconData {
#[cfg(target_os = "macos")]
const PNG: &[u8] = include_bytes!("../../../assets/app-icon/photocraft-1024.png");
#[cfg(not(target_os = "macos"))]
const PNG: &[u8] = include_bytes!("../../../assets/app-icon/hicolor/256x256/apps/ai.storyteller.photocraft.png");
eframe::icon_data::from_png_bytes(PNG).unwrap_or_default()
}
fn main() -> eframe::Result { fn main() -> eframe::Result {
let mut control_port: Option<u16> = std::env::var("PHOTOCRAFT_CONTROL_PORT").ok().and_then(|p| p.parse().ok()); let mut control_port: Option<u16> = std::env::var("PHOTOCRAFT_CONTROL_PORT").ok().and_then(|p| p.parse().ok());
let mut files = Vec::new(); let mut files = Vec::new();
@ -34,7 +47,10 @@ fn main() -> eframe::Result {
} }
let options = eframe::NativeOptions { let options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default().with_title("PhotoCraft").with_inner_size([1440.0, 900.0]).with_min_inner_size([760.0, 480.0]).with_drag_and_drop(true).with_fullsize_content_view(true).with_titlebar_shown(false).with_title_shown(false), viewport: egui::ViewportBuilder::default()
.with_icon(app_icon())
.with_app_id(APP_ID)
.with_title("PhotoCraft").with_inner_size([1440.0, 900.0]).with_min_inner_size([760.0, 480.0]).with_drag_and_drop(true).with_fullsize_content_view(true).with_titlebar_shown(false).with_title_shown(false),
..Default::default() ..Default::default()
}; };
eframe::run_native( eframe::run_native(

View File

@ -1,8 +1,9 @@
Photocraft app icon (photocraft.svg and every file derived from it in this directory: PhotoCraft app icon (photocraft.svg, photocraft-small.svg and every file derived from them in
photocraft-1024.png, photocraft.icns, photocraft.ico, hicolor/). this directory: photocraft-1024.png, photocraft.icns, photocraft.ico, hicolor/).
Original artwork by the Photocraft authors, made for this project (no third-party material). Original artwork made for this project by the project owner: an engraving-style drawing created
Licensed like the rest of Photocraft, under either of in ArtCraft, then vectorised. No third-party material. Licensed like the rest of PhotoCraft,
under either of
* Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0) * Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
* MIT license (https://opensource.org/licenses/MIT) * MIT license (https://opensource.org/licenses/MIT)

44
assets/app-icon/README.md Normal file
View File

@ -0,0 +1,44 @@
# PhotoCraft app icon
A **nine-tailed kitsune with a brow diamond**: an engraving portrait, seated, looking back at the
viewer, in the Crafting Apps' owl-template framing (full-bleed field, head and body filling the
tile, tails running off the edges).
## Palette
Exactly three colours:
| Colour | Hex | Used for |
|---|---|---|
| Ink | `#0b0b0c` | line work and contours |
| Paper | `#efe9dc` | the figure |
| PhotoCraft blue (app colour) | `#2f7bf5` | the full-bleed field |
## Geometry
A 512-unit tile (`viewBox="0 0 512 512"`), rounded square with `rx=112`, no border. The macOS
renders pad it onto Apple's 824/1024 icon grid; the Windows and Linux renders crop 22 units off
each side so the figure reads at 16–48 px.
## Provenance
The owner's original drawing, made in ArtCraft (2880 px, engraving style, keyed to the palette),
vectorised with craftrules `assets/logo-options/_tools/vectorize_tile.py`. The source PNG stays in
craftrules at `assets/app-icons/photocraft/source.png`. License: see `LICENSE.txt`.
## Files
- `photocraft.svg`: canonical master (traced at 2048 px).
- `photocraft-small.svg`: lighter trace (traced at 1024 px); also the hicolor scalable icon.
- `photocraft-1024.png`: 1024 px render on the macOS grid.
- `photocraft.icns`: macOS bundle icon (`CFBundleIconFile`).
- `photocraft.ico`: Windows icon, 16–256 px, embedded in the `.exe` by `apps/photocraft/build.rs`.
- `hicolor/<size>/apps/ai.storyteller.photocraft.png` (16–512) and `hicolor/scalable/...svg`:
Linux icon theme.
The app also sets the window icon and Wayland app ID at runtime (`apps/photocraft/src/main.rs`).
## Regenerate
Replace `photocraft.svg` (and `photocraft-small.svg`), then run `packaging/icons.sh`. It needs
`resvg`, plus `iconutil` on macOS; the `.ico` is packed by `cargo xtask ico`.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 671 B

After

Width:  |  Height:  |  Size: 784 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 321 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 298 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 321 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 98 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 751 KiB

View File

@ -182,8 +182,9 @@ The keychain is deleted at the end of the job.
## Icons ## Icons
`assets/app-icon/photocraft.svg` is our own artwork (MIT OR Apache-2.0, see `LICENSE.txt` `assets/app-icon/photocraft.svg` is the canonical icon: the owner's ArtCraft drawing of a
there). `packaging/icons.sh` regenerates the 1024 px PNG, the `.icns`, the `.ico` (packed by nine-tailed kitsune, vectorised (MIT OR Apache-2.0, see `LICENSE.txt` there; palette and
geometry in `README.md`). `packaging/icons.sh` regenerates the 1024 px PNG, the `.icns`, the `.ico` (packed by
`cargo xtask ico`) and the hicolor PNGs from it. It needs `resvg`, plus `iconutil` on macOS. `cargo xtask ico`) and the hicolor PNGs from it. It needs `resvg`, plus `iconutil` on macOS.
The outputs are committed, so packaging never needs those tools. The outputs are committed, so packaging never needs those tools.

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Regenerate every app icon from assets/app-icon/photocraft.svg. # Regenerate every app icon from assets/app-icon/photocraft.svg (the canonical master).
# #
# Needs: resvg (brew install resvg / cargo install resvg). On macOS, iconutil also writes the # Needs: resvg (brew install resvg / cargo install resvg). On macOS, iconutil also writes the
# .icns. The outputs are committed, so packaging never needs these tools. # .icns. The outputs are committed, so packaging never needs these tools.
@ -14,14 +14,18 @@ trap 'rm -rf "$TMP"' EXIT
command -v resvg >/dev/null || { echo "error: resvg not found (brew install resvg)" >&2; exit 1; } command -v resvg >/dev/null || { echo "error: resvg not found (brew install resvg)" >&2; exit 1; }
# macOS icons keep Apple's 824/1024 body grid (transparent margin). Windows and Linux icons are # The artwork is a full-bleed 512-unit tile (rx=112). macOS icons pad it to Apple's 824/1024 body
# cropped tighter so the shape reads at 16-48 px. # grid (transparent margin). Windows and Linux icons crop 22 units off each side (into the
# rounded corners) so the portrait reads at 16-48 px.
grep -q 'viewBox="0 0 512 512"' "$SVG" || { echo "error: expected viewBox=\"0 0 512 512\" in $SVG" >&2; exit 1; }
MAC="$TMP/mac.svg"
sed 's/viewBox="0 0 512 512"/viewBox="-62 -62 636 636"/' "$SVG" >"$MAC"
TIGHT="$TMP/tight.svg" TIGHT="$TMP/tight.svg"
sed 's/viewBox="0 0 1024 1024"/viewBox="88 88 848 848"/' "$SVG" >"$TIGHT" sed 's/viewBox="0 0 512 512"/viewBox="22 22 468 468"/' "$SVG" >"$TIGHT"
render() { resvg -w "$2" -h "$2" "$1" "$3" </dev/null; } render() { resvg -w "$2" -h "$2" "$1" "$3" </dev/null; }
render "$SVG" 1024 "$DIR/photocraft-1024.png" render "$MAC" 1024 "$DIR/photocraft-1024.png"
# Linux hicolor theme. # Linux hicolor theme.
for s in 16 24 32 48 64 128 256 512; do for s in 16 24 32 48 64 128 256 512; do
@ -29,7 +33,8 @@ for s in 16 24 32 48 64 128 256 512; do
render "$TIGHT" "$s" "$DIR/hicolor/${s}x${s}/apps/ai.storyteller.photocraft.png" render "$TIGHT" "$s" "$DIR/hicolor/${s}x${s}/apps/ai.storyteller.photocraft.png"
done done
mkdir -p "$DIR/hicolor/scalable/apps" mkdir -p "$DIR/hicolor/scalable/apps"
cp "$SVG" "$DIR/hicolor/scalable/apps/ai.storyteller.photocraft.svg" # The lighter trace (photocraft-small.svg) keeps the scalable theme icon cheap to render.
cp "$DIR/photocraft-small.svg" "$DIR/hicolor/scalable/apps/ai.storyteller.photocraft.svg"
# Windows .ico. # Windows .ico.
ICO_PNGS=() ICO_PNGS=()
@ -44,8 +49,8 @@ if command -v iconutil >/dev/null; then
SET="$TMP/photocraft.iconset" SET="$TMP/photocraft.iconset"
mkdir -p "$SET" mkdir -p "$SET"
for s in 16 32 128 256 512; do for s in 16 32 128 256 512; do
render "$SVG" "$s" "$SET/icon_${s}x${s}.png" render "$MAC" "$s" "$SET/icon_${s}x${s}.png"
render "$SVG" $((s * 2)) "$SET/icon_${s}x${s}@2x.png" render "$MAC" $((s * 2)) "$SET/icon_${s}x${s}@2x.png"
done done
iconutil -c icns -o "$DIR/photocraft.icns" "$SET" iconutil -c icns -o "$DIR/photocraft.icns" "$SET"
else else