Skip to content

Commit 7ca65ae

Browse files
authored
Merge pull request #9 from skvggor/develop
Trim em-dashes from the README and add AGENTS.md
2 parents 85419b9 + e5c611a commit 7ca65ae

3 files changed

Lines changed: 113 additions & 20 deletions

File tree

AGENTS.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# AGENTS.md
2+
3+
Guidance for AI agents working in this repository.
4+
5+
## What this is
6+
7+
`acag` (article cover art generator) is a native desktop app that generates
8+
article cover art in five aspect ratios (square, link/Open Graph, wide, portrait,
9+
banner) in an Omakase / Japanese-constructivist style. Rust +
10+
[Slint](https://slint.dev) for the GUI, [resvg](https://github.com/linebender/resvg)
11+
/ tiny-skia for rasterization. Single binary named `acag`.
12+
13+
## Core invariant
14+
15+
`render_cover_svg(&CoverConfig) -> String` (in `src/cover`) is the single source
16+
of truth. The live preview and both exports rasterize the **same SVG**, so what
17+
you see is exactly the file you get. Never fork rendering between preview and
18+
export: change the SVG function and both follow.
19+
20+
## Layout
21+
22+
```
23+
src/
24+
design/ themes · wagara patterns · WCAG contrast
25+
cover/ config · format (aspect ratios) · typesetting · render · layouts
26+
raster.rs SVG → Pixmap/PNG by longest edge (resvg + embedded Montserrat)
27+
export.rs save SVG / PNG (2K or 4K)
28+
preset.rs save/load named presets as TOML
29+
main.rs Slint GUI wiring (background export + spinner)
30+
ui/app.slint the editor + live preview
31+
examples/ gallery.rs (docs/samples), icon.rs (app icon + icon.ico)
32+
build.rs compiles the Slint UI; embeds the Windows icon resource
33+
```
34+
35+
The library crate holds all logic and is what tests cover; `main.rs` is thin GUI
36+
glue. Fonts (Montserrat Black/Bold/Regular) are embedded via `include_bytes!`, so
37+
no system fonts are needed at runtime.
38+
39+
## Commands
40+
41+
```sh
42+
cargo run --release # run the app
43+
cargo test # unit tests
44+
cargo fmt --all --check # formatting gate
45+
cargo clippy --all-targets -- -D warnings # lint gate
46+
cargo llvm-cov --lib --fail-under-lines 80 # coverage gate (library ≥ 80%)
47+
cargo run --example gallery # regenerate docs/samples
48+
cargo run --example icon # regenerate assets/icons/* (PNGs + icon.ico)
49+
```
50+
51+
CI (`.github/workflows/ci.yml`) runs fmt, clippy `-D warnings`, `cargo test`, and
52+
library line coverage ≥ 80%. All four must pass; run them before proposing a
53+
change is done.
54+
55+
## Conventions
56+
57+
- Edition 2024. Note `std::env::set_var` is `unsafe` here; only call it before any
58+
threads/backends start (see `main.rs`).
59+
- Code, comments, and identifiers in English. Prefer full descriptive names, but
60+
keep the project's established abbreviations (`config`, `cfg`, `ctx`); match the
61+
surrounding code rather than renaming.
62+
- No filler comments. Comment only non-obvious *why*, not *what*.
63+
- Tests: cover basic functionality first, then edge cases; keep the library at
64+
≥ 80% lines. Use real types, never ad-hoc untyped mocks.
65+
- Imports inside the same directory use `crate::...` / `super::...` paths already
66+
established in the file; follow the surrounding style.
67+
68+
## Platform & runtime notes
69+
70+
- **Renderer**: defaults to Slint's software (CPU) renderer (`SLINT_BACKEND=winit-software`
71+
set in `main.rs` when unset) so it runs without OpenGL (VMs, RDP). Femtovg/GPU
72+
is opt-in via `SLINT_BACKEND=winit-femtovg`. Don't assume a GL context exists.
73+
- **Windows**: `#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]`
74+
hides the console for release builds. The `.exe` icon is embedded from
75+
`assets/icons/icon.ico` via `winresource` in `build.rs` (only on a Windows host).
76+
- **Output dirs**: covers go to `~/Pictures/article-covers/` (Linux) /
77+
`%USERPROFILE%\Pictures\article-covers\` (Windows), override `ACAG_OUTPUT_DIR`.
78+
Presets live under the platform config dir, override `ACAG_PRESETS_DIR`.
79+
80+
## Release
81+
82+
`.github/workflows/release.yml` triggers on `v*` tags: builds a Linux AppImage +
83+
tarball and a standalone Windows `.exe` (static CRT), attached to the GitHub
84+
release. The AppImage `.desktop` `Categories` must use only freedesktop-registered
85+
values (no unregistered `Design`, etc.) or `appimagetool` fails.
86+
87+
## Gotchas
88+
89+
- Keep preview and export pixel-identical: only the rasterization size differs.
90+
- Regenerate `docs/samples` (`gallery`) and the icon set (`icon`) when their
91+
inputs change; both are committed assets.
92+
- After editing `ui/app.slint`, the build re-runs `slint-build`; mismatched
93+
property names surface as compile errors in `main.rs`.

README.md

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
<p align="center">
1010
A native desktop app that generates <strong>article cover art</strong> in an
11-
<strong>Omakase / Japanese-constructivist</strong> style <strong>five aspect ratios</strong>
11+
<strong>Omakase / Japanese-constructivist</strong> style: <strong>five aspect ratios</strong>
1212
(square, link, wide, portrait, banner), six themes, five patterns, three layouts, a live
1313
preview, exported up to <strong>4K PNG</strong> (plus the source SVG).
1414
</p>
@@ -29,50 +29,50 @@
2929

3030
## The idea
3131

32-
Built around **Omakase** (お任せ "I leave it to you", the sushi chef's choice) and the
32+
Built around **Omakase** (お任せ, "I leave it to you", the sushi chef's choice) and the
3333
geometry of traditional Japanese patterns (**wagara**, 和柄), tempered with bold,
3434
structural, constructivist typography. The result is calm but assertive: a huge
3535
**Montserrat Black** title, a lot of **Ma** (negative space), and a quiet wave "seal".
3636

37-
The Japanese identity comes **only from geometry and color** there are deliberately
37+
The Japanese identity comes **only from geometry and color**; there are deliberately
3838
**no Japanese glyphs in the artwork**. It shares its design language (themes, wagara,
3939
the sumi-ê palette) with [skvggor.dev](https://skvggor.dev) and
4040
[`waka-readme`](https://github.com/skvggor/waka-readme).
4141

4242
## Features
4343

44-
- **6 sumi-ê themes** `terracotta` 赤土 · `sumi` 墨 · `matcha` 抹茶 · `washi` 和紙 · `ai` 藍 · `sakura`
45-
- **5 wagara patterns** `seigaiha` (waves) · `shippo` (interlocking circles) · `kikko`
44+
- **6 sumi-ê themes**: `terracotta` 赤土 · `sumi` 墨 · `matcha` 抹茶 · `washi` 和紙 · `ai` 藍 · `sakura`
45+
- **5 wagara patterns**: `seigaiha` (waves) · `shippo` (interlocking circles) · `kikko`
4646
(tortoiseshell) · `yabane` (arrow feathers) · `asanoha` (hemp leaf)
47-
- **3 layouts** `editorial` (asymmetric), `bloco` (constructivist color block), `ma` (negative space)
48-
- **5 formats** `1:1` square, `1.91:1` link/Open Graph (LinkedIn, Facebook, X, Slack),
49-
`16:9` wide (native LinkedIn article, YouTube), `4:5` portrait, `2:1` banner the layouts
47+
- **3 layouts**: `editorial` (asymmetric), `bloco` (constructivist color block), `ma` (negative space)
48+
- **5 formats**: `1:1` square, `1.91:1` link/Open Graph (LinkedIn, Facebook, X, Slack),
49+
`16:9` wide (native LinkedIn article, YouTube), `4:5` portrait, `2:1` banner; the layouts
5050
adapt to each ratio
51-
- **Live preview** every control updates the preview instantly
51+
- **Live preview**: every control updates the preview instantly
5252
- **Adjustable film grain** and **pattern strength** sliders, shown live in the preview
53-
- **Omakase button** randomizes the visual style and lets the house plate it for you
54-
- **Named presets** save any number of looks as TOML and load/delete any of them (`~/.config/article-cover-art-generator/presets/` on Linux, `%APPDATA%\article-cover-art-generator\presets\` on Windows)
55-
- **WCAG AAA** all readable text is forced to ≥ 7:1 contrast against its background
53+
- **Omakase button**: randomizes the visual style and lets the house plate it for you
54+
- **Named presets**: save any number of looks as TOML and load/delete any of them (`~/.config/article-cover-art-generator/presets/` on Linux, `%APPDATA%\article-cover-art-generator\presets\` on Windows)
55+
- **WCAG AAA**: all readable text is forced to ≥ 7:1 contrast against its background
5656
- **Montserrat** Black / Bold / Regular, embedded in the binary (no system fonts needed)
57-
- **Export** **2K or 4K** (longest edge) PNG at each format's exact dimensions, plus the
57+
- **Export**: **2K or 4K** (longest edge) PNG at each format's exact dimensions, plus the
5858
resolution-independent source SVG; a non-blocking save (spinner while it rasterizes) and
5959
optional open-after-export
60-
- **Native** Rust + [slint](https://slint.dev) + [resvg](https://github.com/linebender/resvg),
60+
- **Native**: Rust + [slint](https://slint.dev) + [resvg](https://github.com/linebender/resvg),
6161
running directly on Wayland (no web view, no Node)
6262

6363
Only the **title** is required; category, date, number and brand are optional, keeping the
6464
cover generic enough for any platform (blog, dev.to, LinkedIn, X, OG image, thumbnail…).
6565

6666
## Download
6767

68-
Prebuilt binaries are attached to each [GitHub release](https://github.com/skvggor/acag/releases) — no Rust toolchain or system dependencies required.
68+
Prebuilt binaries are attached to each [GitHub release](https://github.com/skvggor/acag/releases). No Rust toolchain or system dependencies required.
6969

70-
- **Linux** `acag-*-x86_64.AppImage` (self-contained: `chmod +x` and run), or `acag-*-linux-x86_64.tar.gz` (raw binary).
71-
- **Windows** `acag-*-windows-x86_64.zip` (standalone `acag.exe`, no Visual C++ runtime needed).
70+
- **Linux**: `acag-*-x86_64.AppImage` (self-contained: `chmod +x` and run), or `acag-*-linux-x86_64.tar.gz` (raw binary).
71+
- **Windows**: `acag-*-windows-x86_64.zip` (standalone `acag.exe`, no Visual C++ runtime needed).
7272

7373
### Rendering backend
7474

75-
By default the app uses Slint's **software (CPU) renderer**, so it runs everywhere
75+
By default the app uses Slint's **software (CPU) renderer**, so it runs everywhere,
7676
including headless VMs and RDP sessions without a usable OpenGL driver. For this
7777
form-plus-preview UI the difference is imperceptible. To opt into GPU rendering:
7878

@@ -157,7 +157,7 @@ cargo run --example icon # regenerate the app icon
157157

158158
## Credits
159159

160-
- **Montserrat** by Julieta Ulanovsky et al. [SIL Open Font License](https://github.com/JulietaUla/Montserrat).
160+
- **Montserrat** by Julieta Ulanovsky et al., under the [SIL Open Font License](https://github.com/JulietaUla/Montserrat).
161161
- **resvg / tiny-skia** and **slint** for native rendering and UI.
162162
- Design language shared with [skvggor.dev](https://skvggor.dev) and `waka-readme`.
163163

assets/article-cover-art-generator.desktop

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Type=Application
33
Name=acag
44
GenericName=Article Cover Art Generator
5-
Comment=Generate 1:1 article cover art in an Omakase style
5+
Comment=Generate article cover art in an Omakase style
66
Exec=acag
77
Icon=article-cover-art-generator
88
Terminal=false

0 commit comments

Comments
 (0)