App icon: the chameleon, vectorised like the other Crafting Apps (#156)

The owner's engraving-style chameleon drawing, traced to three colours (ink, paper,
FigCraft green #02da96) on the shared 512-unit tile. assets/app-icon/figcraft.svg is the
master; cargo xtask icon now renders the PNGs (macOS grid), the hicolor theme and the .ico
(tight crop, 16-256 px) from it with resvg instead of drawing the old geometric mark.
Off macOS the window icon uses the tight 256 px render.
This commit is contained in:
BFlat authored and GitHub committed 2026-10-12 14:25:29 +07:00
1 parent ab94cff913
commit a0d1e72c8d
29 files changed
+111 -106

No files matched your search

+2 -1
View File
@@ -46,7 +46,8 @@ code.
`assets/`, `docs/brand/` or `docs/images/`.
- FigCraft's UI icons are drawn in code (`crates/ui-egui/src/icons.rs`) from simple primitives and
are original. Keep it that way: new icons are new code, designed from scratch.
- The app icon is generated in code (`cargo xtask icon`, `xtask/src/icon.rs`).
- The app icon is the owner's chameleon drawing, vectorised (`assets/app-icon/README.md`); `cargo xtask icon`
renders the PNGs and `.ico` from `assets/app-icon/figcraft.svg`.
- **Fonts live in [storytold/craft-fonts](https://github.com/storytold/craft-fonts), never in this
repo.** The app uses it only through the optional `CRAFT_FONTS_DIR` build input
(`.cargo/config.toml` points it at `../craft-fonts` for local builds; `crates/text/build.rs`
+1 -1
View File
@@ -11,7 +11,7 @@ MIT OR Apache-2.0. No third-party icon sets are used.
| Path | Author | Source | Licence | Notes |
|---|---|---|---|---|
| `assets/app-icon/` (all files: `figcraft-*.png`, `figcraft.ico`, `hicolor/*/apps/ai.storyteller.figcraft.png`) | FigCraft contributors | Generated by `cargo xtask icon` (`xtask/src/icon.rs`) with FigCraft's own renderer | MIT OR Apache-2.0 | Original geometric mark (stacked layer cards and a cursor) |
| `assets/app-icon/` (all files: `figcraft.svg`, `figcraft-small.svg`, `figcraft-*.png`, `figcraft.ico`, `hicolor/`) | The project owner (engraving-style drawing, vectorised) | Original work, see [`assets/app-icon/README.md`](assets/app-icon/README.md); derived files rendered by `cargo xtask icon` | MIT OR Apache-2.0, [`assets/app-icon/LICENSE.txt`](assets/app-icon/LICENSE.txt) | FigCraft app icon (chameleon) |
| `docs/brand/artcraft-logo.svg`, `docs/brand/artcraft-logo.png`, `docs/brand/artcraft-logo-white.svg`, `docs/brand/artcraft-logo-white.png`, `docs/brand/artcraft-mark.svg`, `docs/brand/artcraft-mark.png`, `docs/brand/artcraft-mark-black.svg`, `docs/brand/artcraft-mark-black.png` | ArtCraft Team | storytold/craftrules `assets/brand/` | ArtCraft brand terms (`docs/brand/LICENSE-brand.txt`), not open source | Trademarks; unmodified use within FigCraft only |
| `docs/images/` (all screenshots and exports: `shot-*.png`, `art-*.png`) | FigCraft contributors | Screenshots of FigCraft showing synthetic demo documents made in FigCraft, and PNG exports of those documents by FigCraft's renderer | MIT OR Apache-2.0 | No third-party artwork |
| `examples/*.figcraft` | FigCraft contributors | Synthetic demo documents built through FigCraft's command API; invented copy, shapes and vectors drawn from scratch, no images or embedded fonts | MIT OR Apache-2.0 | Text uses Inter (OFL, from craft-fonts or the system); no third-party artwork |
+2 -1
View File
@@ -46,7 +46,8 @@ code.
`assets/`, `docs/brand/` or `docs/images/`.
- FigCraft's UI icons are drawn in code (`crates/ui-egui/src/icons.rs`) from simple primitives and
are original. Keep it that way: new icons are new code, designed from scratch.
- The app icon is generated in code (`cargo xtask icon`, `xtask/src/icon.rs`).
- The app icon is the owner's chameleon drawing, vectorised (`assets/app-icon/README.md`); `cargo xtask icon`
renders the PNGs and `.ico` from `assets/app-icon/figcraft.svg`.
- **Fonts live in [storytold/craft-fonts](https://github.com/storytold/craft-fonts), never in this
repo.** The app uses it only through the optional `CRAFT_FONTS_DIR` build input
(`.cargo/config.toml` points it at `../craft-fonts` for local builds; `crates/text/build.rs`
Generated
-5
View File
@@ -5805,12 +5805,7 @@ checksum = "9440ea3e5aeabb0ac63af70daf835274065238cdd0cec83418f417eae38bacee"
name = "xtask"
version = "0.4.0"
dependencies = [
"figcraft-color",
"figcraft-doc",
"figcraft-engine",
"figcraft-render",
"figcraft-svg",
"image",
"serde_json",
]
+4
View File
@@ -210,7 +210,11 @@ impl Services for Desktop {
/// The window icon from the bundled app icon (if present).
pub fn window_icon() -> Option<egui::IconData> {
// macOS wants Apple's padded grid; the other platforms the tile edge to edge.
#[cfg(target_os = "macos")]
let bytes = include_bytes!("../../../assets/app-icon/figcraft-256.png");
#[cfg(not(target_os = "macos"))]
let bytes = include_bytes!("../../../assets/app-icon/hicolor/256x256/apps/ai.storyteller.figcraft.png");
let img = image::load_from_memory(bytes).ok()?.to_rgba8();
let (w, h) = img.dimensions();
Some(egui::IconData { rgba: img.into_raw(), width: w, height: h })
+12
View File
@@ -0,0 +1,12 @@
FigCraft app icon (figcraft.svg, figcraft-small.svg and every file derived from them in this
directory: figcraft-<size>.png, figcraft.ico, hicolor/).
Original artwork made for this project by the project owner: an engraving-style drawing, then
vectorised. No third-party material. Licensed like the rest of FigCraft, 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 `cargo xtask icon`.
+41
View File
@@ -0,0 +1,41 @@
# FigCraft app icon
A **chameleon**: an engraving portrait in profile with a curled tail, in the Crafting Apps'
owl-template framing (full-bleed field, head and body filling the tile, body running off the edges).
## Palette
Exactly three colours:
| Colour | Hex | Used for |
|---|---|---|
| Ink | `#0b0b0c` | line work and contours |
| Paper | `#efe9dc` | the figure |
| FigCraft green (app colour) | `#02da96` | 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 engraving-style drawing (1500 px, keyed to the palette), supplied for
FigCraft and vectorised with craftrules `assets/logo-options/_tools/vectorize_tile.py`. The source
image is not kept in this repo. License: see `LICENSE.txt`.
## Files
- `figcraft.svg`: canonical master (traced at 1500 px, the source's size).
- `figcraft-small.svg`: lighter trace (traced at 1024 px); also the hicolor scalable icon.
- `figcraft-<size>.png` (16–1024): renders on the macOS grid; `packaging/macos/package.sh` builds
the `.icns` from them.
- `figcraft.ico`: Windows icon, 16–256 px, embedded in the `.exe` by `apps/figcraft/build.rs`.
- `hicolor/<size>/apps/ai.storyteller.figcraft.png` (16–512) and `hicolor/scalable/...svg`:
Linux icon theme; the 256 px one is also the runtime window icon off macOS.
## Regenerate
Replace `figcraft.svg` (and `figcraft-small.svg`), then run `cargo xtask icon`. It needs `resvg`
(`cargo install resvg`).
Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 345 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 559 B

After

Width:  |  Height:  |  Size: 678 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><clipPath id="t"><rect width="512" height="512" rx="112"/></clipPath></defs><g clip-path="url(#t)"><rect width="512" height="512" fill="#02da96"/><path fill="#efe9dc" fill-rule="evenodd" d="M131 505C104 505 99 505 95 504C78 501 62 495 58 490C57 489 55 487 54 486C51 482 46 475 43 468C41 465 39 462 39 461C33 451 25 429 23 416C16 373 25 338 50 313C54 309 63 303 64 303C64 303 65 302 67 300C69 299 71 298 71 298C71 298 73 298 75 297C122 275 177 307 177 357C177 380 168 398 150 410C139 417 122 421 110 418C94 415 84 409 76 396C57 364 82 324 116 331C144 337 149 373 124 386C118 389 107 386 102 381C95 374 98 358 107 357C112 357 114 360 111 364C108 368 110 372 115 372C122 372 125 359 118 354C110 347 97 353 94 365C90 383 110 397 128 388C159 372 145 326 109 326C72 326 52 368 68 413C74 430 90 454 101 464C102 464 105 466 106 468C114 476 130 486 145 493C145 493 147 494 148 495C150 496 154 497 162 500C164 501 176 504 177 504C177 504 177 505 177 505C177 506 174 506 131 505ZM256 505C253 503 249 472 248 446C248 434 248 428 247 422C244 404 246 398 256 386C265 376 271 374 284 375C297 376 307 378 311 379C318 380 318 380 318 378C319 377 317 372 312 363C309 355 305 346 300 330C296 319 295 317 293 317C291 316 290 315 288 312C287 310 287 309 286 310C284 311 283 310 282 308C280 305 280 305 279 306C278 308 275 306 273 302C272 300 271 300 270 303C269 307 266 305 262 299C260 296 259 295 259 299C259 304 253 302 249 295C247 291 246 292 246 297C245 303 241 301 236 292C233 288 232 289 232 295C232 301 226 298 221 288C219 284 218 284 218 289C217 295 215 296 212 293C210 291 207 285 206 282C205 279 203 281 203 286C202 292 196 288 193 279C192 276 191 275 190 279C189 282 188 284 187 284C185 284 180 276 179 270C179 266 178 266 176 270C172 278 172 278 170 276C168 274 167 271 166 266C166 263 165 262 164 264C162 267 160 270 159 270C157 270 155 264 154 258C154 254 153 254 151 258C147 264 145 263 144 254C144 248 143 248 141 251C137 256 135 254 135 245C134 241 134 241 132 243C130 246 128 244 128 240L128 238 126 238C124 238 124 237 124 232L123 228 119 224C112 218 108 214 106 210C105 208 104 206 103 205C100 200 97 193 97 189C97 187 96 185 96 183C96 180 97 174 100 171C104 166 106 163 106 161C106 157 106 155 108 153C109 152 110 150 110 150C110 148 112 144 115 141C116 140 117 138 117 137C118 136 119 134 120 133C121 132 122 130 123 128C124 127 127 123 130 121C134 116 135 116 138 108C144 97 150 88 156 84C160 81 168 76 169 76C169 76 170 76 171 75C175 73 185 73 192 74C193 75 196 75 198 76C200 76 204 77 206 78L210 78 215 76C218 75 222 74 225 74C228 73 229 72 230 71C231 71 232 70 233 70C233 70 235 69 235 68C236 67 238 65 240 64C241 63 244 61 245 60C246 59 248 57 249 57C250 57 252 55 254 54C257 52 260 50 262 50C262 50 264 49 266 48C268 46 270 45 272 45C274 45 276 44 278 42C281 41 283 40 286 39C289 39 290 38 297 36C298 35 301 35 302 35C304 35 306 34 308 33C312 32 313 32 320 31C325 31 329 31 330 31C332 30 357 31 359 31C359 31 362 32 364 32C381 34 389 47 384 61C380 71 378 80 378 92L377 101 379 102C382 103 394 102 399 100C400 99 403 96 406 94C412 88 414 87 415 92C415 95 416 95 419 91C427 82 429 82 430 89C430 93 430 93 434 89C442 82 449 79 448 84C447 92 447 93 450 90C453 86 461 82 465 82C469 81 469 82 468 87C466 95 466 95 470 92C480 85 490 85 487 91C485 96 486 97 490 94C494 92 499 91 502 92C503 93 503 93 502 97C501 100 501 101 503 100C504 100 504 100 505 100C506 101 507 397 505 407C504 420 499 438 496 444C496 444 494 447 493 450C484 468 466 485 446 495C439 498 436 499 428 502C417 505 407 506 381 506C360 506 358 506 360 504C361 504 361 503 362 502C363 495 370 486 378 482C382 479 382 479 376 477C374 476 370 475 368 474C365 473 362 472 362 472C361 473 356 492 353 500C353 503 352 505 352 506C351 506 257 506 256 505ZM309 496C311 490 311 487 312 470C312 451 313 453 306 449C300 446 300 446 302 455C305 466 306 474 306 489C306 502 307 503 309 496ZM390 399C390 399 388 396 386 393C384 390 381 385 379 381C374 374 366 364 366 365C365 366 367 374 368 378C369 380 370 385 371 387C372 394 371 393 381 397C389 400 391 400 390 399Z"/><path fill="#0b0b0c" fill-rule="evenodd" d="M123 504C121 502 120 502 120 504C120 505 119 506 119 506C118 506 118 505 119 503C120 502 118 500 117 500C117 500 116 500 116 500C116 499 117 499 119 500C120 501 120 501 122 498C123 497 123 496 123 496C124 496 124 495 124 495C124 494 126 491 128 490C129 489 129 489 129 490C128 491 131 495 132 493C134 492 134 492 133 494C132 494 132 495 134 496C135 497 134 497 133 496C132 495 131 495 130 498C130 498 129 499 129 498C129 498 129 497 130 496L131 495 129 493L127 492 126 493C124 495 124 496 126 496C127 497 128 497 128 498C128 498 128 499 127 498C124 497 124 497 122 499L121 501 123 502C125 504 126 504 127 502C127 500 128 500 128 500C129 500 127 505 126 506C125 506 124 505 123 504ZM144 505C145 503 145 503 143 502C141 501 139 503 140 505C140 506 138 506 138 505C138 505 137 504 136 504C133 502 134 502 137 503C138 504 141 502 141 500C141 499 143 497 144 497C144 49Line truncated

After

Width:  |  Height:  |  Size: 453 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 106 KiB

+1 -1
View File
@@ -1 +1 @@
<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg"><g><path transform="matrix(1 0 0 1 0 0)" d="M179.2 0L332.8 0C395.526 0 426.889 0 450.847 12.207C471.921 22.945 489.055 40.079 499.793 61.153C512 85.111 512 116.474 512 179.2L512 332.8C512 395.526 512 426.889 499.793 450.847C489.055 471.921 471.921 489.055 450.847 499.793C426.889 512 395.526 512 332.8 512L179.2 512C116.474 512 85.111 512 61.153 499.793C40.079 489.055 22.945 471.921 12.207 450.847C0 426.889 0 395.526 0 332.8L0 179.2C0 116.474 0 85.111 12.207 61.153C22.945 40.079 40.079 22.945 61.153 12.207C85.111 0 116.474 0 179.2 0Z" fill="#0EA5C6"/></g><g><path transform="matrix(1 0 0 1 150 96)" d="M44.8 0L205.2 0C220.881 0 228.722 0 234.712 3.052C239.98 5.736 244.264 10.02 246.948 15.288C250 21.278 250 29.119 250 44.8L250 155.2C250 170.881 250 178.722 246.948 184.712C244.264 189.98 239.98 194.264 234.712 196.948C228.722 200 220.881 200 205.2 200L44.8 200C29.119 200 21.278 200 15.288 196.948C10.02 194.264 5.736 189.98 3.052 184.712C0 178.722 0 170.881 0 155.2L0 44.8C0 29.119 0 21.278 3.052 15.288C5.736 10.02 10.02 5.736 15.288 3.052C21.278 0 29.119 0 44.8 0Z" fill="#EFE9DC"/><path transform="matrix(1 0 0 1 150 96)" d="M15.288 3.052C21.278 0 29.119 0 44.8 0L205.2 0C220.881 0 228.722 0 234.712 3.052C239.98 5.736 244.264 10.02 246.948 15.288C250 21.278 250 29.119 250 44.8L250 155.2C250 170.881 250 178.722 246.948 184.712C244.264 189.98 239.98 194.264 234.712 196.948C228.722 200 220.881 200 205.2 200L44.8 200C29.119 200 21.278 200 15.288 196.948C10.02 194.264 5.736 189.98 3.052 184.712C0 178.722 0 170.881 0 155.2L0 44.8C0 29.119 0 21.278 3.052 15.288C5.736 10.02 10.02 5.736 15.288 3.052ZM44.8 14C32.619 14 24.619 14.01 21.644 15.526C19.01 16.868 16.868 19.01 15.526 21.644C14.01 24.619 14 32.619 14 44.8L14 155.2C14 167.381 14.01 175.381 15.526 178.356C16.868 180.99 19.01 183.132 21.644 184.474C24.619 185.99 32.619 186 44.8 186L205.2 186C217.381 186 225.381 185.99 228.356 184.474C230.99 183.132 233.132 180.99 234.474 178.356C235.99 175.381 236 167.381 236 155.2L236 44.8C236 32.619 235.99 24.619 234.474 21.644C233.132 19.01 230.99 16.868 228.356 15.526C225.381 14.01 217.381 14 205.2 14L44.8 14Z" fill="#0B0B0C" fill-rule="evenodd"/></g><g><path transform="matrix(1 0 0 1 122 150)" d="M44.8 0L205.2 0C220.881 0 228.722 0 234.712 3.052C239.98 5.736 244.264 10.02 246.948 15.288C250 21.278 250 29.119 250 44.8L250 155.2C250 170.881 250 178.722 246.948 184.712C244.264 189.98 239.98 194.264 234.712 196.948C228.722 200 220.881 200 205.2 200L44.8 200C29.119 200 21.278 200 15.288 196.948C10.02 194.264 5.736 189.98 3.052 184.712C0 178.722 0 170.881 0 155.2L0 44.8C0 29.119 0 21.278 3.052 15.288C5.736 10.02 10.02 5.736 15.288 3.052C21.278 0 29.119 0 44.8 0Z" fill="#EFE9DC"/><path transform="matrix(1 0 0 1 122 150)" d="M15.288 3.052C21.278 0 29.119 0 44.8 0L205.2 0C220.881 0 228.722 0 234.712 3.052C239.98 5.736 244.264 10.02 246.948 15.288C250 21.278 250 29.119 250 44.8L250 155.2C250 170.881 250 178.722 246.948 184.712C244.264 189.98 239.98 194.264 234.712 196.948C228.722 200 220.881 200 205.2 200L44.8 200C29.119 200 21.278 200 15.288 196.948C10.02 194.264 5.736 189.98 3.052 184.712C0 178.722 0 170.881 0 155.2L0 44.8C0 29.119 0 21.278 3.052 15.288C5.736 10.02 10.02 5.736 15.288 3.052ZM44.8 14C32.619 14 24.619 14.01 21.644 15.526C19.01 16.868 16.868 19.01 15.526 21.644C14.01 24.619 14 32.619 14 44.8L14 155.2C14 167.381 14.01 175.381 15.526 178.356C16.868 180.99 19.01 183.132 21.644 184.474C24.619 185.99 32.619 186 44.8 186L205.2 186C217.381 186 225.381 185.99 228.356 184.474C230.99 183.132 233.132 180.99 234.474 178.356C235.99 175.381 236 167.381 236 155.2L236 44.8C236 32.619 235.99 24.619 234.474 21.644C233.132 19.01 230.99 16.868 228.356 15.526C225.381 14.01 217.381 14 205.2 14L44.8 14Z" fill="#0B0B0C" fill-rule="evenodd"/></g><g><path transform="matrix(1 0 0 1 94 204)" d="M44.8 0L205.2 0C220.881 0 228.722 0 234.712 3.052C239.98 5.736 244.264 10.02 246.948 15.288C250 21.278 250 29.119 250 44.8L250 155.2C250 170.881 250 178.722 246.948 184.712C244.264 189.98 239.98 194.264 234.712 196.948C228.722 200 220.881 200 205.2 200L44.8 200C29.119 200 21.278 200 15.288 196.948C10.02 194.264 5.736 189.98 3.052 184.712C0 178.722 0 170.881 0 155.2L0 44.8C0 29.119 0 21.278 3.052 15.288C5.736 10.02 10.02 5.736 15.288 3.052C21.278 0 29.119 0 44.8 0Z" fill="#EFE9DC"/><path transform="matrix(1 0 0 1 94 204)" d="M15.288 3.052C21.278 0 29.119 0 44.8 0L205.2 0C220.881 0 228.722 0 234.712 3.052C239.98 5.736 244.264 10.02 246.948 15.288C250 21.278 250 29.119 250 44.8L250 155.2C250 170.881 250 178.722 246.948 184.712C244.264 189.98 239.98 194.264 234.712 196.948C228.722 200 220.881 200 205.2 200L44.8 200C29.119 200 21.278 200 15.288 196.948C10.02 194.264 5.736 189.98 3.052 184.712C0 178.722 0 170.881 0 155.2L0 44.8C0 29.119 0 21.278 3.052 15.288C5.736 10.02 10.02 5.736 15.288 3.052ZM44.8 14C32.619 14 24.619 14.01 21.644 15.526C19.01 16.868 16.868 19.01 15.5Line truncated
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><clipPath id="t"><rect width="512" height="512" rx="112"/></clipPath></defs><g clip-path="url(#t)"><rect width="512" height="512" fill="#02da96"/><path fill="#efe9dc" fill-rule="evenodd" d="M105.6 505.5C99.1 505 89.7 503.4 83.5 501.6C80 500.6 73.9 498.6 73.6 498.4C73.4 498.2 72.4 497.8 71.4 497.5C68.8 496.7 61.6 493.2 59.8 491.9C59 491.3 57.8 490.1 57.2 489.2C56.6 488.3 55.4 486.8 54.6 485.9C52.1 483.2 47.4 476.4 44.9 471.9C43.6 469.7 41.5 465.9 40.2 463.6C19 426.3 14.4 381.3 28.1 346.2C33.1 333.6 39.6 323.6 49.1 314C54.4 308.7 57.7 306.1 64 302.4C84.1 290.3 101.6 287.3 124.1 292.1C146.3 296.8 164.7 312.7 173.3 334.6C176.6 343 177.5 348.8 177.1 359.9C176.7 370.9 175.4 376.8 171.4 385.2C163.2 402.3 149.5 413.1 129.5 418.2C124.7 419.4 113.8 419.3 107.9 418C91.3 414.3 81.2 406.5 73.9 391.7C69.7 383.2 68.4 374.5 70 365.5C72.3 352 79.3 341.5 90.5 334.7C98.3 330.1 111 329 120.2 332.3C128 335.1 135.5 342.2 138 349C141.6 359.2 140.7 368.8 135.2 376.9C133.1 379.9 132.8 380.2 128.7 383.1C124 386.2 122.2 386.8 117.8 386.8C107 386.9 98.9 381 98.1 372.7C97.6 367.4 99 362.1 101.6 359.7C104.3 357 107.5 356.1 110.2 357.4C113 358.6 113.3 361.4 111.1 364.3C108.4 367.7 109.5 370.6 113.8 371.7C118 372.9 121.9 368.5 122 362.8C122.1 356.6 117.4 351.6 110.6 350.7C106.1 350.1 99.5 353.8 96.4 358.7C93.8 362.9 92.8 370.9 94.3 375.5C96.8 382.8 102 387.6 110.1 390C113.4 391 120.6 390.9 123.7 389.8C137.4 385.2 146.2 371.9 144.7 358.2C143.7 348.3 139.2 339.3 132.8 334.1C118 322.1 96.3 323 80.9 336.3C60.3 354.2 56.7 387.8 71.7 421.6C74.8 428.5 76.8 432.3 79.2 435.9C79.9 436.9 81.5 439.3 82.7 441.2C93.2 457.3 109.3 472.5 128.1 484C131.3 486 141.8 491.4 143.7 492C144.5 492.3 146 493.1 146.9 493.7C149.7 495.6 161.4 500.2 167.3 501.8C168.9 502.2 171.2 502.8 172.4 503.3C173.6 503.7 175.7 504.3 177.1 504.6C178.4 505 179.5 505.4 179.5 505.6C179.5 505.9 111.2 505.8 105.6 505.5ZM255.2 505.6C254.8 504.9 252.8 493.7 251.6 485.4C249.4 470.1 248.7 460.4 248.3 440.8C248.1 431.2 247.6 425.4 246.1 416.3C244 403.7 246.6 396.6 257.8 383.9C263.5 377.5 269.7 374.4 277.2 374.4C279.1 374.4 281.3 374.6 282 374.8C282.8 375 285.4 375.3 287.7 375.4C296.8 376.1 309.3 377.9 314.4 379.2C318.5 380.3 318.9 380.2 318.6 378.5C318.3 376.5 317.6 374.5 316.2 371.2C315 368.7 314.3 367.2 310.4 358.8C308.1 354.1 305 345.4 300.9 332.8C298.9 326.7 296.7 320.6 296 319.1C294.7 316.6 294.7 316.6 293.3 316.6C291.2 316.6 289.8 315.3 288.4 312.2C287.2 309.5 286.8 309.2 285.5 310.1C284 311.3 282.4 310.2 281.2 307.3C280.2 304.6 280.1 304.5 278.9 305.8C277.7 307.1 277.8 307 276.1 306.2C274.8 305.5 274 304.5 272.3 301.4C271.6 300.1 270.9 300.4 270.5 302.3C270.1 304.4 269.8 304.8 268.3 304.8C266.7 304.8 264.1 302.2 261.8 298.4C259.9 295.1 259.1 295.2 259.1 298.9C259.1 302.1 257.9 303 255.5 301.6C253.1 300.2 250.7 297.8 249 295.1C246.6 291.5 245.8 291.8 245.8 296.2C245.8 303.1 241.1 301.2 235.7 292.2C234.7 290.6 233.7 289.3 233.5 289.2C232.9 289 232.5 290.6 232.2 293.8C231.9 298.3 230.6 299.3 227.8 297.4C225.7 295.8 223.8 293.3 221.5 289C220.4 286.8 219.2 285 219 285C218.5 285 217.8 287.6 217.4 290.9C216.6 298.5 210.1 293.7 206.3 282.7C205.8 281.2 205.2 279.9 204.9 279.9C204.4 279.9 203.1 283.1 202.9 285.2C202.3 290.5 200.8 291 197.3 286.9C195.4 284.7 193.6 281.3 192.7 277.9C191.9 275.3 191.2 275.2 190.5 277.7C189.7 280.8 188.3 284 187.9 284.2C185.3 285.2 180 276.8 179.2 270.3C178.6 265.7 177.5 266.1 175.3 271.8C173.9 275.3 172.9 277.1 172.2 277.4C171.2 277.7 169.3 276.1 168.3 274.1C167.2 271.9 165.6 265.2 165.5 262.7C165.5 261.7 164.2 263.1 162.7 265.5C161.7 267.1 160.5 268.7 160 269.1L159.1 269.8 158.2 268.9C155.9 266.9 154.6 263.2 154.1 257.8C154 256.2 153.7 254.9 153.6 254.8C153.2 254.6 152.3 255.7 150.4 258.7C148.3 261.8 147.8 262.2 146.5 261.5C145 260.6 144.4 259 144 253.9C143.5 247.3 143.6 247.3 140.8 251.1L138.8 253.7 137.4 253.4C136.6 253.3 135.9 253.1 135.8 253C135.1 252.3 134.7 249.8 134.6 246C134.5 240.9 134.3 240.4 132.9 242.2C130.3 245.8 128.5 245.1 127.9 240.4C127.4 236.7 127.5 236.8 126.3 237.5C124.6 238.5 123.9 237.5 123.5 233.1C123.1 228.5 122.7 227.9 119.9 225.4C111.9 218.5 108.2 214.4 105.7 209.6C104.6 207.4 103 204.6 102.2 203.4C101.4 202.1 100.7 201 100.7 200.9C100.7 200.8 99.8 199 98.8 196.7L96.8 192.7 96.8 189.3C96.8 187.3 96.6 185.5 96.3 185.1C95.6 183.8 95.8 180.3 96.9 177.1C98.1 173.5 98.4 173 100.4 170.5C104.4 165.3 105 164.2 105.3 161.1C105.6 157.1 106.3 155 107.5 153.8C109.1 152.3 109.8 151 110.2 148.8C110.7 146.3 112.5 143.4 115.1 140.7C116.2 139.6 117.1 138.4 117.1 138.1C117.1 137.2 119 133.7 120 132.8C120.5 132.3 121.4 131 122.1 129.9C124 126.7 126.9 123.4 130.3 120.3C133.6 117.4 134.4 116.2 136.7 111.3C137.4 109.9 138.1 108.4 138.3 108C139 106.8 139.2 106.3 140.3 104.1C142.2 99.9 148.2 91.5 152.3 87.2C155.5 83.8 158 81.9 162 79.6C163.3 78.9 165 77.8 165.8 77.3C166.7 76.6 167.8 76.1 168.8 76C169.7 75.9 170.9 75.5 171.5 75.1C174.3 73.4 185.1 72.8 190.9 74.1C192.6 74.4 195.8 75.1 198 75.6C20Line truncated

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 559 B

After

Width:  |  Height:  |  Size: 779 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

@@ -1 +1 @@
<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg"><g><path transform="matrix(1 0 0 1 0 0)" d="M179.2 0L332.8 0C395.526 0 426.889 0 450.847 12.207C471.921 22.945 489.055 40.079 499.793 61.153C512 85.111 512 116.474 512 179.2L512 332.8C512 395.526 512 426.889 499.793 450.847C489.055 471.921 471.921 489.055 450.847 499.793C426.889 512 395.526 512 332.8 512L179.2 512C116.474 512 85.111 512 61.153 499.793C40.079 489.055 22.945 471.921 12.207 450.847C0 426.889 0 395.526 0 332.8L0 179.2C0 116.474 0 85.111 12.207 61.153C22.945 40.079 40.079 22.945 61.153 12.207C85.111 0 116.474 0 179.2 0Z" fill="#0EA5C6"/></g><g><path transform="matrix(1 0 0 1 150 96)" d="M44.8 0L205.2 0C220.881 0 228.722 0 234.712 3.052C239.98 5.736 244.264 10.02 246.948 15.288C250 21.278 250 29.119 250 44.8L250 155.2C250 170.881 250 178.722 246.948 184.712C244.264 189.98 239.98 194.264 234.712 196.948C228.722 200 220.881 200 205.2 200L44.8 200C29.119 200 21.278 200 15.288 196.948C10.02 194.264 5.736 189.98 3.052 184.712C0 178.722 0 170.881 0 155.2L0 44.8C0 29.119 0 21.278 3.052 15.288C5.736 10.02 10.02 5.736 15.288 3.052C21.278 0 29.119 0 44.8 0Z" fill="#EFE9DC"/><path transform="matrix(1 0 0 1 150 96)" d="M15.288 3.052C21.278 0 29.119 0 44.8 0L205.2 0C220.881 0 228.722 0 234.712 3.052C239.98 5.736 244.264 10.02 246.948 15.288C250 21.278 250 29.119 250 44.8L250 155.2C250 170.881 250 178.722 246.948 184.712C244.264 189.98 239.98 194.264 234.712 196.948C228.722 200 220.881 200 205.2 200L44.8 200C29.119 200 21.278 200 15.288 196.948C10.02 194.264 5.736 189.98 3.052 184.712C0 178.722 0 170.881 0 155.2L0 44.8C0 29.119 0 21.278 3.052 15.288C5.736 10.02 10.02 5.736 15.288 3.052ZM44.8 14C32.619 14 24.619 14.01 21.644 15.526C19.01 16.868 16.868 19.01 15.526 21.644C14.01 24.619 14 32.619 14 44.8L14 155.2C14 167.381 14.01 175.381 15.526 178.356C16.868 180.99 19.01 183.132 21.644 184.474C24.619 185.99 32.619 186 44.8 186L205.2 186C217.381 186 225.381 185.99 228.356 184.474C230.99 183.132 233.132 180.99 234.474 178.356C235.99 175.381 236 167.381 236 155.2L236 44.8C236 32.619 235.99 24.619 234.474 21.644C233.132 19.01 230.99 16.868 228.356 15.526C225.381 14.01 217.381 14 205.2 14L44.8 14Z" fill="#0B0B0C" fill-rule="evenodd"/></g><g><path transform="matrix(1 0 0 1 122 150)" d="M44.8 0L205.2 0C220.881 0 228.722 0 234.712 3.052C239.98 5.736 244.264 10.02 246.948 15.288C250 21.278 250 29.119 250 44.8L250 155.2C250 170.881 250 178.722 246.948 184.712C244.264 189.98 239.98 194.264 234.712 196.948C228.722 200 220.881 200 205.2 200L44.8 200C29.119 200 21.278 200 15.288 196.948C10.02 194.264 5.736 189.98 3.052 184.712C0 178.722 0 170.881 0 155.2L0 44.8C0 29.119 0 21.278 3.052 15.288C5.736 10.02 10.02 5.736 15.288 3.052C21.278 0 29.119 0 44.8 0Z" fill="#EFE9DC"/><path transform="matrix(1 0 0 1 122 150)" d="M15.288 3.052C21.278 0 29.119 0 44.8 0L205.2 0C220.881 0 228.722 0 234.712 3.052C239.98 5.736 244.264 10.02 246.948 15.288C250 21.278 250 29.119 250 44.8L250 155.2C250 170.881 250 178.722 246.948 184.712C244.264 189.98 239.98 194.264 234.712 196.948C228.722 200 220.881 200 205.2 200L44.8 200C29.119 200 21.278 200 15.288 196.948C10.02 194.264 5.736 189.98 3.052 184.712C0 178.722 0 170.881 0 155.2L0 44.8C0 29.119 0 21.278 3.052 15.288C5.736 10.02 10.02 5.736 15.288 3.052ZM44.8 14C32.619 14 24.619 14.01 21.644 15.526C19.01 16.868 16.868 19.01 15.526 21.644C14.01 24.619 14 32.619 14 44.8L14 155.2C14 167.381 14.01 175.381 15.526 178.356C16.868 180.99 19.01 183.132 21.644 184.474C24.619 185.99 32.619 186 44.8 186L205.2 186C217.381 186 225.381 185.99 228.356 184.474C230.99 183.132 233.132 180.99 234.474 178.356C235.99 175.381 236 167.381 236 155.2L236 44.8C236 32.619 235.99 24.619 234.474 21.644C233.132 19.01 230.99 16.868 228.356 15.526C225.381 14.01 217.381 14 205.2 14L44.8 14Z" fill="#0B0B0C" fill-rule="evenodd"/></g><g><path transform="matrix(1 0 0 1 94 204)" d="M44.8 0L205.2 0C220.881 0 228.722 0 234.712 3.052C239.98 5.736 244.264 10.02 246.948 15.288C250 21.278 250 29.119 250 44.8L250 155.2C250 170.881 250 178.722 246.948 184.712C244.264 189.98 239.98 194.264 234.712 196.948C228.722 200 220.881 200 205.2 200L44.8 200C29.119 200 21.278 200 15.288 196.948C10.02 194.264 5.736 189.98 3.052 184.712C0 178.722 0 170.881 0 155.2L0 44.8C0 29.119 0 21.278 3.052 15.288C5.736 10.02 10.02 5.736 15.288 3.052C21.278 0 29.119 0 44.8 0Z" fill="#EFE9DC"/><path transform="matrix(1 0 0 1 94 204)" d="M15.288 3.052C21.278 0 29.119 0 44.8 0L205.2 0C220.881 0 228.722 0 234.712 3.052C239.98 5.736 244.264 10.02 246.948 15.288C250 21.278 250 29.119 250 44.8L250 155.2C250 170.881 250 178.722 246.948 184.712C244.264 189.98 239.98 194.264 234.712 196.948C228.722 200 220.881 200 205.2 200L44.8 200C29.119 200 21.278 200 15.288 196.948C10.02 194.264 5.736 189.98 3.052 184.712C0 178.722 0 170.881 0 155.2L0 44.8C0 29.119 0 21.278 3.052 15.288C5.736 10.02 10.02 5.736 15.288 3.052ZM44.8 14C32.619 14 24.619 14.01 21.644 15.526C19.01 16.868 16.868 19.01 15.5Line truncated
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><clipPath id="t"><rect width="512" height="512" rx="112"/></clipPath></defs><g clip-path="url(#t)"><rect width="512" height="512" fill="#02da96"/><path fill="#efe9dc" fill-rule="evenodd" d="M131 505C104 505 99 505 95 504C78 501 62 495 58 490C57 489 55 487 54 486C51 482 46 475 43 468C41 465 39 462 39 461C33 451 25 429 23 416C16 373 25 338 50 313C54 309 63 303 64 303C64 303 65 302 67 300C69 299 71 298 71 298C71 298 73 298 75 297C122 275 177 307 177 357C177 380 168 398 150 410C139 417 122 421 110 418C94 415 84 409 76 396C57 364 82 324 116 331C144 337 149 373 124 386C118 389 107 386 102 381C95 374 98 358 107 357C112 357 114 360 111 364C108 368 110 372 115 372C122 372 125 359 118 354C110 347 97 353 94 365C90 383 110 397 128 388C159 372 145 326 109 326C72 326 52 368 68 413C74 430 90 454 101 464C102 464 105 466 106 468C114 476 130 486 145 493C145 493 147 494 148 495C150 496 154 497 162 500C164 501 176 504 177 504C177 504 177 505 177 505C177 506 174 506 131 505ZM256 505C253 503 249 472 248 446C248 434 248 428 247 422C244 404 246 398 256 386C265 376 271 374 284 375C297 376 307 378 311 379C318 380 318 380 318 378C319 377 317 372 312 363C309 355 305 346 300 330C296 319 295 317 293 317C291 316 290 315 288 312C287 310 287 309 286 310C284 311 283 310 282 308C280 305 280 305 279 306C278 308 275 306 273 302C272 300 271 300 270 303C269 307 266 305 262 299C260 296 259 295 259 299C259 304 253 302 249 295C247 291 246 292 246 297C245 303 241 301 236 292C233 288 232 289 232 295C232 301 226 298 221 288C219 284 218 284 218 289C217 295 215 296 212 293C210 291 207 285 206 282C205 279 203 281 203 286C202 292 196 288 193 279C192 276 191 275 190 279C189 282 188 284 187 284C185 284 180 276 179 270C179 266 178 266 176 270C172 278 172 278 170 276C168 274 167 271 166 266C166 263 165 262 164 264C162 267 160 270 159 270C157 270 155 264 154 258C154 254 153 254 151 258C147 264 145 263 144 254C144 248 143 248 141 251C137 256 135 254 135 245C134 241 134 241 132 243C130 246 128 244 128 240L128 238 126 238C124 238 124 237 124 232L123 228 119 224C112 218 108 214 106 210C105 208 104 206 103 205C100 200 97 193 97 189C97 187 96 185 96 183C96 180 97 174 100 171C104 166 106 163 106 161C106 157 106 155 108 153C109 152 110 150 110 150C110 148 112 144 115 141C116 140 117 138 117 137C118 136 119 134 120 133C121 132 122 130 123 128C124 127 127 123 130 121C134 116 135 116 138 108C144 97 150 88 156 84C160 81 168 76 169 76C169 76 170 76 171 75C175 73 185 73 192 74C193 75 196 75 198 76C200 76 204 77 206 78L210 78 215 76C218 75 222 74 225 74C228 73 229 72 230 71C231 71 232 70 233 70C233 70 235 69 235 68C236 67 238 65 240 64C241 63 244 61 245 60C246 59 248 57 249 57C250 57 252 55 254 54C257 52 260 50 262 50C262 50 264 49 266 48C268 46 270 45 272 45C274 45 276 44 278 42C281 41 283 40 286 39C289 39 290 38 297 36C298 35 301 35 302 35C304 35 306 34 308 33C312 32 313 32 320 31C325 31 329 31 330 31C332 30 357 31 359 31C359 31 362 32 364 32C381 34 389 47 384 61C380 71 378 80 378 92L377 101 379 102C382 103 394 102 399 100C400 99 403 96 406 94C412 88 414 87 415 92C415 95 416 95 419 91C427 82 429 82 430 89C430 93 430 93 434 89C442 82 449 79 448 84C447 92 447 93 450 90C453 86 461 82 465 82C469 81 469 82 468 87C466 95 466 95 470 92C480 85 490 85 487 91C485 96 486 97 490 94C494 92 499 91 502 92C503 93 503 93 502 97C501 100 501 101 503 100C504 100 504 100 505 100C506 101 507 397 505 407C504 420 499 438 496 444C496 444 494 447 493 450C484 468 466 485 446 495C439 498 436 499 428 502C417 505 407 506 381 506C360 506 358 506 360 504C361 504 361 503 362 502C363 495 370 486 378 482C382 479 382 479 376 477C374 476 370 475 368 474C365 473 362 472 362 472C361 473 356 492 353 500C353 503 352 505 352 506C351 506 257 506 256 505ZM309 496C311 490 311 487 312 470C312 451 313 453 306 449C300 446 300 446 302 455C305 466 306 474 306 489C306 502 307 503 309 496ZM390 399C390 399 388 396 386 393C384 390 381 385 379 381C374 374 366 364 366 365C365 366 367 374 368 378C369 380 370 385 371 387C372 394 371 393 381 397C389 400 391 400 390 399Z"/><path fill="#0b0b0c" fill-rule="evenodd" d="M123 504C121 502 120 502 120 504C120 505 119 506 119 506C118 506 118 505 119 503C120 502 118 500 117 500C117 500 116 500 116 500C116 499 117 499 119 500C120 501 120 501 122 498C123 497 123 496 123 496C124 496 124 495 124 495C124 494 126 491 128 490C129 489 129 489 129 490C128 491 131 495 132 493C134 492 134 492 133 494C132 494 132 495 134 496C135 497 134 497 133 496C132 495 131 495 130 498C130 498 129 499 129 498C129 498 129 497 130 496L131 495 129 493L127 492 126 493C124 495 124 496 126 496C127 497 128 497 128 498C128 498 128 499 127 498C124 497 124 497 122 499L121 501 123 502C125 504 126 504 127 502C127 500 128 500 128 500C129 500 127 505 126 506C125 506 124 505 123 504ZM144 505C145 503 145 503 143 502C141 501 139 503 140 505C140 506 138 506 138 505C138 505 137 504 136 504C133 502 134 502 137 503C138 504 141 502 141 500C141 499 143 497 144 497C144 49Line truncated

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 453 KiB

-5
View File
@@ -7,9 +7,4 @@ publish = false
[dependencies]
serde_json = { workspace = true }
figcraft-doc = { workspace = true }
figcraft-color = { workspace = true }
figcraft-render = { workspace = true }
figcraft-engine = { workspace = true }
figcraft-svg = { workspace = true }
image = { workspace = true }
+45 -90
View File
@@ -1,102 +1,64 @@
//! The app icon, generated from code with FigCraft's own renderer (original artwork,
//! MIT OR Apache-2.0): a rounded tile in the app colour with a paper "frame" mark — three stacked
//! layer cards and a cursor. Writes assets/app-icon/*.png, the hicolor theme and figcraft.ico.
//! The app icon: rasterises the master `assets/app-icon/figcraft.svg` (the chameleon, see
//! `assets/app-icon/README.md`) with the `resvg` CLI (`cargo install resvg`). Writes
//! figcraft-<size>.png (macOS grid), the hicolor theme and figcraft.ico. The outputs are
//! committed, so building and packaging never need `resvg`.
use figcraft_color::{Color, Paint};
use figcraft_doc::{Document, NodeKind};
use std::path::Path;
use std::process::Command;
pub const APP_COLOR: &str = "0EA5C6";
const INK: &str = "0B0B0C";
const PAPER: &str = "EFE9DC";
const VIEW_BOX: &str = r#"viewBox="0 0 512 512""#;
/// macOS: the 512-unit tile padded onto Apple's 824/1024 icon grid (transparent margin).
const MAC_VIEW_BOX: &str = r#"viewBox="-62 -62 636 636""#;
/// Windows and Linux: 22 units cropped off each side so the portrait reads at 16-48 px.
const TIGHT_VIEW_BOX: &str = r#"viewBox="22 22 468 468""#;
fn build() -> Option<Document> {
let mut d = Document::new("icon");
let p = d.first_page()?;
let bg = d.create(p, NodeKind::Rectangle, "tile", 0.0, 0.0, 512.0, 512.0).ok()?;
let n = d.get_mut(bg).ok()?;
n.corners.radii = [112.0; 4];
n.corners.smoothing = 0.6;
n.fills = vec![Paint::solid(Color::from_hex(APP_COLOR)?)];
// Three stacked cards (layers), back to front.
for (i, (x, y, w, h)) in [(150.0, 96.0, 250.0, 200.0), (122.0, 150.0, 250.0, 200.0), (94.0, 204.0, 250.0, 200.0)].iter().enumerate() {
let c = d.create(p, NodeKind::Rectangle, "card", *x, *y, *w, *h).ok()?;
let n = d.get_mut(c).ok()?;
n.corners.radii = [28.0; 4];
n.corners.smoothing = 0.6;
n.fills = vec![Paint::solid(Color::from_hex(PAPER)?)];
n.strokes = vec![Paint::solid(Color::from_hex(INK)?)];
n.stroke.weight = 14.0;
n.stroke.align = figcraft_doc::StrokeAlign::Inside;
if i == 2 {
// Front card: a frame grid "#".
for (gx, gy, gw, gh) in
[(150.0, 228.0, 14.0, 152.0), (250.0, 228.0, 14.0, 152.0), (118.0, 260.0, 178.0, 14.0), (118.0, 330.0, 178.0, 14.0)]
{
let g = d.create(p, NodeKind::Rectangle, "grid", gx, gy, gw, gh).ok()?;
let gn = d.get_mut(g).ok()?;
gn.fills = vec![Paint::solid(Color::from_hex(INK)?)];
gn.corners.radii = [7.0; 4];
}
}
fn render(svg: &Path, size: u32, out: &Path) -> bool {
let s = size.to_string();
let ok = Command::new("resvg").args(["-w", &s, "-h", &s]).arg(svg).arg(out).status().is_ok_and(|st| st.success());
if !ok {
eprintln!("icon: resvg failed for {} (is it installed? `cargo install resvg`)", out.display());
}
// Cursor.
let cur = figcraft_doc::VectorNetwork::from_points(
&[
(0.0, 0.0).into(),
(0.0, 120.0).into(),
(32.0, 92.0).into(),
(52.0, 136.0).into(),
(72.0, 128.0).into(),
(52.0, 84.0).into(),
(92.0, 82.0).into(),
],
true,
);
let c = d.create(p, NodeKind::Vector { network: cur }, "cursor", 318.0, 300.0, 92.0, 136.0).ok()?;
let n = d.get_mut(c).ok()?;
n.fills = vec![Paint::solid(Color::from_hex(INK)?)];
n.strokes = vec![Paint::solid(Color::from_hex(PAPER)?)];
n.stroke.weight = 10.0;
n.stroke.align = figcraft_doc::StrokeAlign::Outside;
n.stroke.join = figcraft_doc::StrokeJoin::Round;
Some(d)
ok
}
pub fn generate(root: &std::path::Path) -> bool {
let Some(doc) = build() else { return false };
let Some(page) = doc.first_page() else { return false };
pub fn generate(root: &Path) -> bool {
let dir = root.join("assets/app-icon");
let _ = std::fs::create_dir_all(dir.join("hicolor"));
let render = |size: u32| -> Option<image::RgbaImage> {
let view = figcraft_render::View { origin: (0.0, 0.0), scale: f64::from(size) / 512.0, width: size, height: size };
let opts = figcraft_render::Options { background: Some(Color::TRANSPARENT), ..Default::default() };
let pix = figcraft_render::render_view(&doc, page, &view, &opts)?;
image::RgbaImage::from_raw(size, size, figcraft_render::to_rgba8(&pix))
let Ok(master) = std::fs::read_to_string(dir.join("figcraft.svg")) else {
eprintln!("icon: cannot read {}", dir.join("figcraft.svg").display());
return false;
};
let mut ok = true;
if !master.contains(VIEW_BOX) {
eprintln!("icon: expected {VIEW_BOX} in figcraft.svg");
return false;
}
let tmp = root.join("target/icon");
let (mac, tight) = (tmp.join("mac.svg"), tmp.join("tight.svg"));
let mut ok = std::fs::create_dir_all(&tmp).is_ok()
&& std::fs::write(&mac, master.replacen(VIEW_BOX, MAC_VIEW_BOX, 1)).is_ok()
&& std::fs::write(&tight, master.replacen(VIEW_BOX, TIGHT_VIEW_BOX, 1)).is_ok();
if !ok {
eprintln!("icon: cannot write {}", tmp.display());
return false;
}
for size in [16u32, 32, 48, 64, 128, 256, 512, 1024] {
let Some(img) = render(size) else { return false };
let name = if size == 1024 { "figcraft-1024.png".to_string() } else { format!("figcraft-{size}.png") };
ok &= img.save(dir.join(&name)).is_ok();
ok &= render(&mac, size, &dir.join(format!("figcraft-{size}.png")));
if size <= 512 {
let hd = dir.join(format!("hicolor/{size}x{size}/apps"));
let _ = std::fs::create_dir_all(&hd);
ok &= img.save(hd.join("ai.storyteller.figcraft.png")).is_ok();
ok &= render(&tight, size, &hd.join("ai.storyteller.figcraft.png"));
}
}
// Windows .ico (PNG-compressed entries).
let mut ico = Vec::new();
let sizes = [16u32, 32, 48, 256];
let sizes = [16u32, 20, 24, 32, 40, 48, 64, 128, 256];
let pngs: Vec<Vec<u8>> = sizes
.iter()
.filter_map(|s| {
let img = render(*s)?;
let mut out = Vec::new();
img.write_to(&mut std::io::Cursor::new(&mut out), image::ImageFormat::Png).ok()?;
Some(out)
let png = tmp.join(format!("ico-{s}.png"));
render(&tight, *s, &png).then(|| std::fs::read(png).ok()).flatten()
})
.collect();
ico.extend_from_slice(&[0, 0, 1, 0, pngs.len() as u8, 0]);
ok &= pngs.len() == sizes.len();
let mut ico = vec![0, 0, 1, 0, pngs.len() as u8, 0];
let mut offset = 6 + 16 * pngs.len() as u32;
for (s, png) in sizes.iter().zip(&pngs) {
let b = if *s >= 256 { 0 } else { *s as u8 };
@@ -109,17 +71,10 @@ pub fn generate(root: &std::path::Path) -> bool {
ico.extend_from_slice(png);
}
ok &= std::fs::write(dir.join("figcraft.ico"), ico).is_ok();
// Scalable SVG (same artwork, written by FigCraft's SVG exporter).
let tops: Vec<_> = doc.node(page).map(|p| p.children.clone()).unwrap_or_default();
match figcraft_svg::export_svg(&doc, &tops, &Default::default()) {
Some(svg) => {
let sd = dir.join("hicolor/scalable/apps");
let _ = std::fs::create_dir_all(&sd);
ok &= std::fs::write(dir.join("figcraft.svg"), &svg).is_ok();
ok &= std::fs::write(sd.join("ai.storyteller.figcraft.svg"), &svg).is_ok();
}
None => ok = false,
}
// The lighter trace keeps the scalable theme icon cheap to render.
let sd = dir.join("hicolor/scalable/apps");
let _ = std::fs::create_dir_all(&sd);
ok &= std::fs::copy(dir.join("figcraft-small.svg"), sd.join("ai.storyteller.figcraft.svg")).is_ok();
eprintln!("icon: wrote {}", dir.display());
ok
}
+1 -1
View File
@@ -5,7 +5,7 @@
//! - `assets` every file under assets/ and docs/ has a row in ATTRIBUTION.md
//! - `parity` menu-catalog coverage → docs/parity-checklist.md
//! - `version` print the version, or `version set X.Y.Z`
//! - `icon` regenerate the app icon PNGs/ICO from code (original artwork)
//! - `icon` regenerate the app icon PNGs/ICO from assets/app-icon/figcraft.svg (needs resvg)
//! - `wasm` check the core crates and web app for wasm32, and build the plugin SDK and examples
//! - `plugins` format-check, lint, test and build the plugin SDK and example plugins (`plugins/`, a
//! workspace of its own) for wasm32: `<target>/plugins/dist/<example>/` holds each manifest and