branding: four skeuomorphic wallpapers; the old art goes
tools/wallpapers.py writes them from the Shift geometry, so they follow the mark: Graphite (the default), Strata, Porcelain (light) and Dial. Each is a 3840x2160 SVG with a JPEG render beside it. JPEG is the right format for gradients under grain, and the branding README now says why this is the one exception to its no-JPEG rule. Removed: wallpaper1 (drawn flat, and built on the retired Guru mark), the site's unused copy of it, and the two superseded wordmark PNGs. The root README showed one of those, and now shows Graphite. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
|
|
@ -1,6 +1,8 @@
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
<img src="docs/branding/superseded-full-logo.png" alt="SchOS" width="360">
|
<img src="docs/branding/wallpapers/graphite.jpg" alt="SchOS — Shift, lit, on graphite" width="720">
|
||||||
|
|
||||||
|
# SchOS
|
||||||
|
|
||||||
**A 64-bit operating system, written from the metal up.**
|
**A 64-bit operating system, written from the metal up.**
|
||||||
|
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 132 KiB |
|
|
@ -99,6 +99,12 @@ No JPEG anywhere — a mark is flat colour with hard edges, which is the exact
|
||||||
case JPEG is worst at, and the ringing it leaves around an edge is permanent.
|
case JPEG is worst at, and the ringing it leaves around an edge is permanent.
|
||||||
No screenshots of marks. No re-exports of re-exports: go back to the SVG.
|
No screenshots of marks. No re-exports of re-exports: go back to the SVG.
|
||||||
|
|
||||||
|
**Wallpapers are the one exception**, and the reason is the same rule read the
|
||||||
|
other way round. They are soft gradients under a film of grain: no hard edge
|
||||||
|
for JPEG to ring around, and nothing a PNG can compress -- the grain made each
|
||||||
|
one nine megabytes as PNG and about a hundred kilobytes as JPEG, with no
|
||||||
|
difference anyone can see. The SVG is still the source; the JPEG is a render.
|
||||||
|
|
||||||
**SVG is the source of truth for every mark.** A raster is something generated
|
**SVG is the source of truth for every mark.** A raster is something generated
|
||||||
from it, never edited.
|
from it, never edited.
|
||||||
|
|
||||||
|
|
@ -128,9 +134,33 @@ shift.svg the logo, in colour
|
||||||
shift-mask.svg the same geometry in greys -- see below
|
shift-mask.svg the same geometry in greys -- see below
|
||||||
shift-mask.png rasterised from it, committed on purpose
|
shift-mask.png rasterised from it, committed on purpose
|
||||||
uberblock.svg SchFS
|
uberblock.svg SchFS
|
||||||
superseded-*.png the old wordmark, kept for reference only
|
wallpapers/ 3840x2160, SVG and a JPEG render of each
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Wallpapers
|
||||||
|
|
||||||
|
Generated by `tools/wallpapers.py` from the Shift geometry in `shift.svg`, so a
|
||||||
|
change to the mark is one command away from every wallpaper rather than four
|
||||||
|
hand edits. Rendered to JPEG with a browser, because a browser is the renderer
|
||||||
|
that gets the SVG lighting filters right:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
python3 tools/wallpapers.py
|
||||||
|
chromium --headless=new --window-size=3840,2160 --screenshot=graphite.jpg page.html
|
||||||
|
```
|
||||||
|
|
||||||
|
where `page.html` is an `<img>` of the SVG at 3840x2160.
|
||||||
|
|
||||||
|
| | |
|
||||||
|
|---|---|
|
||||||
|
| `graphite` | Shift on warm graphite, throwing a violet pool of light on the surface. The default. |
|
||||||
|
| `strata` | The slabs repeated into a cascade receding into indigo, near ones sharp, far ones soft. |
|
||||||
|
| `porcelain` | The light one: Shift as glazed porcelain on paper, the top slab in the accent. |
|
||||||
|
| `dial` | The uberblock ring as hardware -- a turned metal face, slots as keys, the newest one and the root lit. |
|
||||||
|
|
||||||
|
The wallpaper they replace used Guru, which is retired (see the top of this
|
||||||
|
file), and was drawn flat.
|
||||||
|
|
||||||
The pipeline is three stages:
|
The pipeline is three stages:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 132 KiB |
BIN
docs/branding/wallpapers/dial.jpg
Normal file
|
After Width: | Height: | Size: 149 KiB |
65
docs/branding/wallpapers/dial.svg
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
docs/branding/wallpapers/graphite.jpg
Normal file
|
After Width: | Height: | Size: 121 KiB |
121
docs/branding/wallpapers/graphite.svg
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3840 2160" width="3840" height="2160">
|
||||||
|
<title>SchOS — Graphite</title>
|
||||||
|
<desc>Shift on warm graphite, lit from the upper left, casting a violet pool of light on the surface it stands on.</desc>
|
||||||
|
<defs>
|
||||||
|
|
||||||
|
<!-- top faces: lit corner to far corner -->
|
||||||
|
<linearGradient id="sh-t1" x1="0" y1="0" x2="1" y2="1">
|
||||||
|
<stop offset="0" stop-color="#A48CFF"/>
|
||||||
|
<stop offset="0.55" stop-color="#7C5CFF"/>
|
||||||
|
<stop offset="1" stop-color="#6A48F0"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="sh-t2" x1="0" y1="0" x2="1" y2="1">
|
||||||
|
<stop offset="0" stop-color="#8064E6"/>
|
||||||
|
<stop offset="0.55" stop-color="#5B44C4"/>
|
||||||
|
<stop offset="1" stop-color="#4E39AE"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="sh-t3" x1="0" y1="0" x2="1" y2="1">
|
||||||
|
<stop offset="0" stop-color="#5A48A8"/>
|
||||||
|
<stop offset="0.55" stop-color="#3C2E85"/>
|
||||||
|
<stop offset="1" stop-color="#332772"/>
|
||||||
|
</linearGradient>
|
||||||
|
<!-- front faces: lit at the top edge, falling into shade -->
|
||||||
|
<linearGradient id="sh-f1" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0" stop-color="#6E50E8"/>
|
||||||
|
<stop offset="1" stop-color="#4E35BC"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="sh-f2" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0" stop-color="#4E3AAE"/>
|
||||||
|
<stop offset="1" stop-color="#372887"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="sh-f3" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0" stop-color="#342874"/>
|
||||||
|
<stop offset="1" stop-color="#231A52"/>
|
||||||
|
</linearGradient>
|
||||||
|
<!-- end walls: facing away from the light -->
|
||||||
|
<linearGradient id="sh-w1" x1="0" y1="0" x2="1" y2="1">
|
||||||
|
<stop offset="0" stop-color="#4F36B4"/>
|
||||||
|
<stop offset="1" stop-color="#3A2690"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="sh-w2" x1="0" y1="0" x2="1" y2="1">
|
||||||
|
<stop offset="0" stop-color="#3A2A86"/>
|
||||||
|
<stop offset="1" stop-color="#2B1F68"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="sh-w3" x1="0" y1="0" x2="1" y2="1">
|
||||||
|
<stop offset="0" stop-color="#261C56"/>
|
||||||
|
<stop offset="1" stop-color="#1A133E"/>
|
||||||
|
</linearGradient>
|
||||||
|
<!-- the gloss across each top face, strongest at its back edge -->
|
||||||
|
<linearGradient id="sh-gloss" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0" stop-color="#FFFFFF" stop-opacity="0.38"/>
|
||||||
|
<stop offset="0.45" stop-color="#FFFFFF" stop-opacity="0.08"/>
|
||||||
|
<stop offset="1" stop-color="#FFFFFF" stop-opacity="0"/>
|
||||||
|
</linearGradient>
|
||||||
|
<filter id="sh-soft" x="-20%" y="-40%" width="140%" height="180%">
|
||||||
|
<feGaussianBlur stdDeviation="4"/>
|
||||||
|
</filter>
|
||||||
|
|
||||||
|
<radialGradient id="ground" cx="0.32" cy="0.18" r="1.05">
|
||||||
|
<stop offset="0" stop-color="#3A3530"/>
|
||||||
|
<stop offset="0.45" stop-color="#1E1B19"/>
|
||||||
|
<stop offset="1" stop-color="#0B0A09"/>
|
||||||
|
</radialGradient>
|
||||||
|
<radialGradient id="pool" cx="0.5" cy="0.5" r="0.5">
|
||||||
|
<stop offset="0" stop-color="#7C5CFF" stop-opacity="0.42"/>
|
||||||
|
<stop offset="0.5" stop-color="#5B3FC9" stop-opacity="0.14"/>
|
||||||
|
<stop offset="1" stop-color="#5B3FC9" stop-opacity="0"/>
|
||||||
|
</radialGradient>
|
||||||
|
<radialGradient id="vignette" cx="0.5" cy="0.5" r="0.75">
|
||||||
|
<stop offset="0.6" stop-color="#000" stop-opacity="0"/>
|
||||||
|
<stop offset="1" stop-color="#000" stop-opacity="0.55"/>
|
||||||
|
</radialGradient>
|
||||||
|
<filter id="grain" x="0" y="0" width="100%" height="100%">
|
||||||
|
<feTurbulence type="fractalNoise" baseFrequency="0.85" numOctaves="2" stitchTiles="stitch"/>
|
||||||
|
<feColorMatrix type="saturate" values="0"/>
|
||||||
|
<feComponentTransfer><feFuncA type="table" tableValues="0 0.07"/></feComponentTransfer>
|
||||||
|
</filter>
|
||||||
|
<filter id="far" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="60"/></filter>
|
||||||
|
</defs>
|
||||||
|
<rect width="3840" height="2160" fill="url(#ground)"/>
|
||||||
|
<ellipse cx="1980.0" cy="1410.0" rx="1500" ry="520" fill="url(#pool)"/>
|
||||||
|
<ellipse cx="2010.0" cy="1550.0" rx="820" ry="70" fill="#000" opacity="0.55" filter="url(#far)"/>
|
||||||
|
<g transform="translate(1244.2 385.6) scale(6.2)">
|
||||||
|
|
||||||
|
|
||||||
|
<path fill="#000" opacity="0.35" filter="url(#sh-soft)" d="M58 138 L160 138 L132 170 L28 170 Z"/>
|
||||||
|
<path fill="#000" opacity="0.30" filter="url(#sh-soft)" d="M76 96 L178 96 L150 128 L46 128 Z"/>
|
||||||
|
<path fill="#000" opacity="0.26" filter="url(#sh-soft)" d="M94 54 L196 54 L168 86 L64 86 Z"/>
|
||||||
|
|
||||||
|
|
||||||
|
<path fill="url(#sh-t3)" d="M54 126 L158 126 L128 156 L24 156 Z"/>
|
||||||
|
<path fill="url(#sh-gloss)" d="M54 126 L158 126 L128 156 L24 156 Z"/>
|
||||||
|
<path fill="url(#sh-f3)" d="M24 156 L128 156 L128 167 L24 167 Z"/>
|
||||||
|
<path fill="url(#sh-w3)" d="M158 126 L158 137 L128 167 L128 156 Z"/>
|
||||||
|
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.35" stroke-width="1.2"
|
||||||
|
stroke-linecap="round" d="M24.6 155.4 L54.4 126.6 L157 126.6"/>
|
||||||
|
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.16" stroke-width="1"
|
||||||
|
d="M24 156.5 L128 156.5"/>
|
||||||
|
|
||||||
|
|
||||||
|
<path fill="url(#sh-t2)" d="M72 84 L176 84 L146 114 L42 114 Z"/>
|
||||||
|
<path fill="url(#sh-gloss)" d="M72 84 L176 84 L146 114 L42 114 Z"/>
|
||||||
|
<path fill="url(#sh-f2)" d="M42 114 L146 114 L146 125 L42 125 Z"/>
|
||||||
|
<path fill="url(#sh-w2)" d="M176 84 L176 95 L146 125 L146 114 Z"/>
|
||||||
|
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.42" stroke-width="1.2"
|
||||||
|
stroke-linecap="round" d="M42.6 113.4 L72.4 84.6 L175 84.6"/>
|
||||||
|
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.18" stroke-width="1"
|
||||||
|
d="M42 114.5 L146 114.5"/>
|
||||||
|
|
||||||
|
|
||||||
|
<path fill="url(#sh-t1)" d="M90 42 L194 42 L164 72 L60 72 Z"/>
|
||||||
|
<path fill="url(#sh-gloss)" d="M90 42 L194 42 L164 72 L60 72 Z"/>
|
||||||
|
<path fill="url(#sh-f1)" d="M60 72 L164 72 L164 83 L60 83 Z"/>
|
||||||
|
<path fill="url(#sh-w1)" d="M194 42 L194 53 L164 83 L164 72 Z"/>
|
||||||
|
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.55" stroke-width="1.2"
|
||||||
|
stroke-linecap="round" d="M60.6 71.4 L90.4 42.6 L193 42.6"/>
|
||||||
|
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.22" stroke-width="1"
|
||||||
|
d="M60 72.5 L164 72.5"/>
|
||||||
|
</g>
|
||||||
|
<rect width="3840" height="2160" fill="url(#vignette)"/>
|
||||||
|
<rect width="3840" height="2160" filter="url(#grain)"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 6 KiB |
BIN
docs/branding/wallpapers/porcelain.jpg
Normal file
|
After Width: | Height: | Size: 76 KiB |
46
docs/branding/wallpapers/porcelain.svg
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3840 2160" width="3840" height="2160">
|
||||||
|
<title>SchOS — Porcelain</title>
|
||||||
|
<desc>The light one: Shift as glazed porcelain on soft paper, with the accent spent on the top slab alone.</desc>
|
||||||
|
<defs>
|
||||||
|
<radialGradient id="paper" cx="0.3" cy="0.2" r="1.1">
|
||||||
|
<stop offset="0" stop-color="#F6F4EF"/>
|
||||||
|
<stop offset="0.6" stop-color="#E6E2DA"/>
|
||||||
|
<stop offset="1" stop-color="#D3CEC4"/>
|
||||||
|
</radialGradient>
|
||||||
|
<linearGradient id="pt" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#FFFFFF"/><stop offset="1" stop-color="#ECE8E0"/></linearGradient>
|
||||||
|
<linearGradient id="pf" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#D9D3C8"/><stop offset="1" stop-color="#C4BDB0"/></linearGradient>
|
||||||
|
<linearGradient id="pw" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#BDB5A7"/><stop offset="1" stop-color="#A9A092"/></linearGradient>
|
||||||
|
<linearGradient id="pvt" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#C9BBFF"/><stop offset="0.6" stop-color="#9479FF"/><stop offset="1" stop-color="#7C5CFF"/></linearGradient>
|
||||||
|
<linearGradient id="pvf" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#6E50E8"/><stop offset="1" stop-color="#5236C8"/></linearGradient>
|
||||||
|
<linearGradient id="pvw" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#5338BC"/><stop offset="1" stop-color="#40289A"/></linearGradient>
|
||||||
|
<filter id="lift" x="-30%" y="-30%" width="160%" height="170%">
|
||||||
|
<feGaussianBlur in="SourceAlpha" stdDeviation="4"/>
|
||||||
|
<feOffset dx="5" dy="9" result="o"/>
|
||||||
|
<feComponentTransfer><feFuncA type="linear" slope="0.28"/></feComponentTransfer>
|
||||||
|
<feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>
|
||||||
|
</filter>
|
||||||
|
<filter id="bevel" x="-10%" y="-10%" width="120%" height="120%">
|
||||||
|
<feGaussianBlur in="SourceAlpha" stdDeviation="0.9" result="h"/>
|
||||||
|
<feSpecularLighting in="h" surfaceScale="2.5" specularConstant="0.7" specularExponent="18" lighting-color="#FFFFFF" result="s">
|
||||||
|
<feDistantLight azimuth="225" elevation="42"/>
|
||||||
|
</feSpecularLighting>
|
||||||
|
<feComposite in="s" in2="SourceAlpha" operator="in" result="sa"/>
|
||||||
|
<feComposite in="SourceGraphic" in2="sa" operator="arithmetic" k2="1" k3="0.6"/>
|
||||||
|
</filter>
|
||||||
|
<radialGradient id="accent" cx="0.5" cy="0.5" r="0.5">
|
||||||
|
<stop offset="0" stop-color="#7C5CFF" stop-opacity="0.22"/>
|
||||||
|
<stop offset="1" stop-color="#7C5CFF" stop-opacity="0"/>
|
||||||
|
</radialGradient>
|
||||||
|
<filter id="grain" x="0" y="0" width="100%" height="100%">
|
||||||
|
<feTurbulence type="fractalNoise" baseFrequency="0.85" numOctaves="2" stitchTiles="stitch"/>
|
||||||
|
<feColorMatrix type="saturate" values="0"/>
|
||||||
|
<feComponentTransfer><feFuncA type="table" tableValues="0 0.06"/></feComponentTransfer>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<rect width="3840" height="2160" fill="url(#paper)"/>
|
||||||
|
<ellipse cx="2040.0" cy="1500.0" rx="1100" ry="260" fill="url(#accent)"/>
|
||||||
|
<g transform="translate(1266.0 432.0) scale(6.0)" filter="url(#lift)">
|
||||||
|
<g filter="url(#bevel)"><path d="M54 126 L158 126 L128 156 L24 156 Z" fill="url(#pt)"/><path d="M24 156 L128 156 L128 167 L24 167 Z" fill="url(#pf)"/><path d="M158 126 L158 137 L128 167 L128 156 Z" fill="url(#pw)"/><path d="M72 84 L176 84 L146 114 L42 114 Z" fill="url(#pt)"/><path d="M42 114 L146 114 L146 125 L42 125 Z" fill="url(#pf)"/><path d="M176 84 L176 95 L146 125 L146 114 Z" fill="url(#pw)"/><path d="M90 42 L194 42 L164 72 L60 72 Z" fill="url(#pvt)"/><path d="M60 72 L164 72 L164 83 L60 83 Z" fill="url(#pvf)"/><path d="M194 42 L194 53 L164 83 L164 72 Z" fill="url(#pvw)"/></g>
|
||||||
|
</g>
|
||||||
|
<rect width="3840" height="2160" filter="url(#grain)"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.6 KiB |
BIN
docs/branding/wallpapers/strata.jpg
Normal file
|
After Width: | Height: | Size: 150 KiB |
94
docs/branding/wallpapers/strata.svg
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3840 2160" width="3840" height="2160">
|
||||||
|
<title>SchOS — Strata</title>
|
||||||
|
<desc>Shift's slabs, repeated into a cascade that recedes into an indigo dark: near ones sharp and bright, far ones soft.</desc>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="sky" x1="0" y1="0" x2="0.4" y2="1">
|
||||||
|
<stop offset="0" stop-color="#1A1438"/>
|
||||||
|
<stop offset="0.55" stop-color="#0C0A1C"/>
|
||||||
|
<stop offset="1" stop-color="#050409"/>
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient id="bloom" cx="0.5" cy="0.5" r="0.5">
|
||||||
|
<stop offset="0" stop-color="#8E72FF" stop-opacity="0.55"/>
|
||||||
|
<stop offset="1" stop-color="#7C5CFF" stop-opacity="0"/>
|
||||||
|
</radialGradient>
|
||||||
|
<linearGradient id="gloss" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0" stop-color="#fff" stop-opacity="0.34"/>
|
||||||
|
<stop offset="0.5" stop-color="#fff" stop-opacity="0.05"/>
|
||||||
|
<stop offset="1" stop-color="#fff" stop-opacity="0"/>
|
||||||
|
</linearGradient>
|
||||||
|
<filter id="grain" x="0" y="0" width="100%" height="100%">
|
||||||
|
<feTurbulence type="fractalNoise" baseFrequency="0.85" numOctaves="2" stitchTiles="stitch"/>
|
||||||
|
<feColorMatrix type="saturate" values="0"/>
|
||||||
|
<feComponentTransfer><feFuncA type="table" tableValues="0 0.05"/></feComponentTransfer>
|
||||||
|
</filter>
|
||||||
|
<filter id="far" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="7"/></filter>
|
||||||
|
<filter id="farther" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="18"/></filter>
|
||||||
|
<filter id="shadow" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="28"/></filter>
|
||||||
|
<linearGradient id="d0t" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#A690FF"/><stop offset="0.55" stop-color="#7C5CFF"/><stop offset="1" stop-color="#6D51E0"/></linearGradient>
|
||||||
|
<linearGradient id="d0f" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#6D51E0"/><stop offset="1" stop-color="#4D399E"/></linearGradient>
|
||||||
|
<linearGradient id="d0w" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#513CA6"/><stop offset="1" stop-color="#382973"/></linearGradient>
|
||||||
|
<linearGradient id="d1t" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#9887E5"/><stop offset="0.55" stop-color="#684ED9"/><stop offset="1" stop-color="#5C45BF"/></linearGradient>
|
||||||
|
<linearGradient id="d1f" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#5C45BF"/><stop offset="1" stop-color="#403087"/></linearGradient>
|
||||||
|
<linearGradient id="d1w" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#44338D"/><stop offset="1" stop-color="#2F2362"/></linearGradient>
|
||||||
|
<linearGradient id="d2t" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#8A7CCB"/><stop offset="0.55" stop-color="#533FB2"/><stop offset="1" stop-color="#49379D"/></linearGradient>
|
||||||
|
<linearGradient id="d2f" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#49379D"/><stop offset="1" stop-color="#33276E"/></linearGradient>
|
||||||
|
<linearGradient id="d2w" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#362974"/><stop offset="1" stop-color="#251C50"/></linearGradient>
|
||||||
|
<linearGradient id="d3t" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#7C72B1"/><stop offset="0.55" stop-color="#3E308C"/><stop offset="1" stop-color="#372A7B"/></linearGradient>
|
||||||
|
<linearGradient id="d3f" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#372A7B"/><stop offset="1" stop-color="#261E57"/></linearGradient>
|
||||||
|
<linearGradient id="d3w" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#281F5B"/><stop offset="1" stop-color="#1C163F"/></linearGradient>
|
||||||
|
<linearGradient id="d4t" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#6E6997"/><stop offset="0.55" stop-color="#2A2266"/><stop offset="1" stop-color="#251E5A"/></linearGradient>
|
||||||
|
<linearGradient id="d4f" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#251E5A"/><stop offset="1" stop-color="#1A153F"/></linearGradient>
|
||||||
|
<linearGradient id="d4w" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#1B1642"/><stop offset="1" stop-color="#130F2E"/></linearGradient>
|
||||||
|
</defs>
|
||||||
|
<rect width="3840" height="2160" fill="url(#sky)"/>
|
||||||
|
<ellipse cx="2300" cy="1150" rx="1900" ry="1100" fill="url(#bloom)"/>
|
||||||
|
<g filter="url(#farther)">
|
||||||
|
<path d="M1635.0 16.0 L2015.0 16.0 L1920.0 131.0 L1540.0 131.0 Z" fill="#000" opacity="0.25" filter="url(#shadow)"/>
|
||||||
|
<g opacity="0.55"><path d="M1595.0 -60.0 L1975.0 -60.0 L1880.0 35.0 L1500.0 35.0 Z" fill="url(#d4t)"/><path d="M1595.0 -60.0 L1975.0 -60.0 L1880.0 35.0 L1500.0 35.0 Z" fill="url(#gloss)"/><path d="M1500.0 35.0 L1880.0 35.0 L1880.0 61.0 L1500.0 61.0 Z" fill="url(#d4f)"/><path d="M1975.0 -60.0 L1975.0 -34.0 L1880.0 61.0 L1880.0 35.0 Z" fill="url(#d4w)"/><path d="M1500.6 34.4 L1595.4 -59.4 L1974.0 -59.4" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="2.9" stroke-linecap="round"/></g>
|
||||||
|
<path d="M1485.0 166.0 L1865.0 166.0 L1770.0 281.0 L1390.0 281.0 Z" fill="#000" opacity="0.25" filter="url(#shadow)"/>
|
||||||
|
<g opacity="0.55"><path d="M1445.0 90.0 L1825.0 90.0 L1730.0 185.0 L1350.0 185.0 Z" fill="url(#d4t)"/><path d="M1445.0 90.0 L1825.0 90.0 L1730.0 185.0 L1350.0 185.0 Z" fill="url(#gloss)"/><path d="M1350.0 185.0 L1730.0 185.0 L1730.0 211.0 L1350.0 211.0 Z" fill="url(#d4f)"/><path d="M1825.0 90.0 L1825.0 116.0 L1730.0 211.0 L1730.0 185.0 Z" fill="url(#d4w)"/><path d="M1350.6 184.4 L1445.4 90.6 L1824.0 90.6" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="2.9" stroke-linecap="round"/></g>
|
||||||
|
<path d="M1335.0 316.0 L1715.0 316.0 L1620.0 431.0 L1240.0 431.0 Z" fill="#000" opacity="0.25" filter="url(#shadow)"/>
|
||||||
|
<g opacity="0.55"><path d="M1295.0 240.0 L1675.0 240.0 L1580.0 335.0 L1200.0 335.0 Z" fill="url(#d4t)"/><path d="M1295.0 240.0 L1675.0 240.0 L1580.0 335.0 L1200.0 335.0 Z" fill="url(#gloss)"/><path d="M1200.0 335.0 L1580.0 335.0 L1580.0 361.0 L1200.0 361.0 Z" fill="url(#d4f)"/><path d="M1675.0 240.0 L1675.0 266.0 L1580.0 361.0 L1580.0 335.0 Z" fill="url(#d4w)"/><path d="M1200.6 334.4 L1295.4 240.6 L1674.0 240.6" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="2.9" stroke-linecap="round"/></g>
|
||||||
|
<path d="M1185.0 466.0 L1565.0 466.0 L1470.0 581.0 L1090.0 581.0 Z" fill="#000" opacity="0.25" filter="url(#shadow)"/>
|
||||||
|
<g opacity="0.55"><path d="M1145.0 390.0 L1525.0 390.0 L1430.0 485.0 L1050.0 485.0 Z" fill="url(#d4t)"/><path d="M1145.0 390.0 L1525.0 390.0 L1430.0 485.0 L1050.0 485.0 Z" fill="url(#gloss)"/><path d="M1050.0 485.0 L1430.0 485.0 L1430.0 511.0 L1050.0 511.0 Z" fill="url(#d4f)"/><path d="M1525.0 390.0 L1525.0 416.0 L1430.0 511.0 L1430.0 485.0 Z" fill="url(#d4w)"/><path d="M1050.6 484.4 L1145.4 390.6 L1524.0 390.6" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="2.9" stroke-linecap="round"/></g>
|
||||||
|
<path d="M1035.0 616.0 L1415.0 616.0 L1320.0 731.0 L940.0 731.0 Z" fill="#000" opacity="0.25" filter="url(#shadow)"/>
|
||||||
|
<g opacity="0.55"><path d="M995.0 540.0 L1375.0 540.0 L1280.0 635.0 L900.0 635.0 Z" fill="url(#d4t)"/><path d="M995.0 540.0 L1375.0 540.0 L1280.0 635.0 L900.0 635.0 Z" fill="url(#gloss)"/><path d="M900.0 635.0 L1280.0 635.0 L1280.0 661.0 L900.0 661.0 Z" fill="url(#d4f)"/><path d="M1375.0 540.0 L1375.0 566.0 L1280.0 661.0 L1280.0 635.0 Z" fill="url(#d4w)"/><path d="M900.6 634.4 L995.4 540.6 L1374.0 540.6" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="2.9" stroke-linecap="round"/></g>
|
||||||
|
<path d="M885.0 766.0 L1265.0 766.0 L1170.0 881.0 L790.0 881.0 Z" fill="#000" opacity="0.25" filter="url(#shadow)"/>
|
||||||
|
<g opacity="0.55"><path d="M845.0 690.0 L1225.0 690.0 L1130.0 785.0 L750.0 785.0 Z" fill="url(#d4t)"/><path d="M845.0 690.0 L1225.0 690.0 L1130.0 785.0 L750.0 785.0 Z" fill="url(#gloss)"/><path d="M750.0 785.0 L1130.0 785.0 L1130.0 811.0 L750.0 811.0 Z" fill="url(#d4f)"/><path d="M1225.0 690.0 L1225.0 716.0 L1130.0 811.0 L1130.0 785.0 Z" fill="url(#d4w)"/><path d="M750.6 784.4 L845.4 690.6 L1224.0 690.6" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="2.9" stroke-linecap="round"/></g>
|
||||||
|
<path d="M735.0 916.0 L1115.0 916.0 L1020.0 1031.0 L640.0 1031.0 Z" fill="#000" opacity="0.25" filter="url(#shadow)"/>
|
||||||
|
<g opacity="0.55"><path d="M695.0 840.0 L1075.0 840.0 L980.0 935.0 L600.0 935.0 Z" fill="url(#d4t)"/><path d="M695.0 840.0 L1075.0 840.0 L980.0 935.0 L600.0 935.0 Z" fill="url(#gloss)"/><path d="M600.0 935.0 L980.0 935.0 L980.0 961.0 L600.0 961.0 Z" fill="url(#d4f)"/><path d="M1075.0 840.0 L1075.0 866.0 L980.0 961.0 L980.0 935.0 Z" fill="url(#d4w)"/><path d="M600.6 934.4 L695.4 840.6 L1074.0 840.6" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="2.9" stroke-linecap="round"/></g>
|
||||||
|
<path d="M585.0 1066.0 L965.0 1066.0 L870.0 1181.0 L490.0 1181.0 Z" fill="#000" opacity="0.25" filter="url(#shadow)"/>
|
||||||
|
<g opacity="0.55"><path d="M545.0 990.0 L925.0 990.0 L830.0 1085.0 L450.0 1085.0 Z" fill="url(#d4t)"/><path d="M545.0 990.0 L925.0 990.0 L830.0 1085.0 L450.0 1085.0 Z" fill="url(#gloss)"/><path d="M450.0 1085.0 L830.0 1085.0 L830.0 1111.0 L450.0 1111.0 Z" fill="url(#d4f)"/><path d="M925.0 990.0 L925.0 1016.0 L830.0 1111.0 L830.0 1085.0 Z" fill="url(#d4w)"/><path d="M450.6 1084.4 L545.4 990.6 L924.0 990.6" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="2.9" stroke-linecap="round"/></g>
|
||||||
|
<path d="M435.0 1216.0 L815.0 1216.0 L720.0 1331.0 L340.0 1331.0 Z" fill="#000" opacity="0.25" filter="url(#shadow)"/>
|
||||||
|
<g opacity="0.55"><path d="M395.0 1140.0 L775.0 1140.0 L680.0 1235.0 L300.0 1235.0 Z" fill="url(#d4t)"/><path d="M395.0 1140.0 L775.0 1140.0 L680.0 1235.0 L300.0 1235.0 Z" fill="url(#gloss)"/><path d="M300.0 1235.0 L680.0 1235.0 L680.0 1261.0 L300.0 1261.0 Z" fill="url(#d4f)"/><path d="M775.0 1140.0 L775.0 1166.0 L680.0 1261.0 L680.0 1235.0 Z" fill="url(#d4w)"/><path d="M300.6 1234.4 L395.4 1140.6 L774.0 1140.6" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="2.9" stroke-linecap="round"/></g>
|
||||||
|
</g>
|
||||||
|
<g filter="url(#far)">
|
||||||
|
<path d="M3610.0 54.0 L4230.0 54.0 L4080.0 224.0 L3460.0 224.0 Z" fill="#000" opacity="0.36" filter="url(#shadow)"/>
|
||||||
|
<g opacity="0.80"><path d="M3570.0 -40.0 L4190.0 -40.0 L4040.0 110.0 L3420.0 110.0 Z" fill="url(#d2t)"/><path d="M3570.0 -40.0 L4190.0 -40.0 L4040.0 110.0 L3420.0 110.0 Z" fill="url(#gloss)"/><path d="M3420.0 110.0 L4040.0 110.0 L4040.0 154.0 L3420.0 154.0 Z" fill="url(#d2f)"/><path d="M4190.0 -40.0 L4190.0 4.0 L4040.0 154.0 L4040.0 110.0 Z" fill="url(#d2w)"/><path d="M3420.6 109.4 L3570.4 -39.4 L4189.0 -39.4" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="4.9" stroke-linecap="round"/></g>
|
||||||
|
<path d="M3380.0 294.0 L4000.0 294.0 L3850.0 464.0 L3230.0 464.0 Z" fill="#000" opacity="0.36" filter="url(#shadow)"/>
|
||||||
|
<g opacity="0.80"><path d="M3340.0 200.0 L3960.0 200.0 L3810.0 350.0 L3190.0 350.0 Z" fill="url(#d2t)"/><path d="M3340.0 200.0 L3960.0 200.0 L3810.0 350.0 L3190.0 350.0 Z" fill="url(#gloss)"/><path d="M3190.0 350.0 L3810.0 350.0 L3810.0 394.0 L3190.0 394.0 Z" fill="url(#d2f)"/><path d="M3960.0 200.0 L3960.0 244.0 L3810.0 394.0 L3810.0 350.0 Z" fill="url(#d2w)"/><path d="M3190.6 349.4 L3340.4 200.6 L3959.0 200.6" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="4.9" stroke-linecap="round"/></g>
|
||||||
|
<path d="M3150.0 534.0 L3770.0 534.0 L3620.0 704.0 L3000.0 704.0 Z" fill="#000" opacity="0.36" filter="url(#shadow)"/>
|
||||||
|
<g opacity="0.80"><path d="M3110.0 440.0 L3730.0 440.0 L3580.0 590.0 L2960.0 590.0 Z" fill="url(#d2t)"/><path d="M3110.0 440.0 L3730.0 440.0 L3580.0 590.0 L2960.0 590.0 Z" fill="url(#gloss)"/><path d="M2960.0 590.0 L3580.0 590.0 L3580.0 634.0 L2960.0 634.0 Z" fill="url(#d2f)"/><path d="M3730.0 440.0 L3730.0 484.0 L3580.0 634.0 L3580.0 590.0 Z" fill="url(#d2w)"/><path d="M2960.6 589.4 L3110.4 440.6 L3729.0 440.6" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="4.9" stroke-linecap="round"/></g>
|
||||||
|
<path d="M2920.0 774.0 L3540.0 774.0 L3390.0 944.0 L2770.0 944.0 Z" fill="#000" opacity="0.36" filter="url(#shadow)"/>
|
||||||
|
<g opacity="0.80"><path d="M2880.0 680.0 L3500.0 680.0 L3350.0 830.0 L2730.0 830.0 Z" fill="url(#d3t)"/><path d="M2880.0 680.0 L3500.0 680.0 L3350.0 830.0 L2730.0 830.0 Z" fill="url(#gloss)"/><path d="M2730.0 830.0 L3350.0 830.0 L3350.0 874.0 L2730.0 874.0 Z" fill="url(#d3f)"/><path d="M3500.0 680.0 L3500.0 724.0 L3350.0 874.0 L3350.0 830.0 Z" fill="url(#d3w)"/><path d="M2730.6 829.4 L2880.4 680.6 L3499.0 680.6" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="4.9" stroke-linecap="round"/></g>
|
||||||
|
<path d="M2690.0 1014.0 L3310.0 1014.0 L3160.0 1184.0 L2540.0 1184.0 Z" fill="#000" opacity="0.36" filter="url(#shadow)"/>
|
||||||
|
<g opacity="0.80"><path d="M2650.0 920.0 L3270.0 920.0 L3120.0 1070.0 L2500.0 1070.0 Z" fill="url(#d3t)"/><path d="M2650.0 920.0 L3270.0 920.0 L3120.0 1070.0 L2500.0 1070.0 Z" fill="url(#gloss)"/><path d="M2500.0 1070.0 L3120.0 1070.0 L3120.0 1114.0 L2500.0 1114.0 Z" fill="url(#d3f)"/><path d="M3270.0 920.0 L3270.0 964.0 L3120.0 1114.0 L3120.0 1070.0 Z" fill="url(#d3w)"/><path d="M2500.6 1069.4 L2650.4 920.6 L3269.0 920.6" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="4.9" stroke-linecap="round"/></g>
|
||||||
|
<path d="M2460.0 1254.0 L3080.0 1254.0 L2930.0 1424.0 L2310.0 1424.0 Z" fill="#000" opacity="0.36" filter="url(#shadow)"/>
|
||||||
|
<g opacity="0.80"><path d="M2420.0 1160.0 L3040.0 1160.0 L2890.0 1310.0 L2270.0 1310.0 Z" fill="url(#d3t)"/><path d="M2420.0 1160.0 L3040.0 1160.0 L2890.0 1310.0 L2270.0 1310.0 Z" fill="url(#gloss)"/><path d="M2270.0 1310.0 L2890.0 1310.0 L2890.0 1354.0 L2270.0 1354.0 Z" fill="url(#d3f)"/><path d="M3040.0 1160.0 L3040.0 1204.0 L2890.0 1354.0 L2890.0 1310.0 Z" fill="url(#d3w)"/><path d="M2270.6 1309.4 L2420.4 1160.6 L3039.0 1160.6" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="4.9" stroke-linecap="round"/></g>
|
||||||
|
<path d="M2230.0 1494.0 L2850.0 1494.0 L2700.0 1664.0 L2080.0 1664.0 Z" fill="#000" opacity="0.36" filter="url(#shadow)"/>
|
||||||
|
<g opacity="0.80"><path d="M2190.0 1400.0 L2810.0 1400.0 L2660.0 1550.0 L2040.0 1550.0 Z" fill="url(#d4t)"/><path d="M2190.0 1400.0 L2810.0 1400.0 L2660.0 1550.0 L2040.0 1550.0 Z" fill="url(#gloss)"/><path d="M2040.0 1550.0 L2660.0 1550.0 L2660.0 1594.0 L2040.0 1594.0 Z" fill="url(#d4f)"/><path d="M2810.0 1400.0 L2810.0 1444.0 L2660.0 1594.0 L2660.0 1550.0 Z" fill="url(#d4w)"/><path d="M2040.6 1549.4 L2190.4 1400.6 L2809.0 1400.6" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="4.9" stroke-linecap="round"/></g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path d="M2920.0 384.0 L3900.0 384.0 L3670.0 634.0 L2690.0 634.0 Z" fill="#000" opacity="0.45" filter="url(#shadow)"/>
|
||||||
|
<g opacity="1.00"><path d="M2880.0 260.0 L3860.0 260.0 L3630.0 490.0 L2650.0 490.0 Z" fill="url(#d0t)"/><path d="M2880.0 260.0 L3860.0 260.0 L3630.0 490.0 L2650.0 490.0 Z" fill="url(#gloss)"/><path d="M2650.0 490.0 L3630.0 490.0 L3630.0 564.0 L2650.0 564.0 Z" fill="url(#d0f)"/><path d="M3860.0 260.0 L3860.0 334.0 L3630.0 564.0 L3630.0 490.0 Z" fill="url(#d0w)"/><path d="M2650.6 489.4 L2880.4 260.6 L3859.0 260.6" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="8.2" stroke-linecap="round"/></g>
|
||||||
|
<path d="M2590.0 724.0 L3570.0 724.0 L3340.0 974.0 L2360.0 974.0 Z" fill="#000" opacity="0.45" filter="url(#shadow)"/>
|
||||||
|
<g opacity="1.00"><path d="M2550.0 600.0 L3530.0 600.0 L3300.0 830.0 L2320.0 830.0 Z" fill="url(#d0t)"/><path d="M2550.0 600.0 L3530.0 600.0 L3300.0 830.0 L2320.0 830.0 Z" fill="url(#gloss)"/><path d="M2320.0 830.0 L3300.0 830.0 L3300.0 904.0 L2320.0 904.0 Z" fill="url(#d0f)"/><path d="M3530.0 600.0 L3530.0 674.0 L3300.0 904.0 L3300.0 830.0 Z" fill="url(#d0w)"/><path d="M2320.6 829.4 L2550.4 600.6 L3529.0 600.6" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="8.2" stroke-linecap="round"/></g>
|
||||||
|
<path d="M2260.0 1064.0 L3240.0 1064.0 L3010.0 1314.0 L2030.0 1314.0 Z" fill="#000" opacity="0.45" filter="url(#shadow)"/>
|
||||||
|
<g opacity="1.00"><path d="M2220.0 940.0 L3200.0 940.0 L2970.0 1170.0 L1990.0 1170.0 Z" fill="url(#d0t)"/><path d="M2220.0 940.0 L3200.0 940.0 L2970.0 1170.0 L1990.0 1170.0 Z" fill="url(#gloss)"/><path d="M1990.0 1170.0 L2970.0 1170.0 L2970.0 1244.0 L1990.0 1244.0 Z" fill="url(#d0f)"/><path d="M3200.0 940.0 L3200.0 1014.0 L2970.0 1244.0 L2970.0 1170.0 Z" fill="url(#d0w)"/><path d="M1990.6 1169.4 L2220.4 940.6 L3199.0 940.6" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="8.2" stroke-linecap="round"/></g>
|
||||||
|
<path d="M1930.0 1404.0 L2910.0 1404.0 L2680.0 1654.0 L1700.0 1654.0 Z" fill="#000" opacity="0.45" filter="url(#shadow)"/>
|
||||||
|
<g opacity="1.00"><path d="M1890.0 1280.0 L2870.0 1280.0 L2640.0 1510.0 L1660.0 1510.0 Z" fill="url(#d1t)"/><path d="M1890.0 1280.0 L2870.0 1280.0 L2640.0 1510.0 L1660.0 1510.0 Z" fill="url(#gloss)"/><path d="M1660.0 1510.0 L2640.0 1510.0 L2640.0 1584.0 L1660.0 1584.0 Z" fill="url(#d1f)"/><path d="M2870.0 1280.0 L2870.0 1354.0 L2640.0 1584.0 L2640.0 1510.0 Z" fill="url(#d1w)"/><path d="M1660.6 1509.4 L1890.4 1280.6 L2869.0 1280.6" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="8.2" stroke-linecap="round"/></g>
|
||||||
|
<path d="M1600.0 1744.0 L2580.0 1744.0 L2350.0 1994.0 L1370.0 1994.0 Z" fill="#000" opacity="0.45" filter="url(#shadow)"/>
|
||||||
|
<g opacity="1.00"><path d="M1560.0 1620.0 L2540.0 1620.0 L2310.0 1850.0 L1330.0 1850.0 Z" fill="url(#d1t)"/><path d="M1560.0 1620.0 L2540.0 1620.0 L2310.0 1850.0 L1330.0 1850.0 Z" fill="url(#gloss)"/><path d="M1330.0 1850.0 L2310.0 1850.0 L2310.0 1924.0 L1330.0 1924.0 Z" fill="url(#d1f)"/><path d="M2540.0 1620.0 L2540.0 1694.0 L2310.0 1924.0 L2310.0 1850.0 Z" fill="url(#d1w)"/><path d="M1330.6 1849.4 L1560.4 1620.6 L2539.0 1620.6" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="8.2" stroke-linecap="round"/></g>
|
||||||
|
</g>
|
||||||
|
<rect width="3840" height="2160" filter="url(#grain)"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 17 KiB |
320
tools/wallpapers.py
Normal file
|
|
@ -0,0 +1,320 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#
|
||||||
|
# The SchOS wallpapers, written out as SVG.
|
||||||
|
#
|
||||||
|
# tools/wallpapers.py [OUTDIR] (default: docs/branding/wallpapers)
|
||||||
|
#
|
||||||
|
# Generated rather than drawn, for the same reason the include rewrite is a
|
||||||
|
# script: every one of them is the Shift geometry from docs/branding/shift.svg
|
||||||
|
# under a different light, and a hand-edited copy of a path is a copy that
|
||||||
|
# drifts. Change the mark there and run this again.
|
||||||
|
#
|
||||||
|
# All of them are 3840x2160 and lit the way Niveus lights a key -- one light
|
||||||
|
# from the upper left, gloss on what faces it, a soft shadow on what is under
|
||||||
|
# it -- because they sit behind a desktop built from those keys.
|
||||||
|
#
|
||||||
|
# The PNGs beside them are renders of these files (see the README there); this
|
||||||
|
# script does not write them, since the only renderer that gets the filters
|
||||||
|
# right is a browser.
|
||||||
|
|
||||||
|
import math, os, re, sys
|
||||||
|
|
||||||
|
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
OUT = sys.argv[1] if len(sys.argv) > 1 else os.path.join(ROOT, "docs/branding/wallpapers")
|
||||||
|
W, H = 3840, 2160
|
||||||
|
|
||||||
|
# --- the mark -----------------------------------------------------------------
|
||||||
|
|
||||||
|
def shift_parts():
|
||||||
|
"""Return (defs, body) of shift.svg, ids prefixed so it can be embedded."""
|
||||||
|
src = open(os.path.join(ROOT, "docs/branding/shift.svg")).read()
|
||||||
|
defs = re.search(r"<defs>(.*?)</defs>", src, re.S).group(1)
|
||||||
|
body = src[src.index("</defs>") + len("</defs>"):src.rindex("</svg>")]
|
||||||
|
body = re.sub(r"<!--.*?-->", "", body, flags=re.S)
|
||||||
|
fix = lambda s: re.sub(r'id="([^"]+)"', r'id="sh-\1"', s).replace("url(#", "url(#sh-")
|
||||||
|
return fix(defs), fix(body)
|
||||||
|
|
||||||
|
# The three slabs as plain outlines, for the wallpapers that light the mark
|
||||||
|
# themselves rather than using its own shading.
|
||||||
|
SLABS = [ # (top face, front face, end wall), bottom slab first
|
||||||
|
("M54 126 L158 126 L128 156 L24 156 Z", "M24 156 L128 156 L128 167 L24 167 Z",
|
||||||
|
"M158 126 L158 137 L128 167 L128 156 Z"),
|
||||||
|
("M72 84 L176 84 L146 114 L42 114 Z", "M42 114 L146 114 L146 125 L42 125 Z",
|
||||||
|
"M176 84 L176 95 L146 125 L146 114 Z"),
|
||||||
|
("M90 42 L194 42 L164 72 L60 72 Z", "M60 72 L164 72 L164 83 L60 83 Z",
|
||||||
|
"M194 42 L194 53 L164 83 L164 72 Z"),
|
||||||
|
]
|
||||||
|
|
||||||
|
def svg(title, desc, defs, body):
|
||||||
|
return f'''<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {W} {H}" width="{W}" height="{H}">
|
||||||
|
<title>{title}</title>
|
||||||
|
<desc>{desc}</desc>
|
||||||
|
<defs>
|
||||||
|
{defs}
|
||||||
|
</defs>
|
||||||
|
{body}
|
||||||
|
</svg>
|
||||||
|
'''
|
||||||
|
|
||||||
|
GRAIN = ''' <filter id="grain" x="0" y="0" width="100%" height="100%">
|
||||||
|
<feTurbulence type="fractalNoise" baseFrequency="0.85" numOctaves="2" stitchTiles="stitch"/>
|
||||||
|
<feColorMatrix type="saturate" values="0"/>
|
||||||
|
<feComponentTransfer><feFuncA type="table" tableValues="0 {a}"/></feComponentTransfer>
|
||||||
|
</filter>'''
|
||||||
|
|
||||||
|
def blur(id_, sd):
|
||||||
|
return f' <filter id="{id_}" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="{sd}"/></filter>'
|
||||||
|
|
||||||
|
# --- 1. Graphite ---------------------------------------------------------------
|
||||||
|
|
||||||
|
def graphite():
|
||||||
|
d, b = shift_parts()
|
||||||
|
s = 6.2
|
||||||
|
tx, ty = W / 2 - 109 * s, H / 2 - 112 * s
|
||||||
|
defs = d + f'''
|
||||||
|
<radialGradient id="ground" cx="0.32" cy="0.18" r="1.05">
|
||||||
|
<stop offset="0" stop-color="#3A3530"/>
|
||||||
|
<stop offset="0.45" stop-color="#1E1B19"/>
|
||||||
|
<stop offset="1" stop-color="#0B0A09"/>
|
||||||
|
</radialGradient>
|
||||||
|
<radialGradient id="pool" cx="0.5" cy="0.5" r="0.5">
|
||||||
|
<stop offset="0" stop-color="#7C5CFF" stop-opacity="0.42"/>
|
||||||
|
<stop offset="0.5" stop-color="#5B3FC9" stop-opacity="0.14"/>
|
||||||
|
<stop offset="1" stop-color="#5B3FC9" stop-opacity="0"/>
|
||||||
|
</radialGradient>
|
||||||
|
<radialGradient id="vignette" cx="0.5" cy="0.5" r="0.75">
|
||||||
|
<stop offset="0.6" stop-color="#000" stop-opacity="0"/>
|
||||||
|
<stop offset="1" stop-color="#000" stop-opacity="0.55"/>
|
||||||
|
</radialGradient>
|
||||||
|
''' + GRAIN.format(a="0.07") + "\n" + blur("far", 60)
|
||||||
|
body = f''' <rect width="{W}" height="{H}" fill="url(#ground)"/>
|
||||||
|
<ellipse cx="{W/2+60}" cy="{H/2+330}" rx="1500" ry="520" fill="url(#pool)"/>
|
||||||
|
<ellipse cx="{W/2+90}" cy="{H/2+470}" rx="820" ry="70" fill="#000" opacity="0.55" filter="url(#far)"/>
|
||||||
|
<g transform="translate({tx:.1f} {ty:.1f}) scale({s})">{b}</g>
|
||||||
|
<rect width="{W}" height="{H}" fill="url(#vignette)"/>
|
||||||
|
<rect width="{W}" height="{H}" filter="url(#grain)"/>'''
|
||||||
|
return svg("SchOS — Graphite",
|
||||||
|
"Shift on warm graphite, lit from the upper left, casting a violet pool of light on the surface it stands on.",
|
||||||
|
defs, body)
|
||||||
|
|
||||||
|
# --- 2. Strata -----------------------------------------------------------------
|
||||||
|
|
||||||
|
def slab(x, y, w, d, t, shade, alpha, gid):
|
||||||
|
"""One slab in Shift's oblique: top face w wide and d deep, t thick."""
|
||||||
|
k = 30 / 104 * w * (d / (30 / 104 * w)) if w else 0
|
||||||
|
# the back edge is displaced right by the depth, as in the mark
|
||||||
|
top = f"M{x+d:.1f} {y:.1f} L{x+d+w:.1f} {y:.1f} L{x+w:.1f} {y+d:.1f} L{x:.1f} {y+d:.1f} Z"
|
||||||
|
front = f"M{x:.1f} {y+d:.1f} L{x+w:.1f} {y+d:.1f} L{x+w:.1f} {y+d+t:.1f} L{x:.1f} {y+d+t:.1f} Z"
|
||||||
|
wall = f"M{x+d+w:.1f} {y:.1f} L{x+d+w:.1f} {y+t:.1f} L{x+w:.1f} {y+d+t:.1f} L{x+w:.1f} {y+d:.1f} Z"
|
||||||
|
edge = f"M{x+0.6:.1f} {y+d-0.6:.1f} L{x+d+0.4:.1f} {y+0.6:.1f} L{x+d+w-1:.1f} {y+0.6:.1f}"
|
||||||
|
return (f' <g opacity="{alpha:.2f}">'
|
||||||
|
f'<path d="{top}" fill="url(#{gid}t)"/>'
|
||||||
|
f'<path d="{top}" fill="url(#gloss)"/>'
|
||||||
|
f'<path d="{front}" fill="url(#{gid}f)"/>'
|
||||||
|
f'<path d="{wall}" fill="url(#{gid}w)"/>'
|
||||||
|
f'<path d="{edge}" fill="none" stroke="#fff" stroke-opacity="0.5" stroke-width="{max(1.5, t/9):.1f}" stroke-linecap="round"/>'
|
||||||
|
'</g>\n')
|
||||||
|
|
||||||
|
def mix(a, b, f):
|
||||||
|
pa = [int(a[i:i+2], 16) for i in (1, 3, 5)]
|
||||||
|
pb = [int(b[i:i+2], 16) for i in (1, 3, 5)]
|
||||||
|
return "#%02X%02X%02X" % tuple(round(x + (y - x) * f) for x, y in zip(pa, pb))
|
||||||
|
|
||||||
|
def strata():
|
||||||
|
defs = [''' <linearGradient id="sky" x1="0" y1="0" x2="0.4" y2="1">
|
||||||
|
<stop offset="0" stop-color="#1A1438"/>
|
||||||
|
<stop offset="0.55" stop-color="#0C0A1C"/>
|
||||||
|
<stop offset="1" stop-color="#050409"/>
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient id="bloom" cx="0.5" cy="0.5" r="0.5">
|
||||||
|
<stop offset="0" stop-color="#8E72FF" stop-opacity="0.55"/>
|
||||||
|
<stop offset="1" stop-color="#7C5CFF" stop-opacity="0"/>
|
||||||
|
</radialGradient>
|
||||||
|
<linearGradient id="gloss" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0" stop-color="#fff" stop-opacity="0.34"/>
|
||||||
|
<stop offset="0.5" stop-color="#fff" stop-opacity="0.05"/>
|
||||||
|
<stop offset="1" stop-color="#fff" stop-opacity="0"/>
|
||||||
|
</linearGradient>''', GRAIN.format(a="0.05"), blur("far", 7), blur("farther", 18), blur("shadow", 28)]
|
||||||
|
# Five depths of colour, from near (bright violet) to far (indigo, dim).
|
||||||
|
near, far = "#7C5CFF", "#2A2266"
|
||||||
|
for i in range(5):
|
||||||
|
c = mix(near, far, i / 4)
|
||||||
|
defs.append(f''' <linearGradient id="d{i}t" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="{mix(c, "#FFFFFF", 0.32)}"/><stop offset="0.55" stop-color="{c}"/><stop offset="1" stop-color="{mix(c, "#000000", 0.12)}"/></linearGradient>
|
||||||
|
<linearGradient id="d{i}f" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="{mix(c, "#000000", 0.12)}"/><stop offset="1" stop-color="{mix(c, "#000000", 0.38)}"/></linearGradient>
|
||||||
|
<linearGradient id="d{i}w" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="{mix(c, "#000000", 0.35)}"/><stop offset="1" stop-color="{mix(c, "#000000", 0.55)}"/></linearGradient>''')
|
||||||
|
|
||||||
|
# A cascade: slabs stepping down and to the left, each displaced from the
|
||||||
|
# one above exactly as Shift's are, at three distances. The near ones are
|
||||||
|
# solid and cast a shadow on what is below them; the far ones are softer
|
||||||
|
# and dimmer, which is all depth of field is.
|
||||||
|
bands = [ # (count, x0, y0, width, depth, thickness, step x, step y, colour, blur, alpha)
|
||||||
|
(9, 1500, -60, 380, 95, 26, -150, 150, 4, "farther", 0.55),
|
||||||
|
(7, 3420, -40, 620, 150, 44, -230, 240, 2, "far", 0.8),
|
||||||
|
(5, 2650, 260, 980, 230, 74, -330, 340, 0, None, 1.0),
|
||||||
|
]
|
||||||
|
body = [f' <rect width="{W}" height="{H}" fill="url(#sky)"/>\n',
|
||||||
|
f' <ellipse cx="2300" cy="1150" rx="1900" ry="1100" fill="url(#bloom)"/>\n']
|
||||||
|
for n, x0, y0, w, d, t, sx, sy, lvl, filt, alpha in bands:
|
||||||
|
body.append(f' <g filter="url(#{filt})">\n' if filt else " <g>\n")
|
||||||
|
for i in range(n):
|
||||||
|
x, y = x0 + sx * i, y0 + sy * i
|
||||||
|
sh = f"M{x+d+40:.1f} {y+t+50:.1f} L{x+d+w+40:.1f} {y+t+50:.1f} L{x+w+40:.1f} {y+d+t+70:.1f} L{x+40:.1f} {y+d+t+70:.1f} Z"
|
||||||
|
body.append(f' <path d="{sh}" fill="#000" opacity="{0.45*alpha:.2f}" filter="url(#shadow)"/>\n')
|
||||||
|
body.append(slab(x, y, w, d, t, None, alpha, f"d{min(4, lvl + i // 3)}"))
|
||||||
|
body.append(" </g>\n")
|
||||||
|
body.append(f' <rect width="{W}" height="{H}" filter="url(#grain)"/>')
|
||||||
|
return svg("SchOS — Strata",
|
||||||
|
"Shift's slabs, repeated into a cascade that recedes into an indigo dark: near ones sharp and bright, far ones soft.",
|
||||||
|
"\n".join(defs), "".join(body))
|
||||||
|
|
||||||
|
# --- 3. Porcelain (light) ------------------------------------------------------
|
||||||
|
|
||||||
|
def porcelain():
|
||||||
|
s = 6.0
|
||||||
|
tx, ty = W / 2 - 109 * s, H / 2 - 108 * s
|
||||||
|
faces = []
|
||||||
|
for i, (top, front, wall) in enumerate(SLABS):
|
||||||
|
g = "pv" if i == 2 else "p" # the top slab carries the accent, as a glaze
|
||||||
|
faces.append(f'<path d="{top}" fill="url(#{g}t)"/><path d="{front}" fill="url(#{g}f)"/><path d="{wall}" fill="url(#{g}w)"/>')
|
||||||
|
defs = ''' <radialGradient id="paper" cx="0.3" cy="0.2" r="1.1">
|
||||||
|
<stop offset="0" stop-color="#F6F4EF"/>
|
||||||
|
<stop offset="0.6" stop-color="#E6E2DA"/>
|
||||||
|
<stop offset="1" stop-color="#D3CEC4"/>
|
||||||
|
</radialGradient>
|
||||||
|
<linearGradient id="pt" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#FFFFFF"/><stop offset="1" stop-color="#ECE8E0"/></linearGradient>
|
||||||
|
<linearGradient id="pf" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#D9D3C8"/><stop offset="1" stop-color="#C4BDB0"/></linearGradient>
|
||||||
|
<linearGradient id="pw" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#BDB5A7"/><stop offset="1" stop-color="#A9A092"/></linearGradient>
|
||||||
|
<linearGradient id="pvt" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#C9BBFF"/><stop offset="0.6" stop-color="#9479FF"/><stop offset="1" stop-color="#7C5CFF"/></linearGradient>
|
||||||
|
<linearGradient id="pvf" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#6E50E8"/><stop offset="1" stop-color="#5236C8"/></linearGradient>
|
||||||
|
<linearGradient id="pvw" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#5338BC"/><stop offset="1" stop-color="#40289A"/></linearGradient>
|
||||||
|
<filter id="lift" x="-30%" y="-30%" width="160%" height="170%">
|
||||||
|
<feGaussianBlur in="SourceAlpha" stdDeviation="4"/>
|
||||||
|
<feOffset dx="5" dy="9" result="o"/>
|
||||||
|
<feComponentTransfer><feFuncA type="linear" slope="0.28"/></feComponentTransfer>
|
||||||
|
<feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>
|
||||||
|
</filter>
|
||||||
|
<filter id="bevel" x="-10%" y="-10%" width="120%" height="120%">
|
||||||
|
<feGaussianBlur in="SourceAlpha" stdDeviation="0.9" result="h"/>
|
||||||
|
<feSpecularLighting in="h" surfaceScale="2.5" specularConstant="0.7" specularExponent="18" lighting-color="#FFFFFF" result="s">
|
||||||
|
<feDistantLight azimuth="225" elevation="42"/>
|
||||||
|
</feSpecularLighting>
|
||||||
|
<feComposite in="s" in2="SourceAlpha" operator="in" result="sa"/>
|
||||||
|
<feComposite in="SourceGraphic" in2="sa" operator="arithmetic" k2="1" k3="0.6"/>
|
||||||
|
</filter>
|
||||||
|
<radialGradient id="accent" cx="0.5" cy="0.5" r="0.5">
|
||||||
|
<stop offset="0" stop-color="#7C5CFF" stop-opacity="0.22"/>
|
||||||
|
<stop offset="1" stop-color="#7C5CFF" stop-opacity="0"/>
|
||||||
|
</radialGradient>
|
||||||
|
''' + GRAIN.format(a="0.06")
|
||||||
|
body = f''' <rect width="{W}" height="{H}" fill="url(#paper)"/>
|
||||||
|
<ellipse cx="{W/2+120}" cy="{H/2+420}" rx="1100" ry="260" fill="url(#accent)"/>
|
||||||
|
<g transform="translate({tx:.1f} {ty:.1f}) scale({s})" filter="url(#lift)">
|
||||||
|
<g filter="url(#bevel)">{"".join(faces)}</g>
|
||||||
|
</g>
|
||||||
|
<rect width="{W}" height="{H}" filter="url(#grain)"/>'''
|
||||||
|
return svg("SchOS — Porcelain",
|
||||||
|
"The light one: Shift as glazed porcelain on soft paper, with the accent spent on the top slab alone.",
|
||||||
|
defs, body)
|
||||||
|
|
||||||
|
# --- 4. Dial ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
def annulus(cx, cy, r0, r1, a0, a1):
|
||||||
|
"""An annular sector, angles in degrees clockwise from twelve o'clock."""
|
||||||
|
def pt(r, a):
|
||||||
|
t = math.radians(a)
|
||||||
|
return cx + r * math.sin(t), cy - r * math.cos(t)
|
||||||
|
(x0, y0), (x1, y1) = pt(r1, a0), pt(r1, a1)
|
||||||
|
(x2, y2), (x3, y3) = pt(r0, a1), pt(r0, a0)
|
||||||
|
big = 1 if a1 - a0 > 180 else 0
|
||||||
|
return (f"M{x0:.1f} {y0:.1f} A{r1} {r1} 0 {big} 1 {x1:.1f} {y1:.1f} "
|
||||||
|
f"L{x2:.1f} {y2:.1f} A{r0} {r0} 0 {big} 0 {x3:.1f} {y3:.1f} Z")
|
||||||
|
|
||||||
|
def dial():
|
||||||
|
cx, cy = W / 2, H / 2
|
||||||
|
R = 520 # the machined face
|
||||||
|
# Brushed metal, radially: thin wedges whose lightness follows the angle
|
||||||
|
# to the light, which is what makes a turned surface look turned.
|
||||||
|
wedges = []
|
||||||
|
# Each wedge overlaps the next by more than its own width, so no seam
|
||||||
|
# between two of them is ever a pixel of background -- which is what drew
|
||||||
|
# an interference cross through the middle of the first render.
|
||||||
|
for i in range(360):
|
||||||
|
a0, a1 = i * 1.0, i * 1.0 + 2.2
|
||||||
|
lit = 0.5 + 0.5 * math.cos(math.radians(2 * (a0 - 315)))
|
||||||
|
jitter = ((i * 7919) % 13) / 13 * 0.08
|
||||||
|
v = int(34 + 46 * lit + 30 * jitter)
|
||||||
|
wedges.append(f'<path d="{annulus(cx, cy, 0.1, R, a0, a1)}" fill="#{v:02X}{v:02X}{v+6:02X}"/>')
|
||||||
|
slots = []
|
||||||
|
for k in range(12):
|
||||||
|
a0 = k * 30 - 10
|
||||||
|
if k == 1:
|
||||||
|
continue
|
||||||
|
slots.append(f'<path d="{annulus(cx, cy, R + 120, R + 290, a0, a0 + 20)}"/>')
|
||||||
|
lit_slot = annulus(cx, cy, R + 120, R + 370, 30 - 10, 30 + 10)
|
||||||
|
defs = f''' <radialGradient id="room" cx="0.5" cy="0.45" r="0.8">
|
||||||
|
<stop offset="0" stop-color="#1D1A26"/>
|
||||||
|
<stop offset="0.6" stop-color="#0D0C12"/>
|
||||||
|
<stop offset="1" stop-color="#050507"/>
|
||||||
|
</radialGradient>
|
||||||
|
<linearGradient id="slot" gradientUnits="userSpaceOnUse" x1="{cx-1000}" y1="{cy-1000}" x2="{cx+1000}" y2="{cy+1000}">
|
||||||
|
<stop offset="0" stop-color="#4B3BA0"/><stop offset="0.5" stop-color="#30246E"/><stop offset="1" stop-color="#1C1548"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="litslot" gradientUnits="userSpaceOnUse" x1="{cx+300}" y1="{cy-1100}" x2="{cx+700}" y2="{cy-700}">
|
||||||
|
<stop offset="0" stop-color="#C4B4FF"/><stop offset="0.5" stop-color="#7C5CFF"/><stop offset="1" stop-color="#5A3BE0"/>
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient id="gem" cx="0.38" cy="0.32" r="0.72">
|
||||||
|
<stop offset="0" stop-color="#F2EEFF"/><stop offset="0.25" stop-color="#A994FF"/>
|
||||||
|
<stop offset="0.7" stop-color="#7C5CFF"/><stop offset="1" stop-color="#3E24B0"/>
|
||||||
|
</radialGradient>
|
||||||
|
<radialGradient id="halo" cx="0.5" cy="0.5" r="0.5">
|
||||||
|
<stop offset="0" stop-color="#9F86FF" stop-opacity="0.6"/><stop offset="1" stop-color="#7C5CFF" stop-opacity="0"/>
|
||||||
|
</radialGradient>
|
||||||
|
<radialGradient id="facefall" cx="0.5" cy="0.5" r="0.5">
|
||||||
|
<stop offset="0.8" stop-color="#000" stop-opacity="0"/><stop offset="1" stop-color="#000" stop-opacity="0.45"/>
|
||||||
|
</radialGradient>
|
||||||
|
<linearGradient id="rim" x1="0" y1="0" x2="1" y2="1">
|
||||||
|
<stop offset="0" stop-color="#F0F0F6"/><stop offset="0.5" stop-color="#5A5A66"/><stop offset="1" stop-color="#1C1C22"/>
|
||||||
|
</linearGradient>
|
||||||
|
<filter id="bevel" x="-10%" y="-10%" width="120%" height="120%">
|
||||||
|
<feGaussianBlur in="SourceAlpha" stdDeviation="7" result="h"/>
|
||||||
|
<feSpecularLighting in="h" surfaceScale="5" specularConstant="0.9" specularExponent="28" lighting-color="#FFFFFF" result="s">
|
||||||
|
<feDistantLight azimuth="225" elevation="35"/>
|
||||||
|
</feSpecularLighting>
|
||||||
|
<feComposite in="s" in2="SourceAlpha" operator="in" result="sa"/>
|
||||||
|
<feComposite in="SourceGraphic" in2="sa" operator="arithmetic" k2="1" k3="0.35"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="drop" x="-30%" y="-30%" width="160%" height="160%">
|
||||||
|
<feGaussianBlur in="SourceAlpha" stdDeviation="22"/>
|
||||||
|
<feOffset dx="14" dy="26"/>
|
||||||
|
<feComponentTransfer><feFuncA type="linear" slope="0.6"/></feComponentTransfer>
|
||||||
|
<feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>
|
||||||
|
</filter>
|
||||||
|
''' + GRAIN.format(a="0.05") + "\n" + blur("soft", 40)
|
||||||
|
body = f''' <rect width="{W}" height="{H}" fill="url(#room)"/>
|
||||||
|
<circle cx="{cx}" cy="{cy}" r="{R+205}" fill="none" stroke="#000" stroke-opacity="0.55" stroke-width="240" filter="url(#soft)"/>
|
||||||
|
<g filter="url(#drop)"><g fill="url(#slot)" filter="url(#bevel)">{"".join(slots)}</g></g>
|
||||||
|
<circle cx="{cx + 0.5*(R+250)}" cy="{cy - 0.866*(R+250)}" r="380" fill="url(#halo)"/>
|
||||||
|
<g filter="url(#drop)"><path d="{lit_slot}" fill="url(#litslot)" filter="url(#bevel)"/></g>
|
||||||
|
<g filter="url(#drop)">
|
||||||
|
<circle cx="{cx}" cy="{cy}" r="{R+18}" fill="url(#rim)"/>
|
||||||
|
<g>{"".join(wedges)}</g>
|
||||||
|
<circle cx="{cx}" cy="{cy}" r="{R}" fill="url(#facefall)"/>
|
||||||
|
</g>
|
||||||
|
<circle cx="{cx}" cy="{cy}" r="330" fill="url(#halo)"/>
|
||||||
|
<circle cx="{cx}" cy="{cy}" r="176" fill="#120C2E"/>
|
||||||
|
<circle cx="{cx}" cy="{cy}" r="160" fill="url(#gem)"/>
|
||||||
|
<ellipse cx="{cx-50}" cy="{cy-62}" rx="56" ry="34" fill="#fff" opacity="0.7"/>
|
||||||
|
<rect width="{W}" height="{H}" filter="url(#grain)"/>'''
|
||||||
|
return svg("SchOS — Dial",
|
||||||
|
"The SchFS uberblock ring as a piece of hardware: a turned metal face, the slots as keys set around it, the newest one and the root lit.",
|
||||||
|
defs, body)
|
||||||
|
|
||||||
|
WALLS = {"graphite": graphite, "strata": strata, "porcelain": porcelain, "dial": dial}
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
os.makedirs(OUT, exist_ok=True)
|
||||||
|
for name, fn in WALLS.items():
|
||||||
|
with open(os.path.join(OUT, name + ".svg"), "w") as f:
|
||||||
|
f.write(fn())
|
||||||
|
print(os.path.join(OUT, name + ".svg"))
|
||||||