import { Chart, ChartSeries, ShapeDash } from '../document-model/index.js'; /** * An axis-aligned rectangle in the scene's local y-up frame: bars, scatter * point markers, legend swatches. Position is the bottom-left corner. */ export interface ChartRect { readonly x: number; readonly y: number; readonly w: number; readonly h: number; readonly fillHex?: string; readonly strokeHex?: string; readonly strokeWidthPt?: number; /** §20.1.10.49 — the outline's preset dash, when it names one. */ readonly strokeDash?: ShapeDash; } /** An open stroked polyline: line-chart series, gridlines and axis lines. */ export interface ChartPolyline { readonly points: ReadonlyArray; readonly strokeHex: string; readonly widthPt: number; } /** A closed, filled polygon (area-chart bands). Drawn before strokes/labels. */ export interface ChartPolygon { readonly points: ReadonlyArray; readonly fillHex: string; readonly strokeHex?: string; readonly widthPt?: number; } /** * A circular sector (pie/doughnut slice), centred at `(cx, cy)` with radius `r`. * `startRad`/`sweepRad` are radians in the y-up frame; sweeps are negative for * Excel's clockwise winding. The doughnut hole is a white wedge drawn last. */ export interface ChartWedge { readonly cx: number; readonly cy: number; readonly r: number; readonly startRad: number; readonly sweepRad: number; readonly fillHex: string; readonly strokeHex?: string; } /** How a {@link ChartLabel} sits horizontally relative to its anchor point. */ export type LabelAlign = 'left' | 'center' | 'right'; /** A text label (title, axis tick, category, data value, legend entry). */ export interface ChartLabel { readonly text: string; /** Anchor point; `align` says how text sits relative to it. */ readonly x: number; /** Text baseline. */ readonly y: number; readonly sizePt: number; readonly colorHex: string; readonly align: LabelAlign; /** * §21.2.2.216 `c:title/c:txPr/a:bodyPr@rot` — a value-axis title reads * bottom-to-top (`rot="-5400000"`, the default every reader applies). Degrees * counter-clockwise about the anchor; `align` then runs along the ROTATED * reading direction. */ readonly rotationDeg?: number; } /** * The fully laid-out chart: rectangles, polylines, wedges and labels (plus * optional filled polygons) in a local y-up frame, origin bottom-left. The * renderer maps these to draw commands — rects/polylines/wedges/polygons via the * vector layer, labels via the text pass. */ export interface ChartScene { readonly rects: ReadonlyArray; readonly polylines: ReadonlyArray; readonly wedges: ReadonlyArray; readonly labels: ReadonlyArray; readonly polygons?: ReadonlyArray; /** §21.2.2.198 chart-space fill + outline: drawn under everything else. */ readonly background?: ChartRect; /** * §21.2.2.145 the PLOT rectangle's own fill + outline, drawn over the chart * frame and under the gridlines. */ readonly plotBackground?: ChartRect; /** * Major gridlines, drawn UNDER the plotted data. Kept apart from the other * polylines because z-order is the whole point: gridlines over the bars strip * every one of them with the axis's own ruling, which is not what any * spreadsheet draws. */ readonly gridlines?: ReadonlyArray; } /** * Injected text-width measurer: the rendered advance width (points) of `text` at * `sizePt`. Keeps this module free of any font/PDF dependency, so it is * unit-testable in isolation. */ export type MeasureText = (text: string, sizePt: number) => number; /** Font size (points) for axis ticks, category/data labels and legend text. */ export declare const CHART_LABEL_PT = 9; /** Font size (points) for the chart title. */ export declare const CHART_TITLE_PT = 13; /** The Office accent cycle (RRGGBB) for series without an explicit colour. */ export declare const SERIES_COLORS: string[]; /** * Resolve a series colour: the series' own `colorHex` if set, else cycling * through `cycle` (the chart's theme accent cycle) or, failing that, * {@link SERIES_COLORS} by index. * * @param s The series. * @param i The series index, used to pick from the cycle. * @param cycle Optional per-chart colour cycle; falls back to {@link SERIES_COLORS}. * @returns An RRGGBB hex string. */ export declare const seriesColor: (s: ChartSeries, i: number, cycle?: ReadonlyArray) => string; /** A value-axis scale: the rounded `min`/`max` extent and the tick `step`. */ export interface Scale { readonly min: number; readonly max: number; readonly step: number; } /** * Compute a human-friendly axis {@link Scale} for the data range using * Heckbert's "nice numbers" algorithm: rounded endpoints and a 1/2/5·10ⁿ step * that yields about `maxTicks` ticks. A degenerate range (`dataMin === dataMax`) * is widened by 1 so the axis is non-empty. * * @param dataMin The smallest data value to cover. * @param dataMax The largest data value to cover. * @param maxTicks Target upper bound on tick count (default 6). * @returns The rounded min/max and tick step. */ export declare function niceScale(dataMin: number, dataMax: number, maxTicks?: number): Scale; /** * Format an axis tick value, choosing decimal places from the tick `step` so * `0.25`-spaced ticks read `0.25` while integer steps drop the fraction. * * @param v The tick value. * @param step The tick spacing (from {@link niceScale}). * @returns The label text. */ export declare function formatTick(v: number, step: number): string; export declare function buildBarScene(chart: Chart, wPt: number, hPt: number, measure: MeasureText): ChartScene; /** * The name a series shows in the legend: its own `c:tx`, or Excel's positional * `SeriesN` when it has none. Exported because the SUBSET has to know it too — * a name invented at draw time is a name no glyph collector ever saw, and * 57362.xlsx drew its unnamed series as "eries1", the capital S appearing * nowhere else on the page and so nowhere in the font. * * @param series The series. * @param index Its zero-based index in the chart. * @returns The legend text. */ export declare function legendSeriesName(series: ChartSeries, index: number): string; /** * Lay out an area {@link Chart} into a {@link ChartScene}: each series becomes a * filled polygon down to the value baseline (stacked when `chart.grouping` is * stacked / percentStacked), over the shared cartesian frame. * * @param chart The area chart. * @param wPt Frame width in points. * @param hPt Frame height in points. * @param measure Text measurer used to size labels and reserve axis gutters. * @returns The positioned scene primitives. */ export declare function buildAreaScene(chart: Chart, wPt: number, hPt: number, measure: MeasureText): ChartScene; /** * Lay out a scatter {@link Chart} into a {@link ChartScene}: numeric X/Y series * plotted as marker points over a frame with two value axes (X from each * series' `xValues`, Y from its `values`). * * @param chart The scatter chart. * @param wPt Frame width in points. * @param hPt Frame height in points. * @param measure Text measurer used to size labels and reserve axis gutters. * @returns The positioned scene primitives. */ export declare function buildScatterScene(chart: Chart, wPt: number, hPt: number, measure: MeasureText): ChartScene; /** * Lay out a line {@link Chart} into a {@link ChartScene}: each series becomes a * stroked polyline across the category slots, over the shared cartesian frame. * Unlike bars/areas the value axis auto-mins (it need not include 0). * * @param chart The line chart. * @param wPt Frame width in points. * @param hPt Frame height in points. * @param measure Text measurer used to size labels and reserve axis gutters. * @returns The positioned scene primitives. */ export declare function buildLineScene(chart: Chart, wPt: number, hPt: number, measure: MeasureText): ChartScene; /** * Lay out a pie/doughnut {@link Chart} into a {@link ChartScene}: the first * series' values become proportional wedges (a centre hole for doughnut), * with a legend instead of axes. * * @param chart The pie/doughnut chart. * @param wPt Frame width in points. * @param hPt Frame height in points. * @param measure Text measurer used to size labels and the legend. * @returns The positioned scene primitives. */ export declare function buildPieScene(chart: Chart, wPt: number, hPt: number, measure: MeasureText): ChartScene; /** * Lay out any supported {@link Chart} into a {@link ChartScene}, dispatching by * `chart.type` to the per-type builders. * * @param chart The chart to lay out. * @param wPt Frame width in points. * @param hPt Frame height in points. * @param measure Text measurer used to size labels and reserve gutters. * @returns The positioned scene, or `null` for an unrenderable type (the * renderer then reserves the box with a light border). */ export declare function buildChartScene(chart: Chart, wPt: number, hPt: number, measure: MeasureText): ChartScene | null;