diff --git a/ATTRIBUTION.md b/ATTRIBUTION.md index 2159c8b7..6b3a38a7 100644 --- a/ATTRIBUTION.md +++ b/ATTRIBUTION.md @@ -4,7 +4,7 @@ Every asset PrintCraft includes, bundles or uses to build its published material, with its author, source and licence. The policy is in [AGENTS.md](AGENTS.md) ยง1. The machine-readable list, with SHA-256 hashes, is [ATTRIBUTION.toml](ATTRIBUTION.toml). Licence texts are kept beside the assets and summarised in [NOTICE](NOTICE). -## In this repository (223) +## In this repository (237) | Asset | Title | Author | Licence | Source | Used for | |---|---|---|---|---|---| @@ -206,6 +206,20 @@ Every asset PrintCraft includes, bundles or uses to build its published material | `docs/brand/artcraft-mark-black.svg` | ArtCraft brand: artcraft-mark-black | Storyteller | LicenseRef-Storyteller-Trademark | Storyteller brand assets (provided by the project owner, 2026-10-01; identical copies in storytold/photocraft) | ArtCraft branding next to the community links (About dialog, Help menu, home screen) and in docs. Not open source; forks must remove it. | | `docs/brand/artcraft-mark.png` | ArtCraft brand: artcraft-mark | Storyteller | LicenseRef-Storyteller-Trademark | Storyteller brand assets (provided by the project owner, 2026-10-01; identical copies in storytold/photocraft) | ArtCraft branding next to the community links (About dialog, Help menu, home screen) and in docs. Not open source; forks must remove it. | | `docs/brand/artcraft-mark.svg` | ArtCraft brand: artcraft-mark | Storyteller | LicenseRef-Storyteller-Trademark | Storyteller brand assets (provided by the project owner, 2026-10-01; identical copies in storytold/photocraft) | ArtCraft branding next to the community links (About dialog, Help menu, home screen) and in docs. Not open source; forks must remove it. | +| `assets/app-icon/printcraft.svg` | PrintCraft app icon (master vector) | PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Master artwork; every other app-icon file is rendered from it (packaging/icons.sh) | +| `assets/app-icon/printcraft-small.svg` | PrintCraft app icon (light vector) | PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | README header and assets/app-icon/README.md | +| `assets/app-icon/printcraft-1024.png` | PrintCraft app icon, 1024 px on Apple's icon grid | PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Runtime window/Dock icon on macOS (apps/printcraft/src/main.rs) | +| `assets/app-icon/printcraft.icns` | PrintCraft app icon (macOS .icns) | PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | macOS app bundle icon | +| `assets/app-icon/printcraft.ico` | PrintCraft app icon (Windows .ico, 16-256 px) | PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Embedded in printcraft.exe by apps/printcraft/build.rs (Explorer, taskbar, Start menu, Alt-Tab) | +| `assets/app-icon/hicolor/16x16/apps/ai.storyteller.printcraft.png` | PrintCraft app icon, 16 px | PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.printcraft.desktop) | +| `assets/app-icon/hicolor/24x24/apps/ai.storyteller.printcraft.png` | PrintCraft app icon, 24 px | PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.printcraft.desktop) | +| `assets/app-icon/hicolor/32x32/apps/ai.storyteller.printcraft.png` | PrintCraft app icon, 32 px | PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.printcraft.desktop) | +| `assets/app-icon/hicolor/48x48/apps/ai.storyteller.printcraft.png` | PrintCraft app icon, 48 px | PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.printcraft.desktop) | +| `assets/app-icon/hicolor/64x64/apps/ai.storyteller.printcraft.png` | PrintCraft app icon, 64 px | PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.printcraft.desktop) | +| `assets/app-icon/hicolor/128x128/apps/ai.storyteller.printcraft.png` | PrintCraft app icon, 128 px | PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.printcraft.desktop) | +| `assets/app-icon/hicolor/256x256/apps/ai.storyteller.printcraft.png` | PrintCraft app icon, 256 px | PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.printcraft.desktop); runtime window icon on Windows and Linux (apps/printcraft/src/main.rs) | +| `assets/app-icon/hicolor/512x512/apps/ai.storyteller.printcraft.png` | PrintCraft app icon, 512 px | PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.printcraft.desktop) | +| `assets/app-icon/hicolor/scalable/apps/ai.storyteller.printcraft.svg` | PrintCraft app icon (Linux scalable) | PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py) | MIT OR Apache-2.0 | Contributor-original (see assets/app-icon/README.md) | Linux hicolor theme icon (packaging/linux/ai.storyteller.printcraft.desktop) | | `docs/images/printcraft-bookmarks.png` | PrintCraft screenshot: Bookmarks | PrintCraft contributors (generated by `cargo xtask screenshots`) | MIT OR Apache-2.0 | this repository | README: navigation. Shows only PrintCraft UI, Lucide icons and the showcase PDF built from the [[fetched]] OFL fonts | | `docs/images/printcraft-dark.png` | PrintCraft screenshot: Dark theme | PrintCraft contributors (generated by `cargo xtask screenshots`) | MIT OR Apache-2.0 | this repository | README: themes. Shows only PrintCraft UI, Lucide icons and the showcase PDF built from the [[fetched]] OFL fonts | | `docs/images/printcraft-find.png` | PrintCraft screenshot: Find text | PrintCraft contributors (generated by `cargo xtask screenshots`) | MIT OR Apache-2.0 | this repository | README: search. Shows only PrintCraft UI, Lucide icons and the showcase PDF built from the [[fetched]] OFL fonts | diff --git a/ATTRIBUTION.toml b/ATTRIBUTION.toml index eda26046..fd107792 100644 --- a/ATTRIBUTION.toml +++ b/ATTRIBUTION.toml @@ -2520,6 +2520,160 @@ kind = "logo" usage = "ArtCraft branding next to the community links (About dialog, Help menu, home screen) and in docs. Not open source; forks must remove it." sha256 = "f87af81b6fa411da8820eed2bfdcc54c0ee9cd453b4e868c64f56c69db142d0e" +[[asset]] +path = "assets/app-icon/printcraft.svg" +title = "PrintCraft app icon (master vector)" +author = "PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)" +source = "Contributor-original (see assets/app-icon/README.md)" +licence = "MIT OR Apache-2.0" +licence_file = "assets/app-icon/LICENSE.txt" +kind = "icon" +usage = "Master artwork; every other app-icon file is rendered from it (packaging/icons.sh)" +sha256 = "52b384a10a2a7fdd3145d9822972cfd568ef0cb7312549bd4399addd89d45a6d" + +[[asset]] +path = "assets/app-icon/printcraft-small.svg" +title = "PrintCraft app icon (light vector)" +author = "PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)" +source = "Contributor-original (see assets/app-icon/README.md)" +licence = "MIT OR Apache-2.0" +licence_file = "assets/app-icon/LICENSE.txt" +kind = "icon" +usage = "README header and assets/app-icon/README.md" +sha256 = "b036304c11ef5dcad36636d06ca0bf331b51e47650d25d3c916a0e1eabf544c7" + +[[asset]] +path = "assets/app-icon/printcraft-1024.png" +title = "PrintCraft app icon, 1024 px on Apple's icon grid" +author = "PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)" +source = "Contributor-original (see assets/app-icon/README.md)" +licence = "MIT OR Apache-2.0" +licence_file = "assets/app-icon/LICENSE.txt" +kind = "icon" +usage = "Runtime window/Dock icon on macOS (apps/printcraft/src/main.rs)" +sha256 = "da577d3f21fbcf5c739067787a9e683be2b064d76813b5d5fec9074a7a106538" + +[[asset]] +path = "assets/app-icon/printcraft.icns" +title = "PrintCraft app icon (macOS .icns)" +author = "PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)" +source = "Contributor-original (see assets/app-icon/README.md)" +licence = "MIT OR Apache-2.0" +licence_file = "assets/app-icon/LICENSE.txt" +kind = "icon" +usage = "macOS app bundle icon" +sha256 = "2425148222873de241d267aba667a8b234ecdd0149f2ca8bb6e79443b743b1e8" + +[[asset]] +path = "assets/app-icon/printcraft.ico" +title = "PrintCraft app icon (Windows .ico, 16-256 px)" +author = "PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)" +source = "Contributor-original (see assets/app-icon/README.md)" +licence = "MIT OR Apache-2.0" +licence_file = "assets/app-icon/LICENSE.txt" +kind = "icon" +usage = "Embedded in printcraft.exe by apps/printcraft/build.rs (Explorer, taskbar, Start menu, Alt-Tab)" +sha256 = "56daaaae9ae5389794909570885809adf5e1d9183bef2d9669ed2f9bba3ed6f5" + +[[asset]] +path = "assets/app-icon/hicolor/16x16/apps/ai.storyteller.printcraft.png" +title = "PrintCraft app icon, 16 px" +author = "PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)" +source = "Contributor-original (see assets/app-icon/README.md)" +licence = "MIT OR Apache-2.0" +licence_file = "assets/app-icon/LICENSE.txt" +kind = "icon" +usage = "Linux hicolor theme icon (packaging/linux/ai.storyteller.printcraft.desktop)" +sha256 = "9b77095cbe75dcba6b74a1fdcd4064812850efaf7a12edebefc9ded5eabb49da" + +[[asset]] +path = "assets/app-icon/hicolor/24x24/apps/ai.storyteller.printcraft.png" +title = "PrintCraft app icon, 24 px" +author = "PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)" +source = "Contributor-original (see assets/app-icon/README.md)" +licence = "MIT OR Apache-2.0" +licence_file = "assets/app-icon/LICENSE.txt" +kind = "icon" +usage = "Linux hicolor theme icon (packaging/linux/ai.storyteller.printcraft.desktop)" +sha256 = "a4cd466687f6c5cb59eef3fc564bdba1c8f0d9e324754eeebab82f18823efae7" + +[[asset]] +path = "assets/app-icon/hicolor/32x32/apps/ai.storyteller.printcraft.png" +title = "PrintCraft app icon, 32 px" +author = "PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)" +source = "Contributor-original (see assets/app-icon/README.md)" +licence = "MIT OR Apache-2.0" +licence_file = "assets/app-icon/LICENSE.txt" +kind = "icon" +usage = "Linux hicolor theme icon (packaging/linux/ai.storyteller.printcraft.desktop)" +sha256 = "e22279013a5ed5c02571e1e4e9bc4cef9aa0847fcb733a285b2916fabd16bf78" + +[[asset]] +path = "assets/app-icon/hicolor/48x48/apps/ai.storyteller.printcraft.png" +title = "PrintCraft app icon, 48 px" +author = "PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)" +source = "Contributor-original (see assets/app-icon/README.md)" +licence = "MIT OR Apache-2.0" +licence_file = "assets/app-icon/LICENSE.txt" +kind = "icon" +usage = "Linux hicolor theme icon (packaging/linux/ai.storyteller.printcraft.desktop)" +sha256 = "55daf2d5575f6c4e4c4975c9f1c74231178f1801963a8b19f68dfa9bc50cb22f" + +[[asset]] +path = "assets/app-icon/hicolor/64x64/apps/ai.storyteller.printcraft.png" +title = "PrintCraft app icon, 64 px" +author = "PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)" +source = "Contributor-original (see assets/app-icon/README.md)" +licence = "MIT OR Apache-2.0" +licence_file = "assets/app-icon/LICENSE.txt" +kind = "icon" +usage = "Linux hicolor theme icon (packaging/linux/ai.storyteller.printcraft.desktop)" +sha256 = "2975c200f341e247b5fa18f568fb27d390e3fa01e9b2ad37acb48d0e1cc8a124" + +[[asset]] +path = "assets/app-icon/hicolor/128x128/apps/ai.storyteller.printcraft.png" +title = "PrintCraft app icon, 128 px" +author = "PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)" +source = "Contributor-original (see assets/app-icon/README.md)" +licence = "MIT OR Apache-2.0" +licence_file = "assets/app-icon/LICENSE.txt" +kind = "icon" +usage = "Linux hicolor theme icon (packaging/linux/ai.storyteller.printcraft.desktop)" +sha256 = "6ef927ca252b40bc9b5d8843d84137334362f8aa1acbb1bf8c15a02affd25b2b" + +[[asset]] +path = "assets/app-icon/hicolor/256x256/apps/ai.storyteller.printcraft.png" +title = "PrintCraft app icon, 256 px" +author = "PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)" +source = "Contributor-original (see assets/app-icon/README.md)" +licence = "MIT OR Apache-2.0" +licence_file = "assets/app-icon/LICENSE.txt" +kind = "icon" +usage = "Linux hicolor theme icon (packaging/linux/ai.storyteller.printcraft.desktop); runtime window icon on Windows and Linux (apps/printcraft/src/main.rs)" +sha256 = "cde7ee8c5ee38f9fc40a429fd9e6d99a035bcd321701fce331bb13bac126614d" + +[[asset]] +path = "assets/app-icon/hicolor/512x512/apps/ai.storyteller.printcraft.png" +title = "PrintCraft app icon, 512 px" +author = "PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)" +source = "Contributor-original (see assets/app-icon/README.md)" +licence = "MIT OR Apache-2.0" +licence_file = "assets/app-icon/LICENSE.txt" +kind = "icon" +usage = "Linux hicolor theme icon (packaging/linux/ai.storyteller.printcraft.desktop)" +sha256 = "5ede733e93b96f4eb8d94299232cf2f9605fa19b0d913f95fe9828c316a2d066" + +[[asset]] +path = "assets/app-icon/hicolor/scalable/apps/ai.storyteller.printcraft.svg" +title = "PrintCraft app icon (Linux scalable)" +author = "PrintCraft contributors (drawn by the project owner in ArtCraft; vectorised with craftrules vectorize_tile.py)" +source = "Contributor-original (see assets/app-icon/README.md)" +licence = "MIT OR Apache-2.0" +licence_file = "assets/app-icon/LICENSE.txt" +kind = "icon" +usage = "Linux hicolor theme icon (packaging/linux/ai.storyteller.printcraft.desktop)" +sha256 = "52b384a10a2a7fdd3145d9822972cfd568ef0cb7312549bd4399addd89d45a6d" + [[asset]] path = "docs/images/printcraft-bookmarks.png" title = "PrintCraft screenshot: Bookmarks" diff --git a/Cargo.lock b/Cargo.lock index 1d6d2d12..8f939d71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3342,6 +3342,7 @@ dependencies = [ "egui", "printcraft-ui-egui", "serde_json", + "winresource", ] [[package]] @@ -5729,6 +5730,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "winresource" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0986a8b1d586b7d3e4fe3d9ea39fb451ae22869dcea4aa109d287a374d866087" +dependencies = [ + "toml", + "version_check", +] + [[package]] name = "wit-bindgen" version = "0.57.1" diff --git a/README.md b/README.md index cd85eeb5..05e50bc1 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,10 @@
+
+
+
diff --git a/apps/printcraft/Cargo.toml b/apps/printcraft/Cargo.toml
index 8716b0a9..bbb31a76 100644
--- a/apps/printcraft/Cargo.toml
+++ b/apps/printcraft/Cargo.toml
@@ -13,3 +13,7 @@ printcraft-ui-egui = { workspace = true }
eframe = { workspace = true, features = ["default_fonts", "wgpu", "accesskit", "wayland", "x11", "persistence", "links"] }
egui = { workspace = true }
serde_json = { workspace = true }
+
+[build-dependencies]
+# Icon + VERSIONINFO for printcraft.exe; build.rs only uses it when targeting Windows.
+winresource = "0.1"
diff --git a/apps/printcraft/build.rs b/apps/printcraft/build.rs
new file mode 100644
index 00000000..638ee1de
--- /dev/null
+++ b/apps/printcraft/build.rs
@@ -0,0 +1,28 @@
+//! Windows only: embed the app icon and version info (VERSIONINFO) into `printcraft.exe`, so it
+//! shows in Explorer, the taskbar, the Start menu and Alt-Tab.
+//!
+//! On every other target this does nothing. A missing resource compiler is a warning, so a
+//! cross-compile from macOS or Linux still links, unless `PRINTCRAFT_REQUIRE_WINRES=1` turns it
+//! into an error (for release builds).
+
+fn main() {
+ println!("cargo:rerun-if-changed=build.rs");
+ println!("cargo:rerun-if-changed=../../assets/app-icon/printcraft.ico");
+ println!("cargo:rerun-if-env-changed=PRINTCRAFT_REQUIRE_WINRES");
+ if std::env::var("CARGO_CFG_TARGET_OS").as_deref() != Ok("windows") {
+ return;
+ }
+ let mut res = winresource::WindowsResource::new();
+ res.set_icon("../../assets/app-icon/printcraft.ico")
+ .set("ProductName", "PrintCraft")
+ .set("FileDescription", "PrintCraft PDF workbench")
+ .set("LegalCopyright", "Copyright (c) the PrintCraft contributors. MIT OR Apache-2.0.")
+ .set("OriginalFilename", "printcraft.exe")
+ .set("InternalName", "printcraft");
+ if let Err(e) = res.compile() {
+ if std::env::var_os("PRINTCRAFT_REQUIRE_WINRES").is_some() {
+ panic!("embedding Windows resources failed: {e}");
+ }
+ println!("cargo:warning=printcraft.exe built without icon/version resources: {e}");
+ }
+}
diff --git a/apps/printcraft/src/main.rs b/apps/printcraft/src/main.rs
index 29816242..6000d46e 100644
--- a/apps/printcraft/src/main.rs
+++ b/apps/printcraft/src/main.rs
@@ -13,6 +13,16 @@
use printcraft_ui_egui::PrintCraftApp;
+/// Freedesktop app id: the `.desktop` file name and the hicolor icon name.
+const APP_ID: &str = "ai.storyteller.printcraft";
+
+/// The app icon (assets/app-icon/README.md). macOS gets the version on Apple's icon grid, with a
+/// transparent margin; Windows and Linux get the full-bleed tile.
+#[cfg(target_os = "macos")]
+const APP_ICON_PNG: &[u8] = include_bytes!("../../../assets/app-icon/printcraft-1024.png");
+#[cfg(not(target_os = "macos"))]
+const APP_ICON_PNG: &[u8] = include_bytes!("../../../assets/app-icon/hicolor/256x256/apps/ai.storyteller.printcraft.png");
+
fn main() -> eframe::Result {
let mut files = Vec::new();
let mut options: Vec<(String, String)> = Vec::new();
@@ -37,11 +47,20 @@ fn main() -> eframe::Result {
.with_title("PrintCraft")
.with_inner_size([1440.0, 920.0])
.with_min_inner_size([820.0, 520.0])
- .with_drag_and_drop(true);
+ .with_drag_and_drop(true)
+ // Wayland app id: matches packaging/linux/ai.storyteller.printcraft.desktop.
+ .with_app_id(APP_ID);
+ // Dock, taskbar, Alt-Tab and launcher icon when running unbundled.
+ match eframe::icon_data::from_png_bytes(APP_ICON_PNG) {
+ Ok(icon) => viewport = viewport.with_icon(icon),
+ Err(e) => eprintln!("printcraft: app icon: {e}"),
+ }
if integrated {
viewport = viewport.with_fullsize_content_view(true).with_titlebar_shown(false).with_title_shown(false);
}
- let native = eframe::NativeOptions { viewport, ..Default::default() };
+ // eframe would otherwise derive the settings folder from the app id: keep it under "PrintCraft".
+ let persistence_path = eframe::storage_dir("PrintCraft").map(|d| d.join("app.ron"));
+ let native = eframe::NativeOptions { viewport, persistence_path, ..Default::default() };
eframe::run_native(
"PrintCraft",
native,
diff --git a/assets/app-icon/LICENSE.txt b/assets/app-icon/LICENSE.txt
new file mode 100644
index 00000000..d472892a
--- /dev/null
+++ b/assets/app-icon/LICENSE.txt
@@ -0,0 +1,12 @@
+PrintCraft app icon (printcraft.svg, printcraft-small.svg and every file derived from them in this
+directory: printcraft-1024.png, printcraft.icns, printcraft.ico, hicolor/).
+
+Original artwork made for this project by the project owner, drawn in ArtCraft and vectorised for
+PrintCraft (no third-party material). Licensed like the rest of PrintCraft, under either of
+
+ * Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license (https://opensource.org/licenses/MIT)
+
+at your option.
+
+Regenerate the derived files with packaging/icons.sh.
diff --git a/assets/app-icon/README.md b/assets/app-icon/README.md
new file mode 100644
index 00000000..208effe0
--- /dev/null
+++ b/assets/app-icon/README.md
@@ -0,0 +1,48 @@
+# PrintCraft app icon
+
+
+
+**Creature:** a lion, in a frontal head-and-shoulders portrait, mane running off the bottom of the tile.
+
+**Style:** an engraving (woodcut-weight line work) portrait in the Crafting Apps "owl template" framing:
+a full-bleed colour field, no frame or roundel, the animal looking at the viewer and filling the tile.
+
+**Palette:** exactly three colours.
+
+| Colour | Hex | Used for |
+|---|---|---|
+| Ink | `#0b0b0c` | line work and the figure's contour |
+| Paper | `#efe9dc` | the figure (the lion's silhouette) |
+| PrintCraft green (app colour) | `#12a58a` | the full-bleed field |
+
+**Tile:** `viewBox="0 0 512 512"`, a rounded square with `rx=112` that clips everything. Windows and Linux
+icons use the full-bleed tile. macOS icons put it on Apple's grid (an 824 px body centred on a transparent
+1024 px canvas).
+
+**Provenance:** the project owner's original drawing, made in ArtCraft (2880 px, keyed to the palette), then
+vectorised with craftrules `assets/logo-options/_tools/vectorize_tile.py` (potrace; no filtering or
+warping). The source drawing is kept in craftrules at `assets/app-icons/printcraft/source.png`, not here.
+Licence: [LICENSE.txt](LICENSE.txt) (`MIT OR Apache-2.0`, like the repo).
+
+## Files
+
+| File | What it is |
+|---|---|
+| `printcraft.svg` | the master vector (traced at 2048 px); every PNG, `.ico` and `.icns` is rendered from it |
+| `printcraft-small.svg` | a lighter vector (traced at 1024 px) for places where size matters, such as this README |
+| `printcraft-1024.png` | 1024 px on Apple's grid; also the runtime Dock icon on macOS |
+| `printcraft.icns` | macOS icon (16โ1024 px) |
+| `printcraft.ico` | Windows icon (16โ256 px), embedded in `printcraft.exe` by `apps/printcraft/build.rs` |
+| `hicolor/