From 79261615956ab21334e49ca1d384390272e647da Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Sat, 10 Oct 2026 21:36:30 -0400 Subject: [PATCH] Release prep 0.7.0: Linux riscv64 tarball + version bump (#2965) * Release prep 0.7.0: add Linux riscv64 tar.gz to the release; bump to 0.7.0 - release.yml: new linux-riscv64 job, ported from GridCraft: cross-compiled on ubuntu-24.04 against ports.ubuntu.com riscv64 libs, tar.gz only, photocraft-cli --version smoke-tested under QEMU. The draft-release job now needs it, so SHA256SUMS.txt covers it. - packaging/linux/package.sh: CROSS_ARCH / CROSS_TARGET / CROSS_COMPILE / EMULATOR support. - linux_libs: search /usr/lib/riscv64-linux-gnu on riscv64 (was the x86_64 triplet). - README and docs/releasing.md list the riscv64 tarball. - Version 0.6.0 -> 0.7.0 (cargo xtask version set), Cargo.lock refreshed; contributors refreshed. Co-Authored-By: Claude Opus 5.5 * canvas: crisp elliptical marquee ants again in an unrotated view #2732 (a27d7175) built the elliptical marquee's live ants in document space and snapped every vertex to the half-pixel grid on its own. Near the edge midpoints the nearly flat arcs became 1 px stairs, whose antialiased steps are grey, so the ants no longer contrast on white or black: drag_preview_canvas's marquee test fails on main (ubuntu and windows). In an axis-aligned view (rotation a multiple of 90 degrees) draw the ellipse inscribed in the snapped screen box again, as before #2732; rotated views keep the mapped ellipse. Co-Authored-By: Claude Opus 5.5 --------- Co-authored-by: Claude Opus 5.5 --- .github/workflows/release.yml | 72 ++- Cargo.lock | 58 +- Cargo.toml | 2 +- README.md | 2 + apps/photocraft/src/linux_libs.rs | 8 +- contributors/contributors.json | 874 +++++++++++++++++++++++------- crates/ui-egui/src/canvas.rs | 9 + docs/releasing.md | 1 + packaging/linux/package.sh | 27 +- 9 files changed, 811 insertions(+), 242 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d3a127589..32da91362 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -372,9 +372,79 @@ jobs: path: dist/release/* if-no-files-found: error + linux-riscv64: + name: Linux riscv64 + needs: version + # Cross-compiled on x86_64 (no hosted RISC-V runners) against the runner's own Ubuntu release + # from ports.ubuntu.com, so the binaries need that release's glibc (24.04: 2.39). 22.04's + # riscv64 ports lag its amd64 updates, which breaks the multiarch install. tar.gz only; the + # CLI is smoke-tested under QEMU. Same recipe as GridCraft's linux-riscv64 job. + runs-on: ubuntu-24.04 + # No `environment: release`: this job reads no secrets, so a branch dry run can run it. + env: + PHOTOCRAFT_VERSION: ${{ needs.version.outputs.version }} + PHOTOCRAFT_BUILD_DATE: ${{ needs.version.outputs.date }} + steps: + - uses: actions/checkout@v4 + - name: Check out craft-fonts (embedded fonts) + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + repository: storytold/craft-fonts + ref: ${{ env.CRAFT_FONTS_REF }} + path: craft-fonts + - uses: dtolnay/rust-toolchain@stable + with: + targets: riscv64gc-unknown-linux-gnu + - uses: Swatinem/rust-cache@v2 + with: + key: release-linux-riscv64 + - name: Apply version override + if: inputs.version != '' + run: cargo xtask version set "$PHOTOCRAFT_VERSION" + - name: Install cross-compilation dependencies + run: | + . /etc/os-release + sudo dpkg --add-architecture riscv64 + # Pin the existing (archive.ubuntu.com) sources to amd64; riscv64 comes from ports. + if [ -f /etc/apt/sources.list.d/ubuntu.sources ]; then + sudo sed -i '/^Types: deb/a Architectures: amd64' /etc/apt/sources.list.d/ubuntu.sources + fi + if [ -f /etc/apt/sources.list ]; then + sudo sed -i 's/^deb /deb [arch=amd64] /g' /etc/apt/sources.list + sudo sed -i 's/^deb-src /deb-src [arch=amd64] /g' /etc/apt/sources.list + fi + for suite in "$VERSION_CODENAME" "$VERSION_CODENAME-updates" "$VERSION_CODENAME-security"; do + echo "deb [arch=riscv64] http://ports.ubuntu.com/ubuntu-ports $suite main universe restricted multiverse" + done | sudo tee /etc/apt/sources.list.d/riscv64.list + sudo apt-get update + sudo apt-get install -y --no-install-recommends \ + gcc-riscv64-linux-gnu binutils-riscv64-linux-gnu libc6-dev-riscv64-cross libc6-dev:riscv64 qemu-user \ + libxkbcommon-dev:riscv64 libwayland-dev:riscv64 libx11-dev:riscv64 libxrandr-dev:riscv64 \ + libxi-dev:riscv64 libgl1-mesa-dev:riscv64 \ + desktop-file-utils appstream + - name: Build and package (tar.gz) + env: + CRAFT_FONTS_DIR: ${{ github.workspace }}/craft-fonts + CRAFT_FONTS_REQUIRED: "1" + CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER: riscv64-linux-gnu-gcc + PKG_CONFIG_SYSROOT_DIR: / + PKG_CONFIG_PATH: /usr/lib/riscv64-linux-gnu/pkgconfig:/usr/share/pkgconfig + PKG_CONFIG_ALLOW_CROSS: "1" + CROSS_ARCH: riscv64 + CROSS_TARGET: riscv64gc-unknown-linux-gnu + CROSS_COMPILE: riscv64-linux-gnu- + EMULATOR: qemu-riscv64 + QEMU_LD_PREFIX: /usr/riscv64-linux-gnu + run: packaging/linux/package.sh --formats tar + - uses: actions/upload-artifact@v4 + with: + name: release-linux-riscv64 + path: dist/release/*.tar.gz + if-no-files-found: error + release: name: Draft GitHub Release - needs: [version, macos, windows, linux, flatpak, freebsd, web] + needs: [version, macos, windows, linux, linux-riscv64, flatpak, freebsd, web] runs-on: ubuntu-latest environment: release permissions: diff --git a/Cargo.lock b/Cargo.lock index 5d3156368..311a6103e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4173,7 +4173,7 @@ dependencies = [ [[package]] name = "photocraft" -version = "0.6.0" +version = "0.7.0" dependencies = [ "arboard", "async-io", @@ -4214,7 +4214,7 @@ dependencies = [ [[package]] name = "photocraft-affinity" -version = "0.6.0" +version = "0.7.0" dependencies = [ "crc32fast", "flate2", @@ -4224,7 +4224,7 @@ dependencies = [ [[package]] name = "photocraft-algo" -version = "0.6.0" +version = "0.7.0" dependencies = [ "photocraft-color", "photocraft-geom", @@ -4237,7 +4237,7 @@ dependencies = [ [[package]] name = "photocraft-automation" -version = "0.6.0" +version = "0.7.0" dependencies = [ "base64", "cap-std", @@ -4259,7 +4259,7 @@ dependencies = [ [[package]] name = "photocraft-cli" -version = "0.6.0" +version = "0.7.0" dependencies = [ "photocraft-automation", "photocraft-codecs", @@ -4273,7 +4273,7 @@ dependencies = [ [[package]] name = "photocraft-cms" -version = "0.6.0" +version = "0.7.0" dependencies = [ "moxcms", "rayon", @@ -4281,7 +4281,7 @@ dependencies = [ [[package]] name = "photocraft-codecs" -version = "0.6.0" +version = "0.7.0" dependencies = [ "exr", "flate2", @@ -4302,7 +4302,7 @@ dependencies = [ [[package]] name = "photocraft-color" -version = "0.6.0" +version = "0.7.0" dependencies = [ "photocraft-cms", "serde", @@ -4310,7 +4310,7 @@ dependencies = [ [[package]] name = "photocraft-compose" -version = "0.6.0" +version = "0.7.0" dependencies = [ "criterion", "photocraft-color", @@ -4325,7 +4325,7 @@ dependencies = [ [[package]] name = "photocraft-doc" -version = "0.6.0" +version = "0.7.0" dependencies = [ "photocraft-color", "photocraft-geom", @@ -4336,7 +4336,7 @@ dependencies = [ [[package]] name = "photocraft-engine" -version = "0.6.0" +version = "0.7.0" dependencies = [ "blake3", "exr", @@ -4369,7 +4369,7 @@ dependencies = [ [[package]] name = "photocraft-format" -version = "0.6.0" +version = "0.7.0" dependencies = [ "blake3", "flate2", @@ -4388,14 +4388,14 @@ dependencies = [ [[package]] name = "photocraft-geom" -version = "0.6.0" +version = "0.7.0" dependencies = [ "serde", ] [[package]] name = "photocraft-gpu" -version = "0.6.0" +version = "0.7.0" dependencies = [ "half", "log", @@ -4412,14 +4412,14 @@ dependencies = [ [[package]] name = "photocraft-heif" -version = "0.6.0" +version = "0.7.0" dependencies = [ "heic-rs", ] [[package]] name = "photocraft-io" -version = "0.6.0" +version = "0.7.0" dependencies = [ "blake3", "crc32fast", @@ -4448,14 +4448,14 @@ dependencies = [ [[package]] name = "photocraft-ops" -version = "0.6.0" +version = "0.7.0" dependencies = [ "photocraft-doc", ] [[package]] name = "photocraft-paint" -version = "0.6.0" +version = "0.7.0" dependencies = [ "photocraft-color", "photocraft-geom", @@ -4466,7 +4466,7 @@ dependencies = [ [[package]] name = "photocraft-plugins" -version = "0.6.0" +version = "0.7.0" dependencies = [ "photocraft-color", "photocraft-geom", @@ -4481,7 +4481,7 @@ dependencies = [ [[package]] name = "photocraft-psd" -version = "0.6.0" +version = "0.7.0" dependencies = [ "flate2", "photocraft-psd", @@ -4492,7 +4492,7 @@ dependencies = [ [[package]] name = "photocraft-raster" -version = "0.6.0" +version = "0.7.0" dependencies = [ "photocraft-color", "photocraft-geom", @@ -4502,7 +4502,7 @@ dependencies = [ [[package]] name = "photocraft-raw" -version = "0.6.0" +version = "0.7.0" dependencies = [ "flate2", "image", @@ -4517,7 +4517,7 @@ dependencies = [ [[package]] name = "photocraft-tablet" -version = "0.6.0" +version = "0.7.0" dependencies = [ "block2 0.6.2", "objc2 0.6.4", @@ -4529,7 +4529,7 @@ dependencies = [ [[package]] name = "photocraft-testkit" -version = "0.6.0" +version = "0.7.0" dependencies = [ "memory-stats", "photocraft-color", @@ -4540,7 +4540,7 @@ dependencies = [ [[package]] name = "photocraft-text" -version = "0.6.0" +version = "0.7.0" dependencies = [ "flate2", "parley", @@ -4554,7 +4554,7 @@ dependencies = [ [[package]] name = "photocraft-ui-egui" -version = "0.6.0" +version = "0.7.0" dependencies = [ "base64", "eframe", @@ -4591,7 +4591,7 @@ dependencies = [ [[package]] name = "photocraft-vector" -version = "0.6.0" +version = "0.7.0" dependencies = [ "photocraft-color", "photocraft-doc", @@ -4602,7 +4602,7 @@ dependencies = [ [[package]] name = "photocraft-web" -version = "0.6.0" +version = "0.7.0" dependencies = [ "eframe", "egui", @@ -7435,7 +7435,7 @@ checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" [[package]] name = "xtask" -version = "0.6.0" +version = "0.7.0" dependencies = [ "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index afcfdd152..71e68de74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ members = ["crates/*", "apps/*", "xtask"] default-members = ["crates/*", "apps/photocraft", "apps/photocraft-cli", "xtask"] [workspace.package] -version = "0.6.0" +version = "0.7.0" edition = "2024" license = "MIT OR Apache-2.0" rust-version = "1.95" diff --git a/README.md b/README.md index fd16ea669..31fc11634 100644 --- a/README.md +++ b/README.md @@ -350,6 +350,8 @@ Installers and executables are code-signed. | Fedora/RHEL/openSUSE | `photocraft--linux-x86_64.rpm` | `photocraft--linux-aarch64.rpm` | | | Tarball | `photocraft--linux-x86_64.tar.gz` | `photocraft--linux-aarch64.tar.gz` | Unpack anywhere | +RISC-V (riscv64): `photocraft--linux-riscv64.tar.gz` only, built against Ubuntu 24.04 (needs glibc 2.39+). + ### FreeBSD | Build | File | diff --git a/apps/photocraft/src/linux_libs.rs b/apps/photocraft/src/linux_libs.rs index b2b64fdcd..3cf1fdd12 100644 --- a/apps/photocraft/src/linux_libs.rs +++ b/apps/photocraft/src/linux_libs.rs @@ -227,7 +227,13 @@ pub fn missing_message(session: DisplaySession, missing: &[AnyOf], distro: Distr /// Library directories to search: `LD_LIBRARY_PATH`, then the usual system and Flatpak paths. fn search_dirs(ld_library_path: Option<&str>) -> Vec { let mut dirs: Vec = ld_library_path.unwrap_or("").split(':').filter(|d| !d.is_empty()).map(PathBuf::from).collect(); - let triplet = if cfg!(target_arch = "aarch64") { "aarch64-linux-gnu" } else { "x86_64-linux-gnu" }; + let triplet = if cfg!(target_arch = "aarch64") { + "aarch64-linux-gnu" + } else if cfg!(target_arch = "riscv64") { + "riscv64-linux-gnu" + } else { + "x86_64-linux-gnu" + }; for d in ["/app/lib", "/usr/local/lib", "/usr/lib64", "/lib64", "/usr/lib", "/lib"] { dirs.push(PathBuf::from(d)); } diff --git a/contributors/contributors.json b/contributors/contributors.json index 18f2db730..053d910f3 100644 --- a/contributors/contributors.json +++ b/contributors/contributors.json @@ -2,23 +2,23 @@ "schema": 1, "repo": "storytold/photocraft", "branch": "main", - "head": "9c427a7a2c792d326939f5b27b1d814a7c6321a7", - "head_date": "2026-10-10T00:34:31Z", - "commits": 1054, + "head": "9d3ba499ade013f9edf92f3b7e26493b9f70db76", + "head_date": "2026-10-10T23:09:26Z", + "commits": 1302, "unattributed_commits": 0, "contributors": [ { "login": "echelon", "people_entry": true, "github_name": null, - "prs": 160, - "commits": 240, - "lines_added": 281036, - "lines_deleted": 22729, + "prs": 166, + "commits": 248, + "lines_added": 284334, + "lines_deleted": 23389, "binary_added": 39, "binary_deleted": 8, "first_commit": "2026-09-30T06:12:04Z", - "last_commit": "2026-10-10T00:16:52Z" + "last_commit": "2026-10-10T22:46:16Z" }, { "login": "storybored379", @@ -115,14 +115,14 @@ "login": "Ni-zav", "people_entry": false, "github_name": null, - "prs": 51, - "commits": 61, - "lines_added": 4037, - "lines_deleted": 328, + "prs": 65, + "commits": 75, + "lines_added": 5049, + "lines_deleted": 375, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-05T05:01:49Z", - "last_commit": "2026-10-10T00:05:15Z" + "last_commit": "2026-10-10T22:32:04Z" }, { "login": "kntrttm", @@ -427,14 +427,14 @@ "login": "coygeek", "people_entry": false, "github_name": null, - "prs": 1, - "commits": 1, - "lines_added": 4, - "lines_deleted": 0, + "prs": 3, + "commits": 3, + "lines_added": 309, + "lines_deleted": 9, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-07T04:32:34Z", - "last_commit": "2026-10-07T04:32:34Z" + "last_commit": "2026-10-10T09:14:41Z" }, { "login": "neversaynv3r", @@ -466,14 +466,14 @@ "login": "TheSeanLavery", "people_entry": false, "github_name": null, - "prs": 4, - "commits": 4, - "lines_added": 2205, - "lines_deleted": 66, + "prs": 5, + "commits": 5, + "lines_added": 2422, + "lines_deleted": 101, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-07T10:11:06Z", - "last_commit": "2026-10-07T11:45:26Z" + "last_commit": "2026-10-10T09:50:58Z" }, { "login": "mnmlyw", @@ -492,14 +492,14 @@ "login": "rosematcha", "people_entry": false, "github_name": null, - "prs": 13, - "commits": 13, - "lines_added": 1735, - "lines_deleted": 205, + "prs": 14, + "commits": 14, + "lines_added": 1752, + "lines_deleted": 206, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-07T10:49:53Z", - "last_commit": "2026-10-08T01:25:19Z" + "last_commit": "2026-10-10T17:40:20Z" }, { "login": "jason4short", @@ -518,14 +518,14 @@ "login": "siraxe", "people_entry": false, "github_name": null, - "prs": 2, - "commits": 2, - "lines_added": 537, - "lines_deleted": 91, + "prs": 3, + "commits": 3, + "lines_added": 1397, + "lines_deleted": 220, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-07T11:03:49Z", - "last_commit": "2026-10-09T23:56:41Z" + "last_commit": "2026-10-10T11:04:52Z" }, { "login": "arpitkjaiswal", @@ -555,16 +555,16 @@ }, { "login": "alexanderalber", - "people_entry": false, + "people_entry": true, "github_name": null, - "prs": 3, - "commits": 3, - "lines_added": 1809, - "lines_deleted": 56, + "prs": 5, + "commits": 5, + "lines_added": 1967, + "lines_deleted": 75, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-07T11:42:30Z", - "last_commit": "2026-10-07T22:59:39Z" + "last_commit": "2026-10-10T18:00:26Z" }, { "login": "flyyangX", @@ -648,14 +648,14 @@ "login": "Elvis33LE", "people_entry": true, "github_name": "Elvis33LE", - "prs": 29, - "commits": 31, - "lines_added": 8395, - "lines_deleted": 610, + "prs": 36, + "commits": 38, + "lines_added": 10956, + "lines_deleted": 890, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-07T13:11:45Z", - "last_commit": "2026-10-09T22:51:33Z" + "last_commit": "2026-10-10T21:57:51Z" }, { "login": "cristianmoroaica", @@ -739,14 +739,14 @@ "login": "tanish2k09", "people_entry": false, "github_name": null, - "prs": 17, - "commits": 17, - "lines_added": 1254, - "lines_deleted": 169, + "prs": 19, + "commits": 19, + "lines_added": 1859, + "lines_deleted": 197, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-07T20:39:39Z", - "last_commit": "2026-10-09T23:55:18Z" + "last_commit": "2026-10-10T08:00:10Z" }, { "login": "jerrykimo", @@ -908,40 +908,40 @@ "login": "harrisonoconnorhover", "people_entry": false, "github_name": null, - "prs": 9, - "commits": 12, - "lines_added": 2445, - "lines_deleted": 221, + "prs": 22, + "commits": 25, + "lines_added": 5348, + "lines_deleted": 450, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-08T13:25:19Z", - "last_commit": "2026-10-09T23:50:53Z" + "last_commit": "2026-10-10T17:40:51Z" }, { "login": "MarekSpodBiedry", "people_entry": false, "github_name": null, - "prs": 27, - "commits": 32, - "lines_added": 1370, - "lines_deleted": 129, + "prs": 36, + "commits": 41, + "lines_added": 1683, + "lines_deleted": 207, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-08T13:44:48Z", - "last_commit": "2026-10-09T19:33:39Z" + "last_commit": "2026-10-10T21:19:47Z" }, { "login": "callmeBalloch", "people_entry": false, "github_name": null, - "prs": 0, - "commits": 12, - "lines_added": 5865, - "lines_deleted": 650, + "prs": 1, + "commits": 13, + "lines_added": 6062, + "lines_deleted": 652, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-08T15:42:23Z", - "last_commit": "2026-10-09T07:44:22Z" + "last_commit": "2026-10-10T17:14:59Z" }, { "login": "marcardenas", @@ -973,14 +973,14 @@ "login": "switch87", "people_entry": true, "github_name": null, - "prs": 10, - "commits": 11, - "lines_added": 5435, - "lines_deleted": 162, + "prs": 12, + "commits": 13, + "lines_added": 5689, + "lines_deleted": 179, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-08T17:37:11Z", - "last_commit": "2026-10-09T23:25:36Z" + "last_commit": "2026-10-10T21:51:20Z" }, { "login": "wstock", @@ -1116,40 +1116,40 @@ "login": "roaldosulejmani", "people_entry": false, "github_name": null, - "prs": 2, - "commits": 2, - "lines_added": 258, - "lines_deleted": 103, + "prs": 3, + "commits": 3, + "lines_added": 427, + "lines_deleted": 105, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-08T20:08:22Z", - "last_commit": "2026-10-09T20:59:07Z" + "last_commit": "2026-10-10T17:39:07Z" }, { "login": "buivanvu94", "people_entry": false, "github_name": null, - "prs": 4, - "commits": 6, - "lines_added": 291, - "lines_deleted": 82, + "prs": 5, + "commits": 7, + "lines_added": 385, + "lines_deleted": 86, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-08T20:09:38Z", - "last_commit": "2026-10-09T15:08:13Z" + "last_commit": "2026-10-10T17:55:43Z" }, { "login": "shorbank", "people_entry": false, "github_name": null, - "prs": 3, - "commits": 3, - "lines_added": 2468, - "lines_deleted": 267, + "prs": 4, + "commits": 4, + "lines_added": 3576, + "lines_deleted": 329, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-08T20:19:19Z", - "last_commit": "2026-10-09T17:44:24Z" + "last_commit": "2026-10-10T02:03:51Z" }, { "login": "prekabreki", @@ -1168,14 +1168,14 @@ "login": "Unemars", "people_entry": false, "github_name": null, - "prs": 10, - "commits": 10, - "lines_added": 3758, - "lines_deleted": 619, + "prs": 11, + "commits": 11, + "lines_added": 4919, + "lines_deleted": 905, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-08T20:19:39Z", - "last_commit": "2026-10-09T20:21:27Z" + "last_commit": "2026-10-10T10:08:47Z" }, { "login": "Powiadomienie", @@ -1194,14 +1194,14 @@ "login": "llduyll10", "people_entry": false, "github_name": null, - "prs": 2, - "commits": 2, - "lines_added": 82, - "lines_deleted": 7, + "prs": 3, + "commits": 3, + "lines_added": 178, + "lines_deleted": 23, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-08T20:38:35Z", - "last_commit": "2026-10-09T11:00:43Z" + "last_commit": "2026-10-10T22:03:32Z" }, { "login": "cold-atom", @@ -1246,14 +1246,14 @@ "login": "optimalbytee", "people_entry": false, "github_name": null, - "prs": 6, - "commits": 6, - "lines_added": 3632, - "lines_deleted": 63, + "prs": 9, + "commits": 9, + "lines_added": 6032, + "lines_deleted": 133, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-08T21:04:45Z", - "last_commit": "2026-10-09T20:30:52Z" + "last_commit": "2026-10-10T18:00:53Z" }, { "login": "LordFarquaadtheCreator", @@ -1285,27 +1285,27 @@ "login": "reynold-hu", "people_entry": true, "github_name": "Reynold Hu", - "prs": 14, - "commits": 14, - "lines_added": 777, - "lines_deleted": 116, + "prs": 17, + "commits": 17, + "lines_added": 944, + "lines_deleted": 152, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-08T22:28:12Z", - "last_commit": "2026-10-09T19:45:20Z" + "last_commit": "2026-10-10T21:53:25Z" }, { "login": "kayrockscreenprinting", "people_entry": false, "github_name": null, - "prs": 34, - "commits": 34, - "lines_added": 3411, - "lines_deleted": 249, + "prs": 35, + "commits": 35, + "lines_added": 3666, + "lines_deleted": 273, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-08T22:28:29Z", - "last_commit": "2026-10-09T23:20:10Z" + "last_commit": "2026-10-10T18:01:06Z" }, { "login": "jeremyfry", @@ -1428,27 +1428,27 @@ "login": "davidmann4", "people_entry": false, "github_name": null, - "prs": 29, - "commits": 30, - "lines_added": 8442, - "lines_deleted": 568, + "prs": 44, + "commits": 45, + "lines_added": 12472, + "lines_deleted": 861, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-09T01:49:29Z", - "last_commit": "2026-10-09T23:46:07Z" + "last_commit": "2026-10-10T18:14:19Z" }, { "login": "Jeremy8776", "people_entry": false, "github_name": null, - "prs": 2, - "commits": 2, - "lines_added": 573, - "lines_deleted": 42, + "prs": 4, + "commits": 4, + "lines_added": 1584, + "lines_deleted": 177, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-09T02:01:45Z", - "last_commit": "2026-10-09T17:04:27Z" + "last_commit": "2026-10-10T18:22:46Z" }, { "login": "fplachecinski", @@ -1480,14 +1480,14 @@ "login": "kubuntugamer", "people_entry": false, "github_name": null, - "prs": 1, - "commits": 3, - "lines_added": 170, - "lines_deleted": 8, + "prs": 2, + "commits": 4, + "lines_added": 469, + "lines_deleted": 93, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-09T03:28:06Z", - "last_commit": "2026-10-09T06:24:14Z" + "last_commit": "2026-10-10T09:49:07Z" }, { "login": "mrjeye", @@ -1519,14 +1519,14 @@ "login": "0x6Ason", "people_entry": false, "github_name": null, - "prs": 7, - "commits": 7, - "lines_added": 1259, - "lines_deleted": 66, + "prs": 8, + "commits": 8, + "lines_added": 1710, + "lines_deleted": 70, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-09T04:54:37Z", - "last_commit": "2026-10-09T17:20:34Z" + "last_commit": "2026-10-10T08:57:56Z" }, { "login": "agincel", @@ -1545,14 +1545,14 @@ "login": "SBaksa", "people_entry": false, "github_name": null, - "prs": 1, - "commits": 1, - "lines_added": 52, - "lines_deleted": 10, + "prs": 2, + "commits": 2, + "lines_added": 149, + "lines_deleted": 28, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-09T06:24:21Z", - "last_commit": "2026-10-09T06:24:21Z" + "last_commit": "2026-10-10T09:53:23Z" }, { "login": "dhiorns15", @@ -1571,14 +1571,14 @@ "login": "hideoneric", "people_entry": false, "github_name": null, - "prs": 2, - "commits": 2, - "lines_added": 203, - "lines_deleted": 20, + "prs": 3, + "commits": 3, + "lines_added": 534, + "lines_deleted": 48, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-09T06:24:27Z", - "last_commit": "2026-10-09T11:00:39Z" + "last_commit": "2026-10-10T17:15:18Z" }, { "login": "yearth", @@ -1597,14 +1597,14 @@ "login": "Duke242", "people_entry": false, "github_name": null, - "prs": 1, - "commits": 1, - "lines_added": 22, - "lines_deleted": 10, + "prs": 2, + "commits": 2, + "lines_added": 29, + "lines_deleted": 17, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-09T13:04:22Z", - "last_commit": "2026-10-09T13:04:22Z" + "last_commit": "2026-10-10T06:04:18Z" }, { "login": "AlanRockefeller", @@ -1662,53 +1662,53 @@ "login": "Sir-Starch", "people_entry": false, "github_name": null, - "prs": 4, - "commits": 4, - "lines_added": 1036, - "lines_deleted": 21, + "prs": 10, + "commits": 10, + "lines_added": 3095, + "lines_deleted": 346, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-09T15:51:36Z", - "last_commit": "2026-10-09T23:39:45Z" + "last_commit": "2026-10-10T23:01:53Z" }, { "login": "xsvm", "people_entry": false, "github_name": null, - "prs": 1, - "commits": 1, - "lines_added": 14, - "lines_deleted": 5, + "prs": 3, + "commits": 3, + "lines_added": 162, + "lines_deleted": 10, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-09T16:02:04Z", - "last_commit": "2026-10-09T16:02:04Z" + "last_commit": "2026-10-10T22:37:25Z" }, { "login": "texjer", "people_entry": false, "github_name": null, - "prs": 1, - "commits": 1, - "lines_added": 21, - "lines_deleted": 16, + "prs": 7, + "commits": 7, + "lines_added": 2267, + "lines_deleted": 259, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-09T16:02:30Z", - "last_commit": "2026-10-09T16:02:30Z" + "last_commit": "2026-10-10T18:01:17Z" }, { "login": "maxm11", "people_entry": true, "github_name": "Max Murphy", - "prs": 5, - "commits": 5, - "lines_added": 531, - "lines_deleted": 125, + "prs": 8, + "commits": 8, + "lines_added": 974, + "lines_deleted": 139, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-09T16:03:52Z", - "last_commit": "2026-10-10T00:34:31Z" + "last_commit": "2026-10-10T17:08:06Z" }, { "login": "dmatviichuk", @@ -1844,14 +1844,14 @@ "login": "rossaai", "people_entry": false, "github_name": null, - "prs": 1, - "commits": 1, - "lines_added": 33, - "lines_deleted": 5, + "prs": 2, + "commits": 2, + "lines_added": 128, + "lines_deleted": 31, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-09T19:17:06Z", - "last_commit": "2026-10-09T19:17:06Z" + "last_commit": "2026-10-10T01:47:12Z" }, { "login": "joe2643", @@ -1870,27 +1870,27 @@ "login": "LloydNicholson", "people_entry": false, "github_name": null, - "prs": 1, - "commits": 1, - "lines_added": 78, - "lines_deleted": 11, + "prs": 2, + "commits": 2, + "lines_added": 117, + "lines_deleted": 14, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-09T19:43:14Z", - "last_commit": "2026-10-09T19:43:14Z" + "last_commit": "2026-10-10T17:16:26Z" }, { "login": "Hathor875", "people_entry": true, "github_name": "Krzysztof Cieślik", - "prs": 1, - "commits": 1, - "lines_added": 129, - "lines_deleted": 20, + "prs": 3, + "commits": 3, + "lines_added": 232, + "lines_deleted": 34, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-09T20:03:44Z", - "last_commit": "2026-10-09T20:03:44Z" + "last_commit": "2026-10-10T06:35:51Z" }, { "login": "raghav2005", @@ -1909,27 +1909,27 @@ "login": "skraus2", "people_entry": true, "github_name": "Simon", - "prs": 1, - "commits": 1, - "lines_added": 401, - "lines_deleted": 14, + "prs": 3, + "commits": 3, + "lines_added": 804, + "lines_deleted": 37, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-09T20:34:01Z", - "last_commit": "2026-10-09T20:34:01Z" + "last_commit": "2026-10-10T17:40:30Z" }, { "login": "alex-ctms", "people_entry": false, "github_name": null, - "prs": 2, - "commits": 2, - "lines_added": 351, - "lines_deleted": 32, + "prs": 3, + "commits": 3, + "lines_added": 567, + "lines_deleted": 62, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-09T20:56:24Z", - "last_commit": "2026-10-09T23:27:35Z" + "last_commit": "2026-10-10T07:58:08Z" }, { "login": "zenjabba", @@ -1961,14 +1961,14 @@ "login": "excited-raccoon", "people_entry": true, "github_name": "Ayan", - "prs": 2, - "commits": 2, - "lines_added": 850, - "lines_deleted": 67, + "prs": 5, + "commits": 5, + "lines_added": 3399, + "lines_deleted": 181, "binary_added": 0, "binary_deleted": 0, "first_commit": "2026-10-09T23:28:33Z", - "last_commit": "2026-10-09T23:34:26Z" + "last_commit": "2026-10-10T18:17:48Z" }, { "login": "hamada147", @@ -1995,6 +1995,474 @@ "binary_deleted": 0, "first_commit": "2026-10-10T00:05:26Z", "last_commit": "2026-10-10T00:05:26Z" + }, + { + "login": "SilentYeti", + "people_entry": true, + "github_name": null, + "prs": 1, + "commits": 1, + "lines_added": 1461, + "lines_deleted": 29, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T01:05:00Z", + "last_commit": "2026-10-10T01:05:00Z" + }, + { + "login": "shivthedev-92", + "people_entry": false, + "github_name": null, + "prs": 1, + "commits": 1, + "lines_added": 214, + "lines_deleted": 7, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T01:08:12Z", + "last_commit": "2026-10-10T01:08:12Z" + }, + { + "login": "luniiya", + "people_entry": false, + "github_name": null, + "prs": 4, + "commits": 4, + "lines_added": 869, + "lines_deleted": 120, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T01:14:37Z", + "last_commit": "2026-10-10T18:01:27Z" + }, + { + "login": "mroxso", + "people_entry": false, + "github_name": null, + "prs": 4, + "commits": 4, + "lines_added": 410, + "lines_deleted": 30, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T01:43:59Z", + "last_commit": "2026-10-10T21:57:41Z" + }, + { + "login": "sawizzle", + "people_entry": false, + "github_name": null, + "prs": 1, + "commits": 1, + "lines_added": 17, + "lines_deleted": 0, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T04:59:34Z", + "last_commit": "2026-10-10T04:59:34Z" + }, + { + "login": "Benziza", + "people_entry": false, + "github_name": null, + "prs": 2, + "commits": 2, + "lines_added": 98, + "lines_deleted": 15, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T05:08:52Z", + "last_commit": "2026-10-10T19:16:42Z" + }, + { + "login": "crqch", + "people_entry": false, + "github_name": null, + "prs": 1, + "commits": 1, + "lines_added": 22, + "lines_deleted": 11, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T05:26:48Z", + "last_commit": "2026-10-10T05:26:48Z" + }, + { + "login": "vbasky", + "people_entry": false, + "github_name": null, + "prs": 1, + "commits": 1, + "lines_added": 159, + "lines_deleted": 11, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T05:42:28Z", + "last_commit": "2026-10-10T05:42:28Z" + }, + { + "login": "kmnkv1", + "people_entry": false, + "github_name": null, + "prs": 2, + "commits": 2, + "lines_added": 14, + "lines_deleted": 4, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T05:43:42Z", + "last_commit": "2026-10-10T05:43:46Z" + }, + { + "login": "tropicaaal", + "people_entry": false, + "github_name": null, + "prs": 3, + "commits": 3, + "lines_added": 211, + "lines_deleted": 214, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T05:57:01Z", + "last_commit": "2026-10-10T08:04:26Z" + }, + { + "login": "kotulsky", + "people_entry": false, + "github_name": null, + "prs": 2, + "commits": 2, + "lines_added": 482, + "lines_deleted": 9, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T06:01:55Z", + "last_commit": "2026-10-10T06:10:24Z" + }, + { + "login": "MrCloudy2", + "people_entry": false, + "github_name": null, + "prs": 8, + "commits": 8, + "lines_added": 706, + "lines_deleted": 58, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T08:12:17Z", + "last_commit": "2026-10-10T17:16:20Z" + }, + { + "login": "JohnnYoru", + "people_entry": false, + "github_name": null, + "prs": 1, + "commits": 1, + "lines_added": 2005, + "lines_deleted": 25, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T09:19:11Z", + "last_commit": "2026-10-10T09:19:11Z" + }, + { + "login": "scottcampbelldata", + "people_entry": false, + "github_name": null, + "prs": 1, + "commits": 1, + "lines_added": 1331, + "lines_deleted": 19, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T12:40:35Z", + "last_commit": "2026-10-10T12:40:35Z" + }, + { + "login": "vangel76", + "people_entry": true, + "github_name": "Valentin Klein", + "prs": 41, + "commits": 41, + "lines_added": 3018, + "lines_deleted": 348, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T17:08:36Z", + "last_commit": "2026-10-10T23:04:19Z" + }, + { + "login": "KausBoss", + "people_entry": false, + "github_name": null, + "prs": 3, + "commits": 3, + "lines_added": 98, + "lines_deleted": 2, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T17:11:40Z", + "last_commit": "2026-10-10T17:12:04Z" + }, + { + "login": "vivekprojects-GIT", + "people_entry": false, + "github_name": null, + "prs": 2, + "commits": 2, + "lines_added": 298, + "lines_deleted": 18, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T17:11:42Z", + "last_commit": "2026-10-10T17:11:59Z" + }, + { + "login": "reneleonhardt", + "people_entry": false, + "github_name": null, + "prs": 1, + "commits": 1, + "lines_added": 259, + "lines_deleted": 25, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T17:11:54Z", + "last_commit": "2026-10-10T17:11:54Z" + }, + { + "login": "itrycodinganditsbad", + "people_entry": false, + "github_name": null, + "prs": 17, + "commits": 17, + "lines_added": 2484, + "lines_deleted": 223, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T17:12:35Z", + "last_commit": "2026-10-10T23:09:26Z" + }, + { + "login": "itsF4LCON", + "people_entry": true, + "github_name": null, + "prs": 2, + "commits": 2, + "lines_added": 267, + "lines_deleted": 16, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T17:13:40Z", + "last_commit": "2026-10-10T20:49:34Z" + }, + { + "login": "bitshiftza", + "people_entry": false, + "github_name": null, + "prs": 6, + "commits": 6, + "lines_added": 509, + "lines_deleted": 35, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T17:14:46Z", + "last_commit": "2026-10-10T18:34:49Z" + }, + { + "login": "fabianghe", + "people_entry": false, + "github_name": null, + "prs": 2, + "commits": 2, + "lines_added": 420, + "lines_deleted": 8, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T17:14:52Z", + "last_commit": "2026-10-10T19:59:34Z" + }, + { + "login": "juswus2000", + "people_entry": false, + "github_name": null, + "prs": 1, + "commits": 1, + "lines_added": 24, + "lines_deleted": 4, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T17:16:14Z", + "last_commit": "2026-10-10T17:16:14Z" + }, + { + "login": "kavishkashehan726-sudo", + "people_entry": false, + "github_name": null, + "prs": 2, + "commits": 2, + "lines_added": 166, + "lines_deleted": 20, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T17:16:32Z", + "last_commit": "2026-10-10T21:11:46Z" + }, + { + "login": "m6502", + "people_entry": false, + "github_name": null, + "prs": 1, + "commits": 1, + "lines_added": 115, + "lines_deleted": 9, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T17:17:38Z", + "last_commit": "2026-10-10T17:17:38Z" + }, + { + "login": "Lyraedan", + "people_entry": false, + "github_name": null, + "prs": 1, + "commits": 1, + "lines_added": 46, + "lines_deleted": 3, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T17:33:53Z", + "last_commit": "2026-10-10T17:33:53Z" + }, + { + "login": "Erica4fr", + "people_entry": true, + "github_name": "Erica Franco", + "prs": 3, + "commits": 3, + "lines_added": 84, + "lines_deleted": 23, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T17:38:12Z", + "last_commit": "2026-10-10T18:46:28Z" + }, + { + "login": "Trade-Mottoes", + "people_entry": false, + "github_name": null, + "prs": 1, + "commits": 1, + "lines_added": 63, + "lines_deleted": 0, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T17:38:33Z", + "last_commit": "2026-10-10T17:38:33Z" + }, + { + "login": "Geljic", + "people_entry": false, + "github_name": null, + "prs": 1, + "commits": 1, + "lines_added": 257, + "lines_deleted": 0, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T18:16:24Z", + "last_commit": "2026-10-10T18:16:24Z" + }, + { + "login": "seldoms", + "people_entry": false, + "github_name": null, + "prs": 1, + "commits": 1, + "lines_added": 18, + "lines_deleted": 2, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T21:10:36Z", + "last_commit": "2026-10-10T21:10:36Z" + }, + { + "login": "twentymls", + "people_entry": false, + "github_name": null, + "prs": 1, + "commits": 1, + "lines_added": 365, + "lines_deleted": 26, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T21:38:59Z", + "last_commit": "2026-10-10T21:38:59Z" + }, + { + "login": "zi-ger", + "people_entry": false, + "github_name": null, + "prs": 1, + "commits": 1, + "lines_added": 51, + "lines_deleted": 1, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T22:10:12Z", + "last_commit": "2026-10-10T22:10:12Z" + }, + { + "login": "arthurdeka", + "people_entry": false, + "github_name": null, + "prs": 2, + "commits": 2, + "lines_added": 186, + "lines_deleted": 3, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T22:18:19Z", + "last_commit": "2026-10-10T22:22:30Z" + }, + { + "login": "ahmedhosnypro", + "people_entry": false, + "github_name": null, + "prs": 1, + "commits": 1, + "lines_added": 34, + "lines_deleted": 12, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T22:27:03Z", + "last_commit": "2026-10-10T22:27:03Z" + }, + { + "login": "FinnNk", + "people_entry": true, + "github_name": null, + "prs": 1, + "commits": 1, + "lines_added": 97, + "lines_deleted": 12, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T22:56:04Z", + "last_commit": "2026-10-10T22:56:04Z" + }, + { + "login": "diax7", + "people_entry": false, + "github_name": null, + "prs": 1, + "commits": 1, + "lines_added": 140, + "lines_deleted": 28, + "binary_added": 0, + "binary_deleted": 0, + "first_commit": "2026-10-10T23:06:05Z", + "last_commit": "2026-10-10T23:06:05Z" } ], "models": [ @@ -2003,18 +2471,18 @@ "company": "Anthropic", "model": "Claude Opus", "version": "5.5", - "commits": 591, - "lines_added": 244448, - "lines_deleted": 28906 + "commits": 736, + "lines_added": 270451, + "lines_deleted": 31636 }, { "id": "anthropic/claude", "company": "Anthropic", "model": "Claude", "version": "", - "commits": 48, - "lines_added": 2292, - "lines_deleted": 232 + "commits": 49, + "lines_added": 2547, + "lines_deleted": 256 }, { "id": "anthropic/claude-opus/4.8", @@ -2057,9 +2525,9 @@ "company": "Anthropic", "model": "Claude Sonnet", "version": "5.5", - "commits": 2, - "lines_added": 4161, - "lines_deleted": 1171 + "commits": 3, + "lines_added": 4220, + "lines_deleted": 1172 }, { "id": "openai/gpt/6", diff --git a/crates/ui-egui/src/canvas.rs b/crates/ui-egui/src/canvas.rs index 7de7b1de9..3cd4d294d 100644 --- a/crates/ui-egui/src/canvas.rs +++ b/crates/ui-egui/src/canvas.rs @@ -265,6 +265,15 @@ pub(crate) fn marquee_ants(xf: &ViewXform, tool: Tool, a: [f64; 2], b: [f64; 2]) if tool != Tool::EllipseMarquee { return vec![at(x0, y0), at(x1, y0), at(x1, y1), at(x0, y1)]; } + // An axis-aligned view (rotation a multiple of 90 degrees) maps the ellipse onto the one + // inscribed in the snapped screen box of two opposite corners. Draw that, unsnapped: snapping + // each vertex on its own turns the nearly flat arcs at the edge midpoints into 1 px stairs, + // whose antialiased steps wash the ants out to grey on white and black. + let quarter = xf.rotation.rem_euclid(90.0); + if quarter < 1e-4 || 90.0 - quarter < 1e-4 { + let r = Rect::from_two_pos(at(x0, y0), at(x1, y1)); + return crate::tool_feedback::ellipse_points(r); + } // As many vertices as the same ellipse would get drawn on screen (`ellipse_points`). let scr = Rect::from_points(&[xf.to_screen(x0 as f32, y0 as f32), xf.to_screen(x1 as f32, y1 as f32)]); let n = (((scr.width() + scr.height()) * 0.25) as usize).clamp(16, 256); diff --git a/docs/releasing.md b/docs/releasing.md index 5a023c4c9..12cb224c3 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -53,6 +53,7 @@ in the dialog. | Windows 10+ x86 (32-bit) | `photocraft--windows-x86.msi`, `photocraft--windows-x86-portable.zip` | `windows-latest` | | Linux x86_64 | `photocraft--linux-x86_64.{AppImage,AppImage.zsync,deb,rpm,tar.gz,flatpak}` | `ubuntu-22.04` (Flatpak: `ubuntu-24.04`) | | Linux aarch64 | `photocraft--linux-aarch64.{AppImage,AppImage.zsync,deb,rpm,tar.gz,flatpak}` | `ubuntu-22.04-arm` (Flatpak: `ubuntu-24.04-arm`) | +| Linux riscv64 (glibc 2.39+) | `photocraft--linux-riscv64.tar.gz` | cross-compiled on `ubuntu-24.04` (ports.ubuntu.com riscv64 libs); CLI smoke-tested under QEMU | | FreeBSD 14 x86_64 | `photocraft--freebsd-x86_64.tar.gz` | FreeBSD 14.3 VM on `ubuntu-latest` | | Web | `photocraft-web-.zip` (static site; see [`packaging/web/README.md`](../packaging/web/README.md)) | `ubuntu-latest` | diff --git a/packaging/linux/package.sh b/packaging/linux/package.sh index 2cd7044b7..c5e003e04 100755 --- a/packaging/linux/package.sh +++ b/packaging/linux/package.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Build and package PhotoCraft for Linux ( is x86_64 or aarch64): +# Build and package PhotoCraft for Linux ( is x86_64, aarch64 or riscv64): # # $DIST/photocraft--linux-.AppImage any distro with glibc >= the build host's # $DIST/photocraft--linux-.AppImage.zsync delta updates (needs zsyncmake) @@ -13,6 +13,10 @@ # (downloaded into $CARGO_TARGET_DIR if missing). Build on an old distro (CI: Ubuntu 22.04, # glibc 2.35) so the binaries run on newer ones. Optional: desktop-file-validate, appstreamcli, # zsyncmake (the zsync package) for the AppImage's .zsync. +# +# Cross builds (CI: riscv64, tar.gz only): set CROSS_ARCH (riscv64), CROSS_TARGET (the Rust +# triple), CROSS_COMPILE (binutils prefix, for strip) and optionally EMULATOR (e.g. qemu-riscv64) +# to smoke-test the CLI. set -euo pipefail # shellcheck source=../env.sh . "$(dirname "${BASH_SOURCE[0]}")/../env.sh" @@ -25,13 +29,14 @@ while [ $# -gt 0 ]; do case "$1" in --skip-build) SKIP_BUILD=1; shift ;; --formats) FORMATS="$2"; shift 2 ;; - -h | --help) sed -n '2,15p' "$0"; exit 0 ;; + -h | --help) sed -n '2,19p' "$0"; exit 0 ;; *) echo "unknown argument: $1" >&2; exit 2 ;; esac done -ARCH="$(uname -m)" +ARCH="${CROSS_ARCH:-$(uname -m)}" case "$ARCH" in + riscv64) DEB_ARCH=riscv64 ;; x86_64) DEB_ARCH=amd64 ;; aarch64 | arm64) ARCH=aarch64; DEB_ARCH=arm64 ;; *) echo "unsupported architecture $ARCH" >&2; exit 2 ;; @@ -42,9 +47,13 @@ BASENAME="photocraft-$VERSION-linux-$ARCH" echo "==> PhotoCraft $VERSION for Linux $ARCH ($FORMATS)" if [ "$SKIP_BUILD" = 0 ]; then - (cd "$ROOT" && cargo build --release --locked -p photocraft -p photocraft-cli --features heif) + if [ -n "${CROSS_TARGET:-}" ]; then + (cd "$ROOT" && cargo build --release --locked -p photocraft -p photocraft-cli --features heif --target "$CROSS_TARGET") + else + (cd "$ROOT" && cargo build --release --locked -p photocraft -p photocraft-cli --features heif) + fi fi -BIN="$CARGO_TARGET_DIR/release" +BIN="$CARGO_TARGET_DIR/${CROSS_TARGET:+$CROSS_TARGET/}release" WORK="$CARGO_TARGET_DIR/linux-package" STAGE="$WORK/root" rm -rf "$WORK" @@ -52,7 +61,7 @@ rm -rf "$WORK" # ---- stage an FHS tree (shared by every format) ------------------------------------------------- install -Dm755 "$BIN/photocraft" "$STAGE/usr/bin/photocraft" install -Dm755 "$BIN/photocraft-cli" "$STAGE/usr/bin/photocraft-cli" -strip "$STAGE/usr/bin/photocraft" "$STAGE/usr/bin/photocraft-cli" 2>/dev/null || true +"${CROSS_COMPILE:-}strip" "$STAGE/usr/bin/photocraft" "$STAGE/usr/bin/photocraft-cli" 2>/dev/null || true install -Dm644 "$HERE/$APP_ID.desktop" "$STAGE/usr/share/applications/$APP_ID.desktop" install -Dm644 "$HERE/$APP_ID.mime.xml" "$STAGE/usr/share/mime/packages/$APP_ID.xml" mkdir -p "$STAGE/usr/share/metainfo" @@ -139,6 +148,10 @@ if has appimage; then fi fi -"$STAGE/usr/bin/photocraft-cli" --version +if [ -z "${CROSS_TARGET:-}" ]; then + "$STAGE/usr/bin/photocraft-cli" --version +elif [ -n "${EMULATOR:-}" ]; then + "$EMULATOR" "$STAGE/usr/bin/photocraft-cli" --version +fi echo "==> done" ls -lh "$DIST"