From 5826377d170091ad5f47a98d27248a00fe660e5b Mon Sep 17 00:00:00 2001 From: Xus Badia Date: Thu, 8 Oct 2026 15:12:32 +0200 Subject: [PATCH] macOS DMG: branded window background and icon layout The DMG opened as a plain Finder window. It now shows the app icon's figure on the EffectCraft colour, with EffectCraft.app and the Applications link side by side. - packaging/macos/dmg/: background.svg (source; text outlined, the figure an of assets/app-icon) and dmg-layout.DS_Store (Finder view settings: window, icon size 128, positions, background), written by generate.py on any OS, byte-for-byte reproducible, with nothing from the machine that ran it. - package.sh renders the SVG with resvg (1x + 2x) into a HiDPI TIFF at package time, so no bitmap is committed; release.yml installs resvg 0.48.1 (pinned, --locked) on the macOS runner. The image is still built with hdiutil makehybrid. - The volume name drops the version: the layout finds the background through an alias that includes the volume name. The DMG file name keeps the version. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/release.yml | 3 + ATTRIBUTION.md | 1 + packaging/macos/dmg/README.md | 44 +++++++++ packaging/macos/dmg/background.svg | 31 +++++++ .../macos/dmg/background.svg.attribution | 8 ++ packaging/macos/dmg/dmg-layout.DS_Store | Bin 0 -> 16388 bytes packaging/macos/dmg/generate.py | 87 ++++++++++++++++++ packaging/macos/package.sh | 12 ++- 8 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 packaging/macos/dmg/README.md create mode 100644 packaging/macos/dmg/background.svg create mode 100644 packaging/macos/dmg/background.svg.attribution create mode 100644 packaging/macos/dmg/dmg-layout.DS_Store create mode 100644 packaging/macos/dmg/generate.py diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1abb43f4..5bbe69d9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -88,6 +88,9 @@ jobs: APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} run: packaging/macos/import-cert.sh + # Renders the DMG background from packaging/macos/dmg/background.svg (package.sh). + - name: Install resvg + run: cargo install resvg --locked --version 0.48.1 - name: Build, sign, notarize env: APPLE_ID: ${{ secrets.APPLE_ID }} diff --git a/ATTRIBUTION.md b/ATTRIBUTION.md index f203522e..6e23b06e 100644 --- a/ATTRIBUTION.md +++ b/ATTRIBUTION.md @@ -17,6 +17,7 @@ iconography, images or other Adobe assets; open licences only; every asset attri | `assets/fonts/NotoSerif-Regular.ttf` | The Noto Project Authors | https://github.com/notofonts/latin-greek-cyrillic | OFL-1.1 (`assets/fonts/OFL-NotoSerif.txt`) | | `assets/fonts/JetBrainsMono-Regular.ttf` | The JetBrains Mono Project Authors | https://github.com/JetBrains/JetBrainsMono | OFL-1.1 (`assets/fonts/OFL-JetBrainsMono.txt`) | | `apps/effectcraft-web/web/favicon.svg` | EffectCraft contributors | Original work: web app icon, a copy of `assets/app-icon/effectcraft-small.svg` (the unicorn app icon) | MIT OR Apache-2.0 (`assets/app-icon/LICENSE.txt`) | +| `packaging/macos/dmg/background.svg` | @XusBadia | Original work: macOS DMG Finder window background, derived from the EffectCraft app icon (`assets/app-icon/effectcraft.svg`); rendered to a TIFF by `packaging/macos/package.sh` at package time | MIT OR Apache-2.0 (`LICENSE-MIT`, `LICENSE-APACHE`) | | `assets/app-icon/effectcraft-1024.png` | EffectCraft contributors | Original work: effectCraft app icon, 1024 px (owner's ArtCraft unicorn drawing, vectorised) | MIT OR Apache-2.0 (`assets/app-icon/LICENSE.txt`) | | `assets/app-icon/effectcraft-macos-512.png` | EffectCraft contributors | Original work: effectCraft runtime Dock icon (macOS) (owner's ArtCraft unicorn drawing, vectorised) | MIT OR Apache-2.0 (`assets/app-icon/LICENSE.txt`) | | `assets/app-icon/effectcraft-small.svg` | EffectCraft contributors | Original work: effectCraft app icon, light vector (owner's ArtCraft unicorn drawing, vectorised) | MIT OR Apache-2.0 (`assets/app-icon/LICENSE.txt`) | diff --git a/packaging/macos/dmg/README.md b/packaging/macos/dmg/README.md new file mode 100644 index 00000000..b3b085aa --- /dev/null +++ b/packaging/macos/dmg/README.md @@ -0,0 +1,44 @@ +# macOS DMG window + +What Finder shows when the DMG opens: a 660 × 400 pt background with the app icon and the +`Applications` link side by side. `package.sh` renders the background from `background.svg` and copies it +and the layout into the image, so no bitmap is committed. The DMG still builds with +`hdiutil makehybrid` (no mounted device, no Finder scripting on CI). + +| File | What | +|---|---| +| `background.svg` | Source of the background: the app icon (`assets/app-icon/effectcraft.svg`, linked, not copied) cropped as a cover on the EffectCraft colour field (`#e0368f`), Ink and Paper. Its text (Inter, JetBrains Mono) is outlined, so rendering it needs no fonts. `package.sh` renders it with [resvg](https://github.com/linebender/resvg) 0.48.1 at 1x (660 × 400 px) and 2x (1320 × 800 px) and joins both into `.background/background.tiff` (`tiffutil -cathidpicheck`); `release.yml` installs that resvg on the macOS runner. | +| `dmg-layout.DS_Store` | Finder's view settings for the volume: window size, icon size 128, EffectCraft.app at (326, 205), `Applications` at (574, 205), and the background. Goes to `.DS_Store` in the image; named so it isn't mistaken for (or ignored like) a Finder-generated `.DS_Store`. | +| `generate.py` | Writes `dmg-layout.DS_Store` from the layout above. | + +## The volume name has no version + +The mounted volume is called `EffectCraft`, not `EffectCraft `. The layout points at the background +through an alias that includes the volume name, and Finder resolves it by that name: with a +versioned name the window keeps its size and icon positions but shows no background (tested). +The DMG file name (`effectcraft--macos-.dmg`) still carries the version. + +## Rules + +- **Finder draws the icon labels in black in light and dark mode** when a window has a background, + so the area under both icons stays light (Paper). +- **Nothing goes inside the icon boxes:** artwork keeps 10 pt clear of each 128 pt icon box and of + the label strip under it. + +## Regenerate + +- **The background:** edit `background.svg`. `package.sh` renders it on every build; to preview it, + `resvg --skip-system-fonts -w 1320 background.svg /tmp/bg@2x.png`. If you add text, outline it + (`usvg` from resvg converts text to paths), since no fonts are loaded. +- **The layout:** edit the constants in `generate.py`, then run, on any OS: + + ```sh + pip install ds_store==1.3.3 mac_alias==2.2.3 + python3 packaging/macos/dmg/generate.py + ``` + + `dmg-layout.DS_Store` is written from scratch and byte-for-byte reproducible: its background + alias holds only the volume name and `/.background/background.tiff`, nothing from the machine that + ran it. The window is 660 × 432 with Finder's 32 pt title bar; the content area is 660 × 400. + +This follows VectorCraft's `packaging/macos/dmg/` (storytold/vectorcraft#493). diff --git a/packaging/macos/dmg/background.svg b/packaging/macos/dmg/background.svg new file mode 100644 index 00000000..1ce5a512 --- /dev/null +++ b/packaging/macos/dmg/background.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packaging/macos/dmg/background.svg.attribution b/packaging/macos/dmg/background.svg.attribution new file mode 100644 index 00000000..c488cf5d --- /dev/null +++ b/packaging/macos/dmg/background.svg.attribution @@ -0,0 +1,8 @@ +asset: background.svg +title: EffectCraft macOS DMG window background +author: @XusBadia +source: original work +license: MIT OR Apache-2.0 +license-file: LICENSE-MIT, LICENSE-APACHE +added: 2026-10-08 by @XusBadia +notes: Original work for this repository, derived from the EffectCraft app icon (assets/app-icon/effectcraft.svg, referenced via , not copied). Used for the Finder window of the macOS DMG; packaging/macos/package.sh renders it to a TIFF at package time. Text is outlined Inter/JetBrains Mono glyph paths. diff --git a/packaging/macos/dmg/dmg-layout.DS_Store b/packaging/macos/dmg/dmg-layout.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..919d960b6e02f1a34816daa51da40495992fd68d GIT binary patch literal 16388 zcmeI2O>7fK6oB7sLUC|{*Kr^T?ZK6W1R`=w_z~jJ8i$1X6ojLYD1oqR&ze;>GuG}n zA&nyC)(f1fo{+e51$wM1u3Wfs?XBve2QFM`-|VchV<{3sTo7+op7&flU`lv7m|w5CI}U z1c(3;AOb{y2oM1xKm>>Y5g-CYfCzkz1k8W?MRz-Dxq);M!85lN_>n4=-Y{!m@W?ku zbxEz;W3y5y#}_=T-Iv=nzrkH6T4)^7WvA-5~C zEgBI{JF&YvQz}j6FU?%po67HAzKr_C3p0CrsS{II=5O8I2+VC^N!|~J`fd|Gv4Ba# zqF>)iA{fYZBKXVBBr&9hj-`i3j%Vy_HanUd8#{4we0*Z^)QS^^j%f1A&bpm*o%%*I z)ccy1feb4_n`6{{y*EP6#kxJ(*L{mO4%k*VohH8)_)c`UYq_}7;;YTjZ!CCT#MN?- zz7p%TmQ(jdbJ?#;QS*Q1cLK-d!GfqrrR3(ior#cq6$fvId<(g*#cjnmtHP7Zia$`= z3wNgn7h1}fB3j~MgmO_x!3#gWHSiX)OlS>jOrxgfJdfAaZ0LB(jCbq5|9!Oo)4BK& zkjYFpl%n!IuWR+u+9^F>$NE1k03%5vx6=#hVs{;#NXEo&;+5^uP2PAC_kX5m`&WB> zuR?bov)|*GQ_g@34%A@-nh=77HV9}y5fu2~;gx|2NW)yLbF@=1i*^pS6^z1n(>)7J z_s^e$vFRllv^RM)-LokjrEL{D0T#+DMlF=@8D%I{D3^?C>pb{bxBykShkJVnkKrl& z4lm&qyn%n<9lU2bHo?BPezktHo>)(/dev/null || { echo "resvg not found (cargo install resvg --locked --version 0.48.1)" >&2; exit 1; } +mkdir -p "$STAGE/.background" +resvg --skip-system-fonts -w 660 "$HERE/dmg/background.svg" "$WORK/background.png" +resvg --skip-system-fonts -w 1320 "$HERE/dmg/background.svg" "$WORK/background@2x.png" +sips -s dpiWidth 144 -s dpiHeight 144 "$WORK/background@2x.png" >/dev/null +tiffutil -cathidpicheck "$WORK/background.png" "$WORK/background@2x.png" -out "$STAGE/.background/background.tiff" +cp "$HERE/dmg/dmg-layout.DS_Store" "$STAGE/.DS_Store" rm -f "$DMG" "$WORK/raw.dmg" # makehybrid + convert builds the image without attaching a device, unlike `create -srcfolder`, # which is flaky on CI runners ("Resource busy") and hangs in sandboxed sessions. -hdiutil makehybrid -hfs -hfs-volume-name "EffectCraft $VERSION" -hfs-openfolder "$STAGE" -o "$WORK/raw.dmg" "$STAGE" +# The volume name has no version: .DS_Store finds the background through an alias that includes it. +hdiutil makehybrid -hfs -hfs-volume-name "EffectCraft" -hfs-openfolder "$STAGE" -o "$WORK/raw.dmg" "$STAGE" hdiutil convert "$WORK/raw.dmg" -format UDZO -imagekey zlib-level=9 -o "$DMG" rm -f "$WORK/raw.dmg" sign "$DMG"