From Data to Pixels (The Chart Life Cycle)
A chart in Charton is a dynamic sequence of transformations. This chapter traces the "biography" of a data point—from its raw state in a Polars DataFrame to its final geometric representation on a canvas.
Phase 1: Specification (Declaring Intent)
Building a chart records intent: Chart::build(), a .mark_*() call and
.encode() populate a specification without drawing anything.
- Intent Gathering: The system records which columns are mapped to which channels (X, Y, Color, etc.).
- Definition-time Work: completing the encoding validates the specification and runs the user-requested and mark-implied statistics (density, binning, quartiles). These are cheap table operations; nothing is measured or drawn yet.
Phase 2: Statistics & Position
Before any scale is trained, the data is summarised and arranged:
- Statistics turn raw rows into the columns a geometry needs (a density curve, bin counts, quartiles). A statistic is computed per group and per facet panel: a faceted chart re-runs it on each panel's own rows, so cumulative summaries never mix panels.
- Position decides where marks that share a category sit — on top of each
other (identity) or side by side (
Dodge). It works in data space, measured in category steps, so every mark reuses one layout.
See The Layer Pipeline.
Phase 3: Training (The Arbitration)
As defined in the Layer trait, the system must perform a "Training" phase before rendering.
- Data Extraction: The
LayeredCharttriggersget_data_bounds()for every layer. - Columnar Efficiency: Thanks to the Apache Arrow integration, Charton accesses contiguous memory slices (
&[T]) for specific columns. This "Columnar" approach minimizes CPU cache misses. - Domain Resolution: The orchestrator merges these bounds into a global ScaleDomain. This is where the "mathematical truth" of the chart is established.
Phase 4: Layout Negotiation
Before a single pixel is drawn, Charton must solve a spatial puzzle: How much space is left for the data after placing the labels? As seen in layout.rs, Charton uses a Greedy Stacking Algorithm:
- First Pass (Measurement): The engine estimates the width/height of axis titles and tick labels based on font metrics.
- Constraint Calculation: It subtracts these dimensions from the total canvas size to determine the
PanelContext—the exact "Physical Rectangle" where the data marks will live. - Legend Placement: Legends are "stacked" (either vertically or horizontally) using a Flex-box style logic, further refining the available plotting area.
Phase 5: Realization (Mapping to Geometry)
Now the abstract data meets physical space. The Mapper system takes over:
- Coordinate Translation: The
CoordSystemtransforms normalized data values into physical(x, y)coordinates within the Plot Panel. - Visual Mapping: The
VisualMapperconverts normalized ratios into concrete visual properties:0.5$\rightarrow$#ff0000(Color)0.8$\rightarrow$PointShape::Diamond(Shape)0.2$\rightarrow$4.0px(Radius)
Phase 6: Rendering (The Final Output)
The final stage involves the RenderBackend. Charton iterates through the resolved geometric primitives (Circles, Paths, Rects) and translates them into the target format:
- SVG/PDF: Generates vector instructions for high-fidelity documents.
- PNG/Raster: Uses hardware-accelerated drawing for high-performance previews.
- HTML/Canvas: Renders interactive frames for web environments.
Key Takeaway: The "Single-Pass" Advantage
Because Charton resolves all scales and layouts before the drawing phase, the actual rendering is a "Single-Pass" operation. This predictable flow is what enables Charton to handle millions of points with near-zero latency, as the expensive logical "negotiations" are handled once per frame.