diff --git a/assets/branding/README.md b/assets/branding/README.md index b136f3a..52a20f1 100644 --- a/assets/branding/README.md +++ b/assets/branding/README.md @@ -14,31 +14,236 @@ Use the transparent original by default. If a derivative needs an opaque background, the background must be black. Do not use another background color. -## Generated derivatives +## Quick selection guide -`generated/` contains reproducible derivatives for common application and -distribution targets. The canonical source above remains the only master -artwork. +| Need | Recommended asset | +|---|---| +| General logo with transparency | `generated/png/transparent/` at the nearest suitable size | +| Icon that may be rounded or cropped | `generated/png/safe-zone/` | +| PWA/installable website | `generated/web/site.webmanifest` and `maskable-icon-*` | +| Windows application | `generated/windows/app.ico` | +| macOS application | `generated/macos/AppIcon.icns` | +| iPhone/iPad application | `generated/ios/AppIcon.appiconset/` | +| Android application | `generated/android/` | +| Linux desktop application | `generated/linux/hicolor/` | +| Tray, notification, stencil, or engraving | `generated/png/monochrome-white/` or `monochrome-black/` | +| Social profile or link preview | `generated/social/` | -- `png/transparent/`: full-bleed transparent PNGs from 16 to 1024 pixels -- `png/on-black/`: opaque black-background PNGs -- `png/safe-zone/`: transparent icons with padding for UI and app chrome -- `png/monochrome-{black,white}/`: single-color notification/tray variants -- `web/`: favicons, Apple touch icon, PWA icons, and maskable PWA icons -- `windows/`: multi-resolution ICO and Microsoft Store square assets -- `macos/`: ICNS and an Xcode-compatible `AppIcon.iconset` -- `ios/`: a ready-to-copy `AppIcon.appiconset` with `Contents.json` -- `android/`: legacy launcher and adaptive foreground assets by density -- `linux/`: freedesktop `hicolor` application icon hierarchy -- `social/`: square profile and 1200 x 630 Open Graph images +The catalog below lists all 128 generated image files individually. -Use the safe-zone or maskable versions anywhere the operating system may crop -an icon to a circle, squircle, or other shape. Android adaptive foreground -assets are transparent and are intended for a black (`#000000`) adaptive-icon -background. +## Canonical artwork +| Preview | File | Dimensions | Background / safe area | Recommended use | +|---|---|---:|---|---| +Original The Pirate Ray logo | [`the-pirate-ray-logo.png`](the-pirate-ray-logo.png) | 1254 x 1254 | Transparent, full-bleed | Canonical master. Use for new derivatives and full-resolution layouts; never overwrite or re-encode it. | + +## PNG — transparent, full-bleed + +| Preview | File | Dimensions | Background / safe area | Recommended use | +|---|---|---:|---|---| +Preview of logo-16.png | [`png/transparent/logo-16.png`](generated/png/transparent/logo-16.png) | 16 x 16 | Transparent | Small UI, browser chrome, or tray use where full artwork may reach the edge. | +Preview of logo-20.png | [`png/transparent/logo-20.png`](generated/png/transparent/logo-20.png) | 20 x 20 | Transparent | Small UI, browser chrome, or tray use where full artwork may reach the edge. | +Preview of logo-24.png | [`png/transparent/logo-24.png`](generated/png/transparent/logo-24.png) | 24 x 24 | Transparent | Small UI, browser chrome, or tray use where full artwork may reach the edge. | +Preview of logo-32.png | [`png/transparent/logo-32.png`](generated/png/transparent/logo-32.png) | 32 x 32 | Transparent | Small UI, browser chrome, or tray use where full artwork may reach the edge. | +Preview of logo-40.png | [`png/transparent/logo-40.png`](generated/png/transparent/logo-40.png) | 40 x 40 | Transparent | Small UI, browser chrome, or tray use where full artwork may reach the edge. | +Preview of logo-48.png | [`png/transparent/logo-48.png`](generated/png/transparent/logo-48.png) | 48 x 48 | Transparent | Small UI, browser chrome, or tray use where full artwork may reach the edge. | +Preview of logo-64.png | [`png/transparent/logo-64.png`](generated/png/transparent/logo-64.png) | 64 x 64 | Transparent | General UI, documentation, avatars, and compact placements on any background. | +Preview of logo-72.png | [`png/transparent/logo-72.png`](generated/png/transparent/logo-72.png) | 72 x 72 | Transparent | General UI, documentation, avatars, and compact placements on any background. | +Preview of logo-96.png | [`png/transparent/logo-96.png`](generated/png/transparent/logo-96.png) | 96 x 96 | Transparent | General UI, documentation, avatars, and compact placements on any background. | +Preview of logo-128.png | [`png/transparent/logo-128.png`](generated/png/transparent/logo-128.png) | 128 x 128 | Transparent | General UI, documentation, avatars, and compact placements on any background. | +Preview of logo-144.png | [`png/transparent/logo-144.png`](generated/png/transparent/logo-144.png) | 144 x 144 | Transparent | General UI, documentation, avatars, and compact placements on any background. | +Preview of logo-152.png | [`png/transparent/logo-152.png`](generated/png/transparent/logo-152.png) | 152 x 152 | Transparent | General UI, documentation, avatars, and compact placements on any background. | +Preview of logo-180.png | [`png/transparent/logo-180.png`](generated/png/transparent/logo-180.png) | 180 x 180 | Transparent | General UI, documentation, avatars, and compact placements on any background. | +Preview of logo-192.png | [`png/transparent/logo-192.png`](generated/png/transparent/logo-192.png) | 192 x 192 | Transparent | General UI, documentation, avatars, and compact placements on any background. | +Preview of logo-256.png | [`png/transparent/logo-256.png`](generated/png/transparent/logo-256.png) | 256 x 256 | Transparent | General high-resolution placement, print/layout source, and manual exports. | +Preview of logo-384.png | [`png/transparent/logo-384.png`](generated/png/transparent/logo-384.png) | 384 x 384 | Transparent | General high-resolution placement, print/layout source, and manual exports. | +Preview of logo-512.png | [`png/transparent/logo-512.png`](generated/png/transparent/logo-512.png) | 512 x 512 | Transparent | General high-resolution placement, print/layout source, and manual exports. | +Preview of logo-1024.png | [`png/transparent/logo-1024.png`](generated/png/transparent/logo-1024.png) | 1024 x 1024 | Transparent | General high-resolution placement, print/layout source, and manual exports. | + +## PNG — opaque on black + +| Preview | File | Dimensions | Background / safe area | Recommended use | +|---|---|---:|---|---| +Preview of logo-16.png | [`png/on-black/logo-16.png`](generated/png/on-black/logo-16.png) | 16 x 16 | Opaque black | Use where transparency is unsupported or a guaranteed black brand background is required. | +Preview of logo-20.png | [`png/on-black/logo-20.png`](generated/png/on-black/logo-20.png) | 20 x 20 | Opaque black | Use where transparency is unsupported or a guaranteed black brand background is required. | +Preview of logo-24.png | [`png/on-black/logo-24.png`](generated/png/on-black/logo-24.png) | 24 x 24 | Opaque black | Use where transparency is unsupported or a guaranteed black brand background is required. | +Preview of logo-32.png | [`png/on-black/logo-32.png`](generated/png/on-black/logo-32.png) | 32 x 32 | Opaque black | Use where transparency is unsupported or a guaranteed black brand background is required. | +Preview of logo-40.png | [`png/on-black/logo-40.png`](generated/png/on-black/logo-40.png) | 40 x 40 | Opaque black | Use where transparency is unsupported or a guaranteed black brand background is required. | +Preview of logo-48.png | [`png/on-black/logo-48.png`](generated/png/on-black/logo-48.png) | 48 x 48 | Opaque black | Use where transparency is unsupported or a guaranteed black brand background is required. | +Preview of logo-64.png | [`png/on-black/logo-64.png`](generated/png/on-black/logo-64.png) | 64 x 64 | Opaque black | Use where transparency is unsupported or a guaranteed black brand background is required. | +Preview of logo-72.png | [`png/on-black/logo-72.png`](generated/png/on-black/logo-72.png) | 72 x 72 | Opaque black | Use where transparency is unsupported or a guaranteed black brand background is required. | +Preview of logo-96.png | [`png/on-black/logo-96.png`](generated/png/on-black/logo-96.png) | 96 x 96 | Opaque black | Use where transparency is unsupported or a guaranteed black brand background is required. | +Preview of logo-128.png | [`png/on-black/logo-128.png`](generated/png/on-black/logo-128.png) | 128 x 128 | Opaque black | Use where transparency is unsupported or a guaranteed black brand background is required. | +Preview of logo-144.png | [`png/on-black/logo-144.png`](generated/png/on-black/logo-144.png) | 144 x 144 | Opaque black | Use where transparency is unsupported or a guaranteed black brand background is required. | +Preview of logo-152.png | [`png/on-black/logo-152.png`](generated/png/on-black/logo-152.png) | 152 x 152 | Opaque black | Use where transparency is unsupported or a guaranteed black brand background is required. | +Preview of logo-180.png | [`png/on-black/logo-180.png`](generated/png/on-black/logo-180.png) | 180 x 180 | Opaque black | Use where transparency is unsupported or a guaranteed black brand background is required. | +Preview of logo-192.png | [`png/on-black/logo-192.png`](generated/png/on-black/logo-192.png) | 192 x 192 | Opaque black | Use where transparency is unsupported or a guaranteed black brand background is required. | +Preview of logo-256.png | [`png/on-black/logo-256.png`](generated/png/on-black/logo-256.png) | 256 x 256 | Opaque black | Use where transparency is unsupported or a guaranteed black brand background is required. | +Preview of logo-384.png | [`png/on-black/logo-384.png`](generated/png/on-black/logo-384.png) | 384 x 384 | Opaque black | Use where transparency is unsupported or a guaranteed black brand background is required. | +Preview of logo-512.png | [`png/on-black/logo-512.png`](generated/png/on-black/logo-512.png) | 512 x 512 | Opaque black | Use where transparency is unsupported or a guaranteed black brand background is required. | +Preview of logo-1024.png | [`png/on-black/logo-1024.png`](generated/png/on-black/logo-1024.png) | 1024 x 1024 | Opaque black | Use where transparency is unsupported or a guaranteed black brand background is required. | + +## PNG — transparent safe-zone + +| Preview | File | Dimensions | Background / safe area | Recommended use | +|---|---|---:|---|---| +Preview of logo-16.png | [`png/safe-zone/logo-16.png`](generated/png/safe-zone/logo-16.png) | 16 x 16 | Transparent, 11% margin | App chrome, launchers, or UI containers that may crop or round the image. | +Preview of logo-32.png | [`png/safe-zone/logo-32.png`](generated/png/safe-zone/logo-32.png) | 32 x 32 | Transparent, 11% margin | App chrome, launchers, or UI containers that may crop or round the image. | +Preview of logo-48.png | [`png/safe-zone/logo-48.png`](generated/png/safe-zone/logo-48.png) | 48 x 48 | Transparent, 11% margin | App chrome, launchers, or UI containers that may crop or round the image. | +Preview of logo-64.png | [`png/safe-zone/logo-64.png`](generated/png/safe-zone/logo-64.png) | 64 x 64 | Transparent, 11% margin | App chrome, launchers, or UI containers that may crop or round the image. | +Preview of logo-128.png | [`png/safe-zone/logo-128.png`](generated/png/safe-zone/logo-128.png) | 128 x 128 | Transparent, 11% margin | App chrome, launchers, or UI containers that may crop or round the image. | +Preview of logo-256.png | [`png/safe-zone/logo-256.png`](generated/png/safe-zone/logo-256.png) | 256 x 256 | Transparent, 11% margin | App chrome, launchers, or UI containers that may crop or round the image. | +Preview of logo-512.png | [`png/safe-zone/logo-512.png`](generated/png/safe-zone/logo-512.png) | 512 x 512 | Transparent, 11% margin | App chrome, launchers, or UI containers that may crop or round the image. | +Preview of logo-1024.png | [`png/safe-zone/logo-1024.png`](generated/png/safe-zone/logo-1024.png) | 1024 x 1024 | Transparent, 11% margin | App chrome, launchers, or UI containers that may crop or round the image. | + +## PNG — monochrome white + +| Preview | File | Dimensions | Background / safe area | Recommended use | +|---|---|---:|---|---| +Preview of logo-16.png | [`png/monochrome-white/logo-16.png`](generated/png/monochrome-white/logo-16.png) | 16 x 16 | Transparent; white silhouette | Dark system bars, notification glyphs, vinyl/stencil work, or one-color output. | +Preview of logo-32.png | [`png/monochrome-white/logo-32.png`](generated/png/monochrome-white/logo-32.png) | 32 x 32 | Transparent; white silhouette | Dark system bars, notification glyphs, vinyl/stencil work, or one-color output. | +Preview of logo-48.png | [`png/monochrome-white/logo-48.png`](generated/png/monochrome-white/logo-48.png) | 48 x 48 | Transparent; white silhouette | Dark system bars, notification glyphs, vinyl/stencil work, or one-color output. | +Preview of logo-64.png | [`png/monochrome-white/logo-64.png`](generated/png/monochrome-white/logo-64.png) | 64 x 64 | Transparent; white silhouette | Dark system bars, notification glyphs, vinyl/stencil work, or one-color output. | +Preview of logo-128.png | [`png/monochrome-white/logo-128.png`](generated/png/monochrome-white/logo-128.png) | 128 x 128 | Transparent; white silhouette | Dark system bars, notification glyphs, vinyl/stencil work, or one-color output. | +Preview of logo-256.png | [`png/monochrome-white/logo-256.png`](generated/png/monochrome-white/logo-256.png) | 256 x 256 | Transparent; white silhouette | Dark system bars, notification glyphs, vinyl/stencil work, or one-color output. | +Preview of logo-512.png | [`png/monochrome-white/logo-512.png`](generated/png/monochrome-white/logo-512.png) | 512 x 512 | Transparent; white silhouette | Dark system bars, notification glyphs, vinyl/stencil work, or one-color output. | +Preview of logo-1024.png | [`png/monochrome-white/logo-1024.png`](generated/png/monochrome-white/logo-1024.png) | 1024 x 1024 | Transparent; white silhouette | Dark system bars, notification glyphs, vinyl/stencil work, or one-color output. | + +## PNG — monochrome black + +| Preview | File | Dimensions | Background / safe area | Recommended use | +|---|---|---:|---|---| +Preview of logo-16.png | [`png/monochrome-black/logo-16.png`](generated/png/monochrome-black/logo-16.png) | 16 x 16 | Transparent; black silhouette | Light system bars, print, engraving masks, or one-color output. | +Preview of logo-32.png | [`png/monochrome-black/logo-32.png`](generated/png/monochrome-black/logo-32.png) | 32 x 32 | Transparent; black silhouette | Light system bars, print, engraving masks, or one-color output. | +Preview of logo-48.png | [`png/monochrome-black/logo-48.png`](generated/png/monochrome-black/logo-48.png) | 48 x 48 | Transparent; black silhouette | Light system bars, print, engraving masks, or one-color output. | +Preview of logo-64.png | [`png/monochrome-black/logo-64.png`](generated/png/monochrome-black/logo-64.png) | 64 x 64 | Transparent; black silhouette | Light system bars, print, engraving masks, or one-color output. | +Preview of logo-128.png | [`png/monochrome-black/logo-128.png`](generated/png/monochrome-black/logo-128.png) | 128 x 128 | Transparent; black silhouette | Light system bars, print, engraving masks, or one-color output. | +Preview of logo-256.png | [`png/monochrome-black/logo-256.png`](generated/png/monochrome-black/logo-256.png) | 256 x 256 | Transparent; black silhouette | Light system bars, print, engraving masks, or one-color output. | +Preview of logo-512.png | [`png/monochrome-black/logo-512.png`](generated/png/monochrome-black/logo-512.png) | 512 x 512 | Transparent; black silhouette | Light system bars, print, engraving masks, or one-color output. | +Preview of logo-1024.png | [`png/monochrome-black/logo-1024.png`](generated/png/monochrome-black/logo-1024.png) | 1024 x 1024 | Transparent; black silhouette | Light system bars, print, engraving masks, or one-color output. | + +## Web and PWA + +| Preview | File | Dimensions | Background / safe area | Recommended use | +|---|---|---:|---|---| +Preview of favicon.ico | [`web/favicon.ico`](generated/web/favicon.ico) | 16–48 px | Transparent | Multi-resolution legacy browser favicon (16, 32, and 48 px). | +Preview of favicon-16x16.png | [`web/favicon-16x16.png`](generated/web/favicon-16x16.png) | 16 x 16 | Transparent | Browser tab/favicon at 16 px; reference from HTML with rel=icon. | +Preview of favicon-32x32.png | [`web/favicon-32x32.png`](generated/web/favicon-32x32.png) | 32 x 32 | Transparent | Browser tab/favicon at 32 px; reference from HTML with rel=icon. | +Preview of apple-touch-icon.png | [`web/apple-touch-icon.png`](generated/web/apple-touch-icon.png) | 180 x 180 | Transparent | iOS/iPadOS home-screen bookmark; reference with rel=apple-touch-icon. | +Preview of icon-192.png | [`web/icon-192.png`](generated/web/icon-192.png) | 192 x 192 | Transparent | Standard PWA/web-app manifest icon; set purpose to any. | +Preview of maskable-icon-192.png | [`web/maskable-icon-192.png`](generated/web/maskable-icon-192.png) | 192 x 192 | Opaque black | PWA manifest icon with extra safe area; set purpose to maskable. | +Preview of icon-512.png | [`web/icon-512.png`](generated/web/icon-512.png) | 512 x 512 | Transparent | Standard PWA/web-app manifest icon; set purpose to any. | +Preview of maskable-icon-512.png | [`web/maskable-icon-512.png`](generated/web/maskable-icon-512.png) | 512 x 512 | Opaque black | PWA manifest icon with extra safe area; set purpose to maskable. | + +## Windows + +| Preview | File | Dimensions | Background / safe area | Recommended use | +|---|---|---:|---|---| +Preview of app.ico | [`windows/app.ico`](generated/windows/app.ico) | 16–256 px | Opaque black, padded | Windows executable, installer, shortcut, and window icon (16–256 px). | +Preview of BadgeLogo.png | [`windows/store/BadgeLogo.png`](generated/windows/store/BadgeLogo.png) | 24 x 24 | Opaque black | Windows package badge asset. | +Preview of Square44x44Logo.png | [`windows/store/Square44x44Logo.png`](generated/windows/store/Square44x44Logo.png) | 44 x 44 | Opaque black | Windows package/Start tile asset matching the size encoded in its filename. | +Preview of StoreLogo.png | [`windows/store/StoreLogo.png`](generated/windows/store/StoreLogo.png) | 50 x 50 | Opaque black | Microsoft Store package logo. | +Preview of Square71x71Logo.png | [`windows/store/Square71x71Logo.png`](generated/windows/store/Square71x71Logo.png) | 71 x 71 | Opaque black | Windows package/Start tile asset matching the size encoded in its filename. | +Preview of Square150x150Logo.png | [`windows/store/Square150x150Logo.png`](generated/windows/store/Square150x150Logo.png) | 150 x 150 | Opaque black | Windows package/Start tile asset matching the size encoded in its filename. | +Preview of Square310x310Logo.png | [`windows/store/Square310x310Logo.png`](generated/windows/store/Square310x310Logo.png) | 310 x 310 | Opaque black | Windows package/Start tile asset matching the size encoded in its filename. | +Preview of Wide310x150Logo.png | [`windows/store/Wide310x150Logo.png`](generated/windows/store/Wide310x150Logo.png) | 310 x 150 | Opaque black | Wide Windows Start tile/package visual. | + +## macOS + +| Preview | File | Dimensions | Background / safe area | Recommended use | +|---|---|---:|---|---| +Preview of AppIcon.icns | [`macos/AppIcon.icns`](generated/macos/AppIcon.icns) | 16–1024 px | Opaque black, padded | Ready-to-use macOS app-bundle icon containing platform resolutions. | +Preview of icon_16x16.png | [`macos/AppIcon.iconset/icon_16x16.png`](generated/macos/AppIcon.iconset/icon_16x16.png) | 16 x 16 | Opaque black, padded | macOS iconset source; keep the filename unchanged for Xcode or iconutil. | +Preview of icon_16x16@2x.png | [`macos/AppIcon.iconset/icon_16x16@2x.png`](generated/macos/AppIcon.iconset/icon_16x16@2x.png) | 32 x 32 | Opaque black, padded | macOS iconset source; keep the filename unchanged for Xcode or iconutil. | +Preview of icon_32x32.png | [`macos/AppIcon.iconset/icon_32x32.png`](generated/macos/AppIcon.iconset/icon_32x32.png) | 32 x 32 | Opaque black, padded | macOS iconset source; keep the filename unchanged for Xcode or iconutil. | +Preview of icon_32x32@2x.png | [`macos/AppIcon.iconset/icon_32x32@2x.png`](generated/macos/AppIcon.iconset/icon_32x32@2x.png) | 64 x 64 | Opaque black, padded | macOS iconset source; keep the filename unchanged for Xcode or iconutil. | +Preview of icon_128x128.png | [`macos/AppIcon.iconset/icon_128x128.png`](generated/macos/AppIcon.iconset/icon_128x128.png) | 128 x 128 | Opaque black, padded | macOS iconset source; keep the filename unchanged for Xcode or iconutil. | +Preview of icon_128x128@2x.png | [`macos/AppIcon.iconset/icon_128x128@2x.png`](generated/macos/AppIcon.iconset/icon_128x128@2x.png) | 256 x 256 | Opaque black, padded | macOS iconset source; keep the filename unchanged for Xcode or iconutil. | +Preview of icon_256x256.png | [`macos/AppIcon.iconset/icon_256x256.png`](generated/macos/AppIcon.iconset/icon_256x256.png) | 256 x 256 | Opaque black, padded | macOS iconset source; keep the filename unchanged for Xcode or iconutil. | +Preview of icon_256x256@2x.png | [`macos/AppIcon.iconset/icon_256x256@2x.png`](generated/macos/AppIcon.iconset/icon_256x256@2x.png) | 512 x 512 | Opaque black, padded | macOS iconset source; keep the filename unchanged for Xcode or iconutil. | +Preview of icon_512x512.png | [`macos/AppIcon.iconset/icon_512x512.png`](generated/macos/AppIcon.iconset/icon_512x512.png) | 512 x 512 | Opaque black, padded | macOS iconset source; keep the filename unchanged for Xcode or iconutil. | +Preview of icon_512x512@2x.png | [`macos/AppIcon.iconset/icon_512x512@2x.png`](generated/macos/AppIcon.iconset/icon_512x512@2x.png) | 1024 x 1024 | Opaque black, padded | macOS iconset source; keep the filename unchanged for Xcode or iconutil. | + +## iOS and iPadOS + +| Preview | File | Dimensions | Background / safe area | Recommended use | +|---|---|---:|---|---| +Preview of icon-20@1x.png | [`ios/AppIcon.appiconset/icon-20@1x.png`](generated/ios/AppIcon.appiconset/icon-20@1x.png) | 20 x 20 | Opaque black, padded | iOS/iPadOS notifications icon; use through the included AppIcon asset catalog. | +Preview of icon-29@1x.png | [`ios/AppIcon.appiconset/icon-29@1x.png`](generated/ios/AppIcon.appiconset/icon-29@1x.png) | 29 x 29 | Opaque black, padded | iOS/iPadOS Settings icon; use through the included AppIcon asset catalog. | +Preview of icon-20@2x.png | [`ios/AppIcon.appiconset/icon-20@2x.png`](generated/ios/AppIcon.appiconset/icon-20@2x.png) | 40 x 40 | Opaque black, padded | iOS/iPadOS notifications icon; use through the included AppIcon asset catalog. | +Preview of icon-40@1x.png | [`ios/AppIcon.appiconset/icon-40@1x.png`](generated/ios/AppIcon.appiconset/icon-40@1x.png) | 40 x 40 | Opaque black, padded | iOS/iPadOS Spotlight icon; use through the included AppIcon asset catalog. | +Preview of icon-29@2x.png | [`ios/AppIcon.appiconset/icon-29@2x.png`](generated/ios/AppIcon.appiconset/icon-29@2x.png) | 58 x 58 | Opaque black, padded | iOS/iPadOS Settings icon; use through the included AppIcon asset catalog. | +Preview of icon-20@3x.png | [`ios/AppIcon.appiconset/icon-20@3x.png`](generated/ios/AppIcon.appiconset/icon-20@3x.png) | 60 x 60 | Opaque black, padded | iOS/iPadOS notifications icon; use through the included AppIcon asset catalog. | +Preview of icon-76@1x.png | [`ios/AppIcon.appiconset/icon-76@1x.png`](generated/ios/AppIcon.appiconset/icon-76@1x.png) | 76 x 76 | Opaque black, padded | iOS/iPadOS iPad app icon; use through the included AppIcon asset catalog. | +Preview of icon-40@2x.png | [`ios/AppIcon.appiconset/icon-40@2x.png`](generated/ios/AppIcon.appiconset/icon-40@2x.png) | 80 x 80 | Opaque black, padded | iOS/iPadOS Spotlight icon; use through the included AppIcon asset catalog. | +Preview of icon-29@3x.png | [`ios/AppIcon.appiconset/icon-29@3x.png`](generated/ios/AppIcon.appiconset/icon-29@3x.png) | 87 x 87 | Opaque black, padded | iOS/iPadOS Settings icon; use through the included AppIcon asset catalog. | +Preview of icon-40@3x.png | [`ios/AppIcon.appiconset/icon-40@3x.png`](generated/ios/AppIcon.appiconset/icon-40@3x.png) | 120 x 120 | Opaque black, padded | iOS/iPadOS Spotlight icon; use through the included AppIcon asset catalog. | +Preview of icon-60@2x.png | [`ios/AppIcon.appiconset/icon-60@2x.png`](generated/ios/AppIcon.appiconset/icon-60@2x.png) | 120 x 120 | Opaque black, padded | iOS/iPadOS iPhone app icon; use through the included AppIcon asset catalog. | +Preview of icon-76@2x.png | [`ios/AppIcon.appiconset/icon-76@2x.png`](generated/ios/AppIcon.appiconset/icon-76@2x.png) | 152 x 152 | Opaque black, padded | iOS/iPadOS iPad app icon; use through the included AppIcon asset catalog. | +Preview of icon-83.5@2x.png | [`ios/AppIcon.appiconset/icon-83.5@2x.png`](generated/ios/AppIcon.appiconset/icon-83.5@2x.png) | 167 x 167 | Opaque black, padded | iOS/iPadOS iPad Pro app icon; use through the included AppIcon asset catalog. | +Preview of icon-60@3x.png | [`ios/AppIcon.appiconset/icon-60@3x.png`](generated/ios/AppIcon.appiconset/icon-60@3x.png) | 180 x 180 | Opaque black, padded | iOS/iPadOS iPhone app icon; use through the included AppIcon asset catalog. | +Preview of icon-1024.png | [`ios/AppIcon.appiconset/icon-1024.png`](generated/ios/AppIcon.appiconset/icon-1024.png) | 1024 x 1024 | Opaque black, padded | App Store marketing icon. | + +## Android + +| Preview | File | Dimensions | Background / safe area | Recommended use | +|---|---|---:|---|---| +Preview of ic_launcher.png | [`android/mipmap-mdpi/ic_launcher.png`](generated/android/mipmap-mdpi/ic_launcher.png) | 48 x 48 | Opaque black, padded | Legacy Android launcher icon for the named display density. | +Preview of ic_launcher_round.png | [`android/mipmap-mdpi/ic_launcher_round.png`](generated/android/mipmap-mdpi/ic_launcher_round.png) | 48 x 48 | Opaque black, padded | Legacy round Android launcher icon for the named display density. | +Preview of ic_launcher.png | [`android/mipmap-hdpi/ic_launcher.png`](generated/android/mipmap-hdpi/ic_launcher.png) | 72 x 72 | Opaque black, padded | Legacy Android launcher icon for the named display density. | +Preview of ic_launcher_round.png | [`android/mipmap-hdpi/ic_launcher_round.png`](generated/android/mipmap-hdpi/ic_launcher_round.png) | 72 x 72 | Opaque black, padded | Legacy round Android launcher icon for the named display density. | +Preview of ic_launcher.png | [`android/mipmap-xhdpi/ic_launcher.png`](generated/android/mipmap-xhdpi/ic_launcher.png) | 96 x 96 | Opaque black, padded | Legacy Android launcher icon for the named display density. | +Preview of ic_launcher_round.png | [`android/mipmap-xhdpi/ic_launcher_round.png`](generated/android/mipmap-xhdpi/ic_launcher_round.png) | 96 x 96 | Opaque black, padded | Legacy round Android launcher icon for the named display density. | +Preview of ic_launcher_foreground.png | [`android/drawable-mdpi/ic_launcher_foreground.png`](generated/android/drawable-mdpi/ic_launcher_foreground.png) | 108 x 108 | Transparent adaptive foreground | Android adaptive-icon foreground for the density named in the parent folder. | +Preview of ic_launcher.png | [`android/mipmap-xxhdpi/ic_launcher.png`](generated/android/mipmap-xxhdpi/ic_launcher.png) | 144 x 144 | Opaque black, padded | Legacy Android launcher icon for the named display density. | +Preview of ic_launcher_round.png | [`android/mipmap-xxhdpi/ic_launcher_round.png`](generated/android/mipmap-xxhdpi/ic_launcher_round.png) | 144 x 144 | Opaque black, padded | Legacy round Android launcher icon for the named display density. | +Preview of ic_launcher_foreground.png | [`android/drawable-hdpi/ic_launcher_foreground.png`](generated/android/drawable-hdpi/ic_launcher_foreground.png) | 162 x 162 | Transparent adaptive foreground | Android adaptive-icon foreground for the density named in the parent folder. | +Preview of ic_launcher.png | [`android/mipmap-xxxhdpi/ic_launcher.png`](generated/android/mipmap-xxxhdpi/ic_launcher.png) | 192 x 192 | Opaque black, padded | Legacy Android launcher icon for the named display density. | +Preview of ic_launcher_round.png | [`android/mipmap-xxxhdpi/ic_launcher_round.png`](generated/android/mipmap-xxxhdpi/ic_launcher_round.png) | 192 x 192 | Opaque black, padded | Legacy round Android launcher icon for the named display density. | +Preview of ic_launcher_foreground.png | [`android/drawable-xhdpi/ic_launcher_foreground.png`](generated/android/drawable-xhdpi/ic_launcher_foreground.png) | 216 x 216 | Transparent adaptive foreground | Android adaptive-icon foreground for the density named in the parent folder. | +Preview of ic_launcher_foreground.png | [`android/drawable-xxhdpi/ic_launcher_foreground.png`](generated/android/drawable-xxhdpi/ic_launcher_foreground.png) | 324 x 324 | Transparent adaptive foreground | Android adaptive-icon foreground for the density named in the parent folder. | +Preview of ic_launcher_foreground.png | [`android/drawable-xxxhdpi/ic_launcher_foreground.png`](generated/android/drawable-xxxhdpi/ic_launcher_foreground.png) | 432 x 432 | Transparent adaptive foreground | Android adaptive-icon foreground for the density named in the parent folder. | + +## Linux / freedesktop + +| Preview | File | Dimensions | Background / safe area | Recommended use | +|---|---|---:|---|---| +Preview of the-pirate-ray.png | [`linux/hicolor/16x16/apps/the-pirate-ray.png`](generated/linux/hicolor/16x16/apps/the-pirate-ray.png) | 16 x 16 | Transparent | Linux desktop/app-menu icon; install in the matching hicolor size directory. | +Preview of the-pirate-ray.png | [`linux/hicolor/22x22/apps/the-pirate-ray.png`](generated/linux/hicolor/22x22/apps/the-pirate-ray.png) | 22 x 22 | Transparent | Linux desktop/app-menu icon; install in the matching hicolor size directory. | +Preview of the-pirate-ray.png | [`linux/hicolor/24x24/apps/the-pirate-ray.png`](generated/linux/hicolor/24x24/apps/the-pirate-ray.png) | 24 x 24 | Transparent | Linux desktop/app-menu icon; install in the matching hicolor size directory. | +Preview of the-pirate-ray.png | [`linux/hicolor/32x32/apps/the-pirate-ray.png`](generated/linux/hicolor/32x32/apps/the-pirate-ray.png) | 32 x 32 | Transparent | Linux desktop/app-menu icon; install in the matching hicolor size directory. | +Preview of the-pirate-ray.png | [`linux/hicolor/48x48/apps/the-pirate-ray.png`](generated/linux/hicolor/48x48/apps/the-pirate-ray.png) | 48 x 48 | Transparent | Linux desktop/app-menu icon; install in the matching hicolor size directory. | +Preview of the-pirate-ray.png | [`linux/hicolor/64x64/apps/the-pirate-ray.png`](generated/linux/hicolor/64x64/apps/the-pirate-ray.png) | 64 x 64 | Transparent | Linux desktop/app-menu icon; install in the matching hicolor size directory. | +Preview of the-pirate-ray.png | [`linux/hicolor/128x128/apps/the-pirate-ray.png`](generated/linux/hicolor/128x128/apps/the-pirate-ray.png) | 128 x 128 | Transparent | Linux desktop/app-menu icon; install in the matching hicolor size directory. | +Preview of the-pirate-ray.png | [`linux/hicolor/256x256/apps/the-pirate-ray.png`](generated/linux/hicolor/256x256/apps/the-pirate-ray.png) | 256 x 256 | Transparent | Linux desktop/app-menu icon; install in the matching hicolor size directory. | +Preview of the-pirate-ray.png | [`linux/hicolor/512x512/apps/the-pirate-ray.png`](generated/linux/hicolor/512x512/apps/the-pirate-ray.png) | 512 x 512 | Transparent | Linux desktop/app-menu icon; install in the matching hicolor size directory. | + +## Social media + +| Preview | File | Dimensions | Background / safe area | Recommended use | +|---|---|---:|---|---| +Preview of profile-400.png | [`social/profile-400.png`](generated/social/profile-400.png) | 400 x 400 | Opaque black | Square account, organization, repository, or social profile image. | +Preview of open-graph-1200x630.png | [`social/open-graph-1200x630.png`](generated/social/open-graph-1200x630.png) | 1200 x 630 | Opaque black | Open Graph/link-preview image for websites, repositories, and social sharing. | + +## Supporting manifests and configuration + +These files are not logos themselves, but make the image sets copy-ready for +their target platforms. + +| File | Purpose | +|---|---| +[`manifest.json`](generated/manifest.json) | Inventory with byte sizes, dimensions, and SHA-256 for every generated file. | +[`android/mipmap-anydpi-v26/ic_launcher.xml`](generated/android/mipmap-anydpi-v26/ic_launcher.xml) | Android adaptive launcher icon declaration. | +[`android/mipmap-anydpi-v26/ic_launcher_round.xml`](generated/android/mipmap-anydpi-v26/ic_launcher_round.xml) | Android adaptive round launcher icon declaration. | +[`android/values/ic_launcher_background.xml`](generated/android/values/ic_launcher_background.xml) | Required black Android adaptive-icon background color. | +[`ios/AppIcon.appiconset/Contents.json`](generated/ios/AppIcon.appiconset/Contents.json) | Xcode asset-catalog mapping for every iOS and iPadOS icon. | +[`web/site.webmanifest`](generated/web/site.webmanifest) | Ready-to-adapt PWA manifest with regular and maskable icon declarations. | + +## Regeneration and integrity + +The complete catalog is generated deterministically from the canonical logo. `generated/manifest.json` records every derivative's dimensions and SHA-256. -Regenerate the complete set from the repository root with: +Regenerate the assets and this README from the repository root with: ```powershell uv run --with pillow python scripts/generate_brand_assets.py diff --git a/scripts/generate_brand_assets.py b/scripts/generate_brand_assets.py index d1fa83e..7419122 100644 --- a/scripts/generate_brand_assets.py +++ b/scripts/generate_brand_assets.py @@ -18,11 +18,28 @@ from PIL import Image ROOT = Path(__file__).resolve().parents[1] SOURCE = ROOT / "assets" / "branding" / "the-pirate-ray-logo.png" OUTPUT = ROOT / "assets" / "branding" / "generated" +BRANDING_README = ROOT / "assets" / "branding" / "README.md" SOURCE_SHA256 = "afcd7e457b5bf9cf92a7222b3ab8a2850d75c05bc2c37d242c959cd7569e6fa4" PNG_SIZES = (16, 20, 24, 32, 40, 48, 64, 72, 96, 128, 144, 152, 180, 192, 256, 384, 512, 1024) APP_SIZES = (16, 32, 48, 64, 128, 256, 512, 1024) +CATALOG_GROUPS = ( + ("png/transparent/", "PNG — transparent, full-bleed"), + ("png/on-black/", "PNG — opaque on black"), + ("png/safe-zone/", "PNG — transparent safe-zone"), + ("png/monochrome-white/", "PNG — monochrome white"), + ("png/monochrome-black/", "PNG — monochrome black"), + ("web/", "Web and PWA"), + ("windows/", "Windows"), + ("macos/", "macOS"), + ("ios/", "iOS and iPadOS"), + ("android/", "Android"), + ("linux/", "Linux / freedesktop"), + ("social/", "Social media"), +) + + def sha256(path: Path) -> str: return hashlib.sha256(path.read_bytes()).hexdigest() @@ -55,6 +72,215 @@ def monochrome(source: Image.Image, size: int, color: tuple[int, int, int]) -> I return image +def catalog_background(relative: str) -> str: + if any(part in relative for part in ("on-black/", "maskable-", "social/", "store/")): + return "Opaque black" + if relative.startswith(("ios/", "macos/")) or relative == "windows/app.ico": + return "Opaque black, padded" + if "/ic_launcher.png" in relative or "/ic_launcher_round.png" in relative: + return "Opaque black, padded" + if "monochrome-white/" in relative: + return "Transparent; white silhouette" + if "monochrome-black/" in relative: + return "Transparent; black silhouette" + if "safe-zone/" in relative: + return "Transparent, 11% margin" + if "foreground" in relative: + return "Transparent adaptive foreground" + return "Transparent" + + +def catalog_usage(relative: str, width: int | None = None) -> str: + name = Path(relative).name + if relative.startswith("png/transparent/"): + if width and width <= 48: + return "Small UI, browser chrome, or tray use where full artwork may reach the edge." + if width and width <= 192: + return "General UI, documentation, avatars, and compact placements on any background." + return "General high-resolution placement, print/layout source, and manual exports." + if relative.startswith("png/on-black/"): + return "Use where transparency is unsupported or a guaranteed black brand background is required." + if relative.startswith("png/safe-zone/"): + return "App chrome, launchers, or UI containers that may crop or round the image." + if "monochrome-white/" in relative: + return "Dark system bars, notification glyphs, vinyl/stencil work, or one-color output." + if "monochrome-black/" in relative: + return "Light system bars, print, engraving masks, or one-color output." + if relative == "web/favicon.ico": + return "Multi-resolution legacy browser favicon (16, 32, and 48 px)." + if name.startswith("favicon-"): + return f"Browser tab/favicon at {width} px; reference from HTML with rel=icon." + if name == "apple-touch-icon.png": + return "iOS/iPadOS home-screen bookmark; reference with rel=apple-touch-icon." + if name.startswith("maskable-icon-"): + return "PWA manifest icon with extra safe area; set purpose to maskable." + if relative.startswith("web/icon-"): + return "Standard PWA/web-app manifest icon; set purpose to any." + if relative == "windows/app.ico": + return "Windows executable, installer, shortcut, and window icon (16–256 px)." + if name == "BadgeLogo.png": + return "Windows package badge asset." + if name == "StoreLogo.png": + return "Microsoft Store package logo." + if name == "Wide310x150Logo.png": + return "Wide Windows Start tile/package visual." + if relative.startswith("windows/store/"): + return "Windows package/Start tile asset matching the size encoded in its filename." + if relative == "macos/AppIcon.icns": + return "Ready-to-use macOS app-bundle icon containing platform resolutions." + if relative.startswith("macos/AppIcon.iconset/"): + return "macOS iconset source; keep the filename unchanged for Xcode or iconutil." + if relative.startswith("ios/"): + if name == "icon-1024.png": + return "App Store marketing icon." + point_size = name.removeprefix("icon-").split("@")[0] + role = {"20": "notifications", "29": "Settings", "40": "Spotlight", "60": "iPhone app", "76": "iPad app", "83.5": "iPad Pro app"}.get(point_size, "app") + return f"iOS/iPadOS {role} icon; use through the included AppIcon asset catalog." + if "ic_launcher_foreground" in relative: + return "Android adaptive-icon foreground for the density named in the parent folder." + if "ic_launcher_round" in relative: + return "Legacy round Android launcher icon for the named display density." + if relative.startswith("android/"): + return "Legacy Android launcher icon for the named display density." + if relative.startswith("linux/"): + return "Linux desktop/app-menu icon; install in the matching hicolor size directory." + if name == "profile-400.png": + return "Square account, organization, repository, or social profile image." + if name == "open-graph-1200x630.png": + return "Open Graph/link-preview image for websites, repositories, and social sharing." + return "Platform-specific project logo asset." + + +def write_branding_readme(files: list[dict[str, object]]) -> None: + image_files = [ + record for record in files + if Path(str(record["path"])).suffix.lower() in {".png", ".ico", ".icns"} + ] + support_files = [record for record in files if record not in image_files] + lines = [ + "# The Pirate Ray branding", + "", + "The official project name is **The Pirate Ray**.", + "", + "`the-pirate-ray-logo.png` is the original transparent project logo supplied by", + "the project owner for use by this project. It is stored without resizing,", + "re-encoding, or other modification.", + "", + "- Dimensions: 1254 x 1254 pixels", + "- Format: 32-bit ARGB PNG", + f"- SHA-256: `{SOURCE_SHA256}`", + "", + "Use the transparent original by default. If a derivative needs an opaque", + "background, the background must be black. Do not use another background", + "color.", + "", + "## Quick selection guide", + "", + "| Need | Recommended asset |", + "|---|---|", + "| General logo with transparency | `generated/png/transparent/` at the nearest suitable size |", + "| Icon that may be rounded or cropped | `generated/png/safe-zone/` |", + "| PWA/installable website | `generated/web/site.webmanifest` and `maskable-icon-*` |", + "| Windows application | `generated/windows/app.ico` |", + "| macOS application | `generated/macos/AppIcon.icns` |", + "| iPhone/iPad application | `generated/ios/AppIcon.appiconset/` |", + "| Android application | `generated/android/` |", + "| Linux desktop application | `generated/linux/hicolor/` |", + "| Tray, notification, stencil, or engraving | `generated/png/monochrome-white/` or `monochrome-black/` |", + "| Social profile or link preview | `generated/social/` |", + "", + f"The catalog below lists all {len(image_files)} generated image files individually.", + "", + "## Canonical artwork", + "", + "| Preview | File | Dimensions | Background / safe area | Recommended use |", + "|---|---|---:|---|---|", + 'Original The Pirate Ray logo | [`the-pirate-ray-logo.png`](the-pirate-ray-logo.png) | 1254 x 1254 | Transparent, full-bleed | Canonical master. Use for new derivatives and full-resolution layouts; never overwrite or re-encode it. |', + ] + + for prefix, title in CATALOG_GROUPS: + records = [record for record in image_files if str(record["path"]).startswith(prefix)] + records.sort(key=lambda record: (record.get("width", 0), str(record["path"]))) + if not records: + continue + lines.extend([ + "", + f"## {title}", + "", + "| Preview | File | Dimensions | Background / safe area | Recommended use |", + "|---|---|---:|---|---|", + ]) + for record in records: + relative = str(record["path"]) + width = record.get("width") + height = record.get("height") + if width and height: + dimensions = f"{width} x {height}" + elif relative == "windows/app.ico": + dimensions = "16–256 px" + elif relative == "web/favicon.ico": + dimensions = "16–48 px" + else: + dimensions = "16–1024 px" + preview_relative = { + "web/favicon.ico": "web/favicon-32x32.png", + "windows/app.ico": "windows/store/Square150x150Logo.png", + "macos/AppIcon.icns": "macos/AppIcon.iconset/icon_128x128.png", + }.get(relative, relative) + preview_style = "" + if "monochrome-white/" in relative: + preview_style = ' style="background:#222;padding:4px"' + elif "monochrome-black/" in relative: + preview_style = ' style="background:#eee;padding:4px"' + preview = f'Preview of {Path(relative).name}' + link = f"[`{relative}`](generated/{relative})" + lines.append( + f"{preview} | {link} | {dimensions} | {catalog_background(relative)} | {catalog_usage(relative, width if isinstance(width, int) else None)} |" + ) + + lines.extend([ + "", + "## Supporting manifests and configuration", + "", + "These files are not logos themselves, but make the image sets copy-ready for", + "their target platforms.", + "", + "| File | Purpose |", + "|---|---|", + "[`manifest.json`](generated/manifest.json) | Inventory with byte sizes, dimensions, and SHA-256 for every generated file. |", + ]) + support_usage = { + "web/site.webmanifest": "Ready-to-adapt PWA manifest with regular and maskable icon declarations.", + "ios/AppIcon.appiconset/Contents.json": "Xcode asset-catalog mapping for every iOS and iPadOS icon.", + "android/mipmap-anydpi-v26/ic_launcher.xml": "Android adaptive launcher icon declaration.", + "android/mipmap-anydpi-v26/ic_launcher_round.xml": "Android adaptive round launcher icon declaration.", + "android/values/ic_launcher_background.xml": "Required black Android adaptive-icon background color.", + } + for record in support_files: + relative = str(record["path"]) + purpose = support_usage.get(relative, "Platform support/configuration file.") + lines.append(f"[`{relative}`](generated/{relative}) | {purpose} |") + + lines.extend([ + "", + "## Regeneration and integrity", + "", + "The complete catalog is generated deterministically from the canonical logo.", + "`generated/manifest.json` records every derivative's dimensions and SHA-256.", + "Regenerate the assets and this README from the repository root with:", + "", + "```powershell", + "uv run --with pillow python scripts/generate_brand_assets.py", + "```", + "", + "The repository does not yet have a project license. This directory records", + "the asset's provenance and approved presentation; it does not independently", + "grant broader rights or select a license.", + "", + ]) + BRANDING_README.write_text("\n".join(lines), encoding="utf-8", newline="\n") + + def generate_ios(source: Image.Image) -> None: directory = OUTPUT / "ios" / "AppIcon.appiconset" specs = ( @@ -242,6 +468,7 @@ def generate() -> None: (OUTPUT / "manifest.json").write_text( json.dumps(manifest, indent=2, ensure_ascii=False) + "\n", encoding="utf-8" ) + write_branding_readme(files) if __name__ == "__main__": diff --git a/tests/test_brand_assets.py b/tests/test_brand_assets.py index ee8487c..041d6bf 100644 --- a/tests/test_brand_assets.py +++ b/tests/test_brand_assets.py @@ -71,6 +71,15 @@ class BrandAssetsTests(unittest.TestCase): (GENERATED / "ios" / "AppIcon.appiconset" / "Contents.json").read_text(encoding="utf-8") ) + def test_branding_readme_catalogs_every_image(self): + readme = (BRANDING / "README.md").read_text(encoding="utf-8") + image_suffixes = {".png", ".ico", ".icns"} + for record in self.manifest["files"]: + relative = record["path"] + if Path(relative).suffix.lower() in image_suffixes: + with self.subTest(path=relative): + self.assertIn(f"generated/{relative}", readme) + if __name__ == "__main__": unittest.main()