SchOS/docs/branding/README.md
Nexoniarz 953f9c5c3c branding: one mark, and PSOGM draws it
Guru and SchCotie are gone. Shift is the only mark, and the crash screen draws
it where the face used to be.

Guru was an icon -- a pictogram with a face, denoting one state -- that lived
on the crash screen and nowhere else. Its argument was identity: `:(` is
recognisably Microsoft's, and a crash screen is the single screenshot most
likely to leave the machine, so it is the worst place to be wearing somebody
else's face. That part holds, and it is kept in the branding README because it
is the argument against any second mark. What does not follow is that the
answer is a *new* mark. Shift already signs the system, it is already what the
machine drew on the splash it started with, and a reader who has seen it twice
before the crash recognises it faster than a face they have never seen.

SchCotie was a mascot, and never existed: the file said so itself under "what
this does not cover". A brief for a character nobody is about to draw is not
worth carrying.

So `draw_guru()` and its SVG-space geometry leave panic.c, the two `guru.svg`
files are deleted, and PSOGM calls gfx_draw_logo() -- the same include/logo.h
mask the loader splash and the boot console composite. At its native 128 px:
there is no resampler in the crash path, and the face was scalable in a place
that only ever drew it at one size.

The name stays. "Purple Screen of Guru Meditation" is the Amiga nod, which
panic.c's own header already called out as a separate thing from the mark.

**And taking the screenshot to check it caught a regression from the TTF
console work.** `gfx_draw_char()` -- the pixel-positioned path, which only
PSOGM uses -- still walked `font_data[c][row]` for `row < CHAR_HEIGHT`.
font_data has exactly 16 rows per glyph; CHAR_HEIGHT is the *TrueType* cell
height now, about 21. So every line of the crash report drew five rows of the
next character's bitmap underneath itself, and it looked like each line had
been printed twice. The grid path had been updated when the cell size stopped
being a constant; this one had not, because nothing routine draws text in pixel
coordinates. Both go through one draw_glyph_px() now, and the bitmap's own
geometry is spelled BITMAP_W/BITMAP_H so it cannot be mistaken for a cell size
again.

Two stale claims corrected while in there, in panic.c's header and in
graphics.md: PSOGM has not dimmed-and-floated over the old screen for a while
-- it clears to full purple, and the file's own code comment says why -- and
there is no longer "a face that is obviously a cartoon".

The website's crash section shows the mark in flat white rather than its own
violets, which is what the kernel actually draws: PSOGM composites a coverage
mask in one colour, and those violets sit close enough to #4B1D9A to
half-disappear against it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 21:35:58 +02:00

