Actually render emoji in calendar event titles; stack duplicate shared events
Build and push server image / build-and-push (push) Successful in 53s

The earlier fix stripped emoji instead of rendering them, which wasn't
what was asked for. Event titles now draw with two fonts: the usual
default font for text, and a vendored monochrome emoji font (Noto
Emoji, OFL-1.1) for actual emoji runs, so they show up as real glyphs
instead of a tofu box or nothing at all. Monochrome rather than color,
since reliably rendering COLR/CBDT color glyphs depends on how Pillow's
FreeType was built -- not something to depend on across deployments.

Also: events sharing the exact same title and time across different
calendars (e.g. a shared family event synced onto more than one
person's calendar) now collapse into one row instead of showing twice,
with a color bar split between every contributing calendar so it's
still clear whose event it is.
This commit is contained in:
2026-07-22 23:13:34 -04:00
parent 7fc262f9c3
commit 67d99dd6c0
5 changed files with 276 additions and 49 deletions
+14
View File
@@ -224,6 +224,20 @@ Pages: `/` (routing hub), `/setup`, `/login`, `/claim`, `/settings`,
explicit, informed call by the project owner, not a default -- anyone
redistributing this project (vs. just self-hosting it) should
re-evaluate that tradeoff for their own situation before doing so.
- Calendar event titles can contain emoji, which `ImageFont.load_default()`
(used for every other bit of text this project renders) has no glyphs
for -- PIL/FreeType substitute a visible ".notdef" tofu box rather than
skipping the codepoint. `app/calendar_render.py` draws emoji runs with
a vendored monochrome font instead (`app/fonts/NotoEmoji.ttf`, Google's
Noto Emoji, OFL-1.1 -- license text alongside it at
`app/fonts/NotoEmoji-OFL.txt`), the one deliberate exception to this
project's usual "no new font/icon assets" default elsewhere in
calendar_render.py -- there's no way to hand-draw arbitrary emoji with
primitives the way the weather icons are. Monochrome rather than a
color emoji font on purpose: reliably rendering COLR/CBDT color glyphs
depends on how Pillow's FreeType was built, which isn't something this
project controls in every deployment environment, and solid black
reads cleanly against everything else this module draws in black.
- The 6-color palette RGB values in `app/image_pipeline.py`
(`DEFAULT_PALETTE_RGB`) are approximations, not measured values
(Waveshare doesn't publish exact color primaries for this panel).