Files
k-frame/docs/adr/0004-domain-owned-rendering.md

1.8 KiB
Raw Blame History

0004 — Domain-owned rendering, thin DisplayPort

Status: accepted Date: 2026-06-19

Context

Adding text alignment, overflow scrolling, color markup, and theming to the client. These features require text measurement, line wrapping, scroll state management, and markup parsing. The question is whether this logic lives in the domain (client-domain crate) or in each display adapter (ESP32, desktop, terminal).

Decision

All rendering intelligence lives in client-domain. The DisplayPort trait becomes a thin pixel-pusher with three methods: draw_text_span, fill_rect, flush. The domain's render engine parses markup, wraps text, computes alignment, manages scroll offsets, and emits positioned spans. Adapters only convert Color(u8,u8,u8) to native format and draw.

Font metrics are injected into the domain at init as a FontMetrics struct (char width/height per FontSize), enabling pure-math text measurement with no hardware callbacks.

Alternatives considered

Enriched DisplayPortdraw_rich_text(spans, bounds, alignment) with each adapter handling wrapping, alignment, and markup internally. Duplicates complex logic across every adapter. Harder to test — requires hardware or mocks.

Split ownership — domain handles markup/scroll, adapter handles wrapping/alignment. Splits a single concern across layers, making behavior inconsistent across clients.

Consequences

  • All text behavior is testable without hardware — pure functions on structs.
  • New display adapters are trivial: implement three methods, provide font metrics.
  • Domain is coupled to monospace font assumption (width = char_count × char_width). Proportional fonts would require a measurement callback. Acceptable — all current targets use bitmap monospace fonts.
  • DisplayPort is a breaking change — existing adapters must be rewritten.