# Architecture `plot` is one library, `plot_core`, plus optional adapter targets. The public headers are grouped into seven directories, and the umbrella header `include/plot/plot.hpp` includes them in this order: ``` core / math → gl → data → render → plot → input ``` with the host adapters (`adapters/glfw`, `adapters/imgui`, `adapters/qt6`, `adapters/gtk4`) built on top. This page says what each layer owns and the rules the build enforces. ## What each layer owns | layer | directory | owns | |---|---|---| | `core` | `include/plot/core/`, `src/core/` | the vocabulary: `f32`/`f64`/`u32`/`usize`, `kInvalid`, `Range`, `Rect`, `Color`, `Span`, and `Status`/`ErrorCode` for fallible operations. | | `math` | `include/plot/math/`, `src/math/` | `Vec2`, `Mat3`, and `Transform` — the data↔pixel affine mapping, including the log-axis handling and its invertibility guarantee. | | `gl` | `include/plot/gl/`, `src/gl/` | a hand-written OpenGL surface: enumerator typedefs, the entry-point table `plot::gl::load()` fills, `plot::gl::caps()`, and the move-only RAII wrappers (`gl::Buffer`, `VertexArray`, `Program`, `Texture`, `Framebuffer`, `Fence`). No GL loader library is used. | | `data` | `include/plot/data/`, `src/data/` | the sample stores: the `Series` interface, `ArraySeries`, `StreamSeries`, `RingBuffer`, and the min/max LOD `MinMaxPyramid`. | | `render` | `include/plot/render/`, `src/render/` | presentation: `Style`, the `Renderer`, the text machinery (`TextBackend`, `TextAtlas`, `EmbeddedMonoFont`), and the shader/program/buffer/vertex-array primitives. | | `plot` | `include/plot/plot/`, `src/plot/` | the scene model: `Plot`, `Figure`, and the primitives they own — `Axis`, `Trace`, `Cursor`, `Region`, `Measure`, `Legend`, `Crosshair`, `Annotation`, `Grid`, `Ticks`. Pure CPU state, no GL. | | `input` | `include/plot/input/`, `src/input/` | `Controller` and the host-neutral event types (`PointerEvent`, `WheelEvent`, `KeyEvent`); turns events into gestures. | | adapters | `adapters/*/` | one per host: they own the window/context/event loop and translate their toolkit's events into `input` events. | ## The dependency rules - **`plot_core` is third-party-free.** Its `CMakeLists.txt` links only `${CMAKE_DL_LIBS}`, and the public headers under `include/plot/` include no third-party header. The one exception is the optional `plot::font_ttf` target, which compiles the vendored `third_party/stb_truetype.h` (stb_truetype v1.26, public domain) in its own object library `plot_stb_truetype`, whose include directory is `PRIVATE` — so nothing else in the build, and no consumer, can reach it by accident. `PLOT_BUILD_TTF_FONT` defaults to on exactly when the vendored header is present. - **Every public header compiles standalone, and `plot.hpp` includes every one of them.** `tests/CMakeLists.txt` generates one translation unit per header (globbed, so a new header is picked up automatically), builds an umbrella TU, and registers ctest cases (`plot_headers_self_contained`, `plot_umbrella_covers_public_headers`, `plot_umbrella_check`) that fail the build if either rule breaks. - **The umbrella stops at the library.** It never includes an adapter header, so `#include ` cannot drag in GLFW, ImGui, Qt or GTK. The adapter headers are reached as ``, ``, `` and ``. - **The renderer never owns the context or the event loop.** `Renderer` never creates, binds or resizes a framebuffer: `begin_frame(fb_w, fb_h, viewport_px)` draws into whatever framebuffer is bound, clears exactly the given rectangle (scissored, so a host that painted the rest of its surface keeps it), and `end_frame()` turns the GL state it moved back off. The renderer also never sees a pointer, a button or a modifier — it draws the handles the plot reports as hot, and only a host that drives the plot with an `input::Controller` ever makes anything hot. Owning the window, the context and the loop is the adapter's job (or, for a library user, the application's). One direction is worth stating precisely, because it is the one place the layer order is not a strict include chain: `Renderer` (in `render/`) includes `plot/plot.hpp` and `plot/figure.hpp`, because drawing *is* being handed a `Plot` or a `Figure` to draw. The `plot` layer names only `render`'s value types — `render::Style` and `render::TextBackend` — and never names `Renderer`. So the runtime direction is "the renderer knows the plot, the plot does not know the renderer". ## The design record The specifications and implementation plans — the requirements, the numbered spec sections this documentation sometimes refers to, and the reasoning behind decisions — live under [`docs/superpowers/`](superpowers/) (`specs/` and `plans/`). That tree is the project's design record, not user documentation: it is where a decision is argued, not where the library is explained. This `docs/` guide and [docs/coverage.md](coverage.md) are the user-facing documents.