181 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Branding
One mark.
| | | |
|---|---|---|
| **Shift** | *the logo* | An abstract mark. Non-human, non-animal. Signs the system. |
There were three. **Guru**, an icon — a pictogram with a face, denoting one
state — lived on the crash screen and nowhere else. **SchCotie**, a mascot —
a character with a body, poses and expressions — was a brief and was never
drawn. Both are gone for now, and may come back.
The reasoning that retired Guru is worth keeping, because it is the argument
against any second mark. Guru existed to give the crash screen an identity:
`:(` is recognisably Microsoft's, and a crash screen is the single screenshot
most likely to leave the machine, so it is the worst place to be wearing
somebody else's face. That part holds. What does not follow is that the answer
is a *new* mark. Shift already signs the system, it is already what the machine
drew on the splash it started with, and a reader who has seen it twice before
the crash recognises it faster than a face they have never seen.
SchCotie went for a simpler reason: **a mascot has to be able to do things.**
An icon works once, at one size, in one state. A character has to work
confused, pleased, asleep and from behind — which is why it costs more, and why
a brief for one is not worth carrying until somebody is going to draw it.
---
## The one constraint everything answers to
**The kernel draws its mark as a 128×128 single-channel coverage mask.**
`include/logo.h` holds no colour at all — two pixels per byte, sixteen levels of
ink — and the kernel composites it in whatever `include/theme.h` says.
So any mark that will end up there has to survive as **a solid shape in one
colour at 128 px, and be recognisable at 24**. That rules out hairlines, thin
rings and anything that depends on a gradient to read. The mark this replaced
failed on all three counts.
Colour is therefore the *last* decision, never the first. Design the silhouette,
then colour it.
---
## Shift — the logo
`shift.svg`
Three slabs, displaced: the layer diagram in
[../architecture/README.md](../architecture/README.md) as a solid object, and
the kernel's name (**SchIFT**) as a shape.
- **Any colour.** This is a fact about the pipeline, not a preference — the
coverage mask carries none, so the loader draws it in metal and the kernel in
the theme accent, from the same bytes.
- **With or without a wordmark.** Set "SchOS" beside it in **Roboto Bold**,
which is already in the tree (`ports/Roboto`), already Apache-2.0, and already
in `NOTICE`.
- Non-human and non-animal, permanently. If a character is ever drawn it gets
its own mark; a logo that starts growing a face has taken that job.
---
## Colour
From `include/theme.h`, which is the source of truth. Nothing here restates a
value it does not already define.
| | | |
|---|---|---|
| `SCH_BG` | `#0C0E13` | Ground. Near-black with a blue cast, because pure black reads as "switched off". |
| `SCH_FG` | `#E6E8EC` | Primary text |
| `SCH_DIM` | `#707784` | Secondary |
| `SCH_ACCENT` | `#7C5CFF` | The one accent. Shift, and anything calm. |
| `PSOGM_BG` | `#4B1D9A` | **Failure only.** The crash screen's ground and nothing else's. |
`PSOGM_BG` is deliberately **not** the accent. `theme.h` states the rule it
enforces:
> normal states are calm and dark; only failure is loud. PSOGM keeps the
> full-bleed purple entirely to itself, which is what makes it mean something.
If that purple ever appears on a splash, a sticker or a README header, it stops
meaning *the machine stopped* — and it is the only colour in the system that
means anything at all.
## File formats
**SVG, or PNG at high resolution with no lossy compression.** Nothing else.
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.
No screenshots of marks. No re-exports of re-exports: go back to the SVG.
**SVG is the source of truth for every mark.** A raster is something generated
from it, never edited.
## The mark as characters
`Ascii/ascii_{50,68,100,150}.txt` — Shift rendered in text at four widths, named
for the column count they fit in.
`make` installs the 50-column one as `/usr/share/schos/logo.txt`, because 50 is
what leaves room for an info block beside it on an 80-column console:
```sh
fastfetch --file-raw /usr/share/schos/logo.txt
```
Installed from here rather than copied into `sysroot/` by hand, so there is one
source and the build keeps them in step.
These are a *rendering* of the mark, not a second mark. If Shift changes they
are regenerated from it; they are not edited to taste, or the two drift and the
text one wins by being the one people see in a terminal.
## What is in here, and why a raster is committed
```
shift.svg the logo, in colour
shift-mask.svg the same geometry in greys -- see below
shift-mask.png rasterised from it, committed on purpose
uberblock.svg SchFS
superseded-*.png the old wordmark, kept for reference only
```
The pipeline is three stages:
```
shift-mask.svg --(inkscape)--> shift-mask.png --(make logo)--> include/logo.h
```
**Both intermediates are committed, and that is deliberate.** `inkscape` is not
a build prerequisite — see [../guides/building.md](../guides/building.md) — so a
build that required a vector rasteriser would stop working on most hosts for the
sake of a file that changes about once a year. The PNG is regenerated by hand
when the SVG changes, and `make logo` turns it into the header.
### Why the mask is a separate file from the logo
`tools/python/mklogo.py` reads ink as `(255 - luminance) * alpha`, so **tones
survive as coverage** rather than being flattened — and the relationship
inverts: *darkest here is brightest on screen*. Copying the violet fills from
`shift.svg` would light the object from below.
So `shift-mask.svg` is the same geometry in greys chosen for how the mask reads.
Two files sharing one geometry is a drift hazard; the `<desc>` in both says so.
If either is edited, edit both.
---
## Where each mark is actually drawn
| | |
|---|---|
| Loader splash | Shift, from `include/logo.h`, shaded per row by `metal()` in `boot/common/ui.c` — silver, not accent. |
| Kernel console / early boot | Shift, same mask, composited flat in a theme colour by `gfx_draw_logo`. |
| PSOGM | Shift, the same mask again, by `gfx_draw_logo()` from `kernel/core/panic.c`. At its native 128 px — there is no resampler in the crash path, and the mark was only ever drawn at one size there anyway. |
| Serial crash report | `:(`, as text. The mark cannot be drawn in ASCII, and a mood marker in a log is not a mark. |
| SchFS | **Nowhere yet.** `uberblock.svg` has no consumer; it is waiting for `projects/schfs-linux/` to have a README worth heading. |
One trap, since it has already been stepped in: `boot/common/ui.c` includes
`logo.h`, `theme.h` and `font.h`, and the Makefile rule for the loader did not
list them. A new logo therefore did not rebuild the loader — `make` reported
nothing to do and the splash kept drawing a mask compiled months earlier. The
kernel half never showed the problem because those objects are built with
`-MD -MP` and track their own headers. **Changing anything in here means the
loader must actually relink**, and that needs `clang` and `lld-link`.
## What this does not cover
- **No trademark position.** These are marks the project uses, not marks anyone
has registered or defended.
- **No usage rules for third parties** — nothing says what someone else may do
with them. Worth writing before anything is published.
- **There is no icon and no mascot.** Both were removed rather than left
half-specified. If either comes back it starts from the argument at the top
of this file, not from what used to be here.
- **No wordmark lockup is specified.** "Roboto Bold beside it" is not a spacing
rule, a size ratio or a clear-space margin, and it will want to be.