Skip to content

Commit 4b01632

Browse files
committed
Add release binaries, software renderer default, and acag repo rename
- Release workflow building Linux (AppImage + tarball) and standalone Windows .exe on v* tags, attached to the GitHub release - Default to Slint's software renderer so the app runs without a usable OpenGL driver (VMs, RDP); opt into GPU with SLINT_BACKEND=winit-femtovg - Point repository URLs at github.com/skvggor/acag - Document Debian and Arch build dependencies, the rendering backend, and the Windows preset/output paths
1 parent 1dae29e commit 4b01632

5 files changed

Lines changed: 163 additions & 7 deletions

File tree

.github/workflows/release.yml

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags: ["v*"]
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: write
10+
11+
env:
12+
CARGO_TERM_COLOR: always
13+
CARGO_INCREMENTAL: "0"
14+
15+
jobs:
16+
linux:
17+
name: Linux · AppImage + tarball
18+
runs-on: ubuntu-latest
19+
steps:
20+
- uses: actions/checkout@v4
21+
22+
- name: Install slint build dependencies
23+
run: |
24+
sudo apt-get update
25+
sudo apt-get install -y \
26+
libxkbcommon-dev libwayland-dev wayland-protocols \
27+
libxcb1-dev libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev \
28+
libfontconfig1-dev libgl1-mesa-dev
29+
30+
- name: Install Rust toolchain
31+
uses: dtolnay/rust-toolchain@stable
32+
33+
- uses: Swatinem/rust-cache@v2
34+
35+
- name: Build release
36+
run: cargo build --release --locked
37+
38+
- name: Tarball (raw binary)
39+
run: |
40+
mkdir -p dist
41+
install -Dm755 target/release/acag stage/acag
42+
install -Dm644 README.md stage/README.md
43+
install -Dm644 LICENSE stage/LICENSE
44+
tar -C stage -czf "dist/acag-${VERSION}-linux-x86_64.tar.gz" .
45+
env:
46+
VERSION: ${{ github.ref_name }}
47+
48+
- name: Build AppImage
49+
run: |
50+
curl -fsSL -o linuxdeploy.AppImage \
51+
https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
52+
chmod +x linuxdeploy.AppImage
53+
54+
# AppImage's own runtime needs FUSE; extract-and-run avoids it on CI.
55+
export APPIMAGE_EXTRACT_AND_RUN=1
56+
57+
# Icon basename must match Icon= in the .desktop file.
58+
cp assets/icons/icon-256.png article-cover-art-generator.png
59+
60+
export OUTPUT="acag-${VERSION}-x86_64.AppImage"
61+
./linuxdeploy.AppImage \
62+
--appdir AppDir \
63+
-e target/release/acag \
64+
-d assets/article-cover-art-generator.desktop \
65+
-i article-cover-art-generator.png \
66+
--output appimage
67+
68+
mv "${OUTPUT}" dist/
69+
env:
70+
VERSION: ${{ github.ref_name }}
71+
72+
- name: Publish to release
73+
uses: softprops/action-gh-release@v2
74+
with:
75+
files: dist/*
76+
77+
windows:
78+
name: Windows · standalone .exe
79+
runs-on: windows-latest
80+
steps:
81+
- uses: actions/checkout@v4
82+
83+
- name: Install Rust toolchain
84+
uses: dtolnay/rust-toolchain@stable
85+
86+
- uses: Swatinem/rust-cache@v2
87+
88+
- name: Build release (static CRT)
89+
run: cargo build --release --locked
90+
env:
91+
# Statically link the MSVC runtime so the .exe runs without vcredist.
92+
RUSTFLAGS: "-C target-feature=+crt-static"
93+
94+
- name: Zip
95+
shell: pwsh
96+
run: |
97+
New-Item -ItemType Directory -Force -Path dist, stage | Out-Null
98+
Copy-Item target/release/acag.exe stage/
99+
Copy-Item README.md stage/
100+
Copy-Item LICENSE stage/
101+
Compress-Archive -Path stage/* -DestinationPath "dist/acag-$env:VERSION-windows-x86_64.zip"
102+
env:
103+
VERSION: ${{ github.ref_name }}
104+
105+
- name: Publish to release
106+
uses: softprops/action-gh-release@v2
107+
with:
108+
files: dist/*

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ edition = "2024"
55
description = "Native generator for 1:1 article cover art, in an Omakase / Japanese-constructivist style."
66
authors = ["Marcos Lima <marckfree@gmail.com>"]
77
license = "MIT"
8-
repository = "https://github.com/skvggor/article-cover-art-generator"
8+
repository = "https://github.com/skvggor/acag"
99
readme = "README.md"
1010

1111
[[bin]]
@@ -18,7 +18,7 @@ dirs = "6.0.0"
1818
fastrand = "2.4.1"
1919
resvg = "0.47.0"
2020
serde = { version = "1.0.228", features = ["derive"] }
21-
slint = "1.16.1"
21+
slint = { version = "1.16.1", features = ["renderer-software"] }
2222
toml = "1.1.2"
2323
ttf-parser = "0.25.1"
2424

README.md

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ the sumi-ê palette) with [skvggor.dev](https://skvggor.dev) and
5151
- **Live preview** — every control updates the preview instantly
5252
- **Adjustable film grain** and **pattern strength** sliders, shown live in the preview
5353
- **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/`)
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)
5555
- **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)
5757
- **Export****2K or 4K** (longest edge) PNG at each format's exact dimensions, plus the
@@ -63,15 +63,49 @@ the sumi-ê palette) with [skvggor.dev](https://skvggor.dev) and
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

66-
## Build & run
66+
## Download
6767

68-
Requires a recent stable Rust toolchain.
68+
Prebuilt binaries are attached to each [GitHub release](https://github.com/skvggor/acag/releases) — no Rust toolchain or system dependencies required.
69+
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).
72+
73+
### Rendering backend
74+
75+
By default the app uses Slint's **software (CPU) renderer**, so it runs everywhere —
76+
including headless VMs and RDP sessions without a usable OpenGL driver. For this
77+
form-plus-preview UI the difference is imperceptible. To opt into GPU rendering:
78+
79+
```sh
80+
SLINT_BACKEND=winit-femtovg acag
81+
```
82+
83+
## Build from source
84+
85+
Requires a recent stable Rust toolchain. On Linux, Slint also needs a few system
86+
libraries for the windowing/build:
87+
88+
```sh
89+
# Debian / Ubuntu
90+
sudo apt install build-essential pkg-config \
91+
libxkbcommon-dev libwayland-dev wayland-protocols \
92+
libxcb1-dev libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev \
93+
libfontconfig1-dev libgl1-mesa-dev
94+
```
95+
96+
```sh
97+
# Arch Linux
98+
sudo pacman -S --needed base-devel \
99+
libxkbcommon wayland wayland-protocols \
100+
libxcb fontconfig mesa
101+
```
69102

70103
```sh
71104
cargo run --release
72105
```
73106

74-
Covers are saved to `~/Pictures/article-covers/` (named from the title). Set
107+
Covers are saved to `~/Pictures/article-covers/` on Linux and
108+
`%USERPROFILE%\Pictures\article-covers\` on Windows (named from the title). Set
75109
`ACAG_OUTPUT_DIR` to write them somewhere else.
76110

77111
### Install on Omarchy / Hyprland

src/main.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,20 @@ fn reload_presets(model: &VecModel<SharedString>) {
101101
model.set_vec(names);
102102
}
103103

104+
/// Default to Slint's CPU (software) renderer so the app runs everywhere,
105+
/// including machines without a usable OpenGL driver (headless VMs, RDP).
106+
/// For this form-plus-preview UI the cost is imperceptible. Users with working
107+
/// GPU drivers can opt into hardware rendering with `SLINT_BACKEND=winit-femtovg`.
108+
fn default_to_software_renderer() {
109+
if std::env::var_os("SLINT_BACKEND").is_none() {
110+
// Safe: set before any backend/window initialization, still single-threaded.
111+
unsafe { std::env::set_var("SLINT_BACKEND", "winit-software") };
112+
}
113+
}
114+
104115
fn main() -> Result<()> {
116+
default_to_software_renderer();
117+
105118
let ui = AppWindow::new()?;
106119

107120
ui.set_themes(string_model(

src/preset.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Named presets: save the current look under a name and load any saved one
22
//! later. Each preset is a TOML file in the presets directory
3-
//! (`~/.config/article-cover-art-generator/presets/`, override with
3+
//! (`~/.config/article-cover-art-generator/presets/` on Linux,
4+
//! `%APPDATA%\article-cover-art-generator\presets\` on Windows; override with
45
//! `ACAG_PRESETS_DIR`).
56
67
use std::path::{Path, PathBuf};

0 commit comments

Comments
 (0)