/** * ChartEx renderer — serialises a ChartExModel to `cx:chart` XML. * * This is a standalone renderer (not a full SAX parser): it produces byte * output for a programmatically-built chartEx. Round-trip of existing cx:chart * files is handled by raw byte passthrough (model.rawXml is preferred when set). */ import type { ChartExModel } from "./chart-ex-types.js"; import { type ChartPdfDrawingSurface, type ChartRenderOptions, type RegionMapDataOptions } from "./chart-renderer.js"; import { type ChartRect } from "./chart-utils.js"; /** * Local alias kept for file-level readability. ChartEx code has always * called these `SvgRect`; the underlying shape matches the shared * {@link ChartRect} exactly. */ type SvgRect = ChartRect; /** * Rewrite a freshly-built ChartEx model's data references to use * `_xlchart.vN.M` hidden defined-name indirection, matching the * exact scheme Microsoft Excel emits. * * Excel 2016+ REQUIRES chartEx `` elements to point at * hidden defined names, NOT directly at worksheet ranges. A * chartEx with a bare `Sheet1!$A$1:$A$3` is rejected * on load with: * * "Removed Part: /xl/drawings/drawingN.xml (Drawing shape)" * * The canonical layout Excel uses: * * chartEx1.xml: * _xlchart.v1.0 * _xlchart.v1.1 * * workbook.xml: * * * * This function walks the chart's data entries, allocates a * sequential minor index `M` for every worksheet-range formula, * registers a hidden defined name via the supplied callback, and * rewrites the `formula` field on the model to point at the * name. It also clears any cached `` point levels on * those dimensions — Excel's output uses defined-name pointers * exclusively; the cached-point form is what our earlier writer * emitted to work around the (buggy) direct-reference path and is * no longer needed. * * Non-worksheet formulas (lambda expressions, literal data, * already-indirect `_xlchart.*` names from round-tripped files) * are left untouched — only `SheetName!...` style references need * the rewrite. * * @param model ChartEx model to mutate in place. * @param chartExIndex 1-based chartEx file index — becomes the * `vN` major version in `_xlchart.vN.M`. * @param register Callback invoked for each newly allocated * defined name. Implementations should add * the name to the workbook's `definedNames` * list with `hidden="1"`. */ export declare function rewriteChartExDataRefsToDefinedNames(model: ChartExModel, chartExIndex: number, register: (definedName: string, ref: string) => void): void; /** * Render a ChartExModel to the full XML string representation of cx:chart. * * By default the function prefers the raw XML captured at parse time * (`model.rawXml`) when present — that path gives byte-perfect * round-trip for files that haven't been mutated since load. This is * the fastest and safest mode for the common "load → save" pipeline. * * Pass `{ forceStructural: true }` when the caller has mutated * structured fields on the model (e.g. via `setSpPrFill` / * `setSpPrLine` / direct assignment) and needs the writer to * rebuild from the model tree instead of reusing the stale raw bytes. * The `Chart.mutateChartEx` API already clears `model.rawXml` for * normal mutations; `forceStructural` is the escape hatch for callers * that bypass that helper (e.g. low-level tests, ad-hoc scripts). */ export declare function renderChartEx(model: ChartExModel, options?: { forceStructural?: boolean; }): string; export declare function renderChartExSvg(model: ChartExModel, options?: ChartRenderOptions): string; export declare function renderChartExPng(model: ChartExModel, options?: ChartRenderOptions): Promise; /** * Layout IDs whose PDF geometry is expressed in `drawRect` / * `drawPath` primitives rather than SVG-specific filters or raster * fallbacks. {@link drawChartExPdf} consults this set to decide * whether a vector path is available; any layout not listed falls * back to the raster pipeline in `chartToPdf`. * * As of the regionMap port this set covers every ChartEx layout the * library currently emits, so vector is the default and raster is * only reached when the caller passes `chartToPdf(chart, { * forceRaster: true })`. * * Exported so the `@pdf/excel-bridge` `chartToPdf` helper can make * the same decision without reimplementing it. */ export declare const VECTOR_PDF_CHART_EX_LAYOUT_IDS: readonly string[]; /** * True when every series of a ChartEx model has a layoutId that * `drawChartExPdf` can render as vector PDF. Used by `chartToPdf` to * route the chart to the vector or raster path automatically. */ export declare function canRenderChartExAsVectorPdf(model: ChartExModel): boolean; /** * Draw a ChartEx chart as vector content onto a * {@link ChartPdfDrawingSurface}. All layout IDs listed in * {@link VECTOR_PDF_CHART_EX_LAYOUT_IDS} are supported — the * surrounding geometry lives in the "collect" functions shared with * the SVG renderer, so the SVG and PDF paths stay equivalent by * construction. * * For any layout ID not in the set the function throws; callers * (notably `@pdf/excel-bridge.chartToPdf`) must pre-filter via * {@link canRenderChartExAsVectorPdf}. Filtering ahead of time rather * than silently skipping preserves "fail loud on unsupported" — a * silent no-op would produce an empty page and hide the mistake. */ export declare function drawChartExPdf(surface: ChartPdfDrawingSurface, model: ChartExModel, rect: { x: number; y: number; width: number; height: number; }, options?: { title?: string; regionMap?: RegionMapDataOptions; }): ChartPdfDrawingSurface; interface HierarchyNode { name: string; value: number; children: HierarchyNode[]; } /** * Treemap geometry collector. Shared between the SVG emitter (which * prints `` elements) and the PDF emitter (which calls * `surface.drawRect` / `surface.drawText`). Returning plain data — * rect, colour, optional label — keeps both backends honest: any * future visual regression in the geometry shows up on the test that * exercises the primary (SVG) backend, not only on the secondary * (PDF) one. * * The label threshold (> 40 × 18 pixels) mirrors the historical SVG * code; both backends honour it identically so small treemap cells * degrade to colour-only the same way everywhere. */ export interface TreemapCell { rect: SvgRect; color: string; label: string | undefined; } export declare function collectTreemapCells(root: HierarchyNode, plot: SvgRect): TreemapCell[]; /** * Sunburst geometry collector. Recursively walks the hierarchy, * emitting one {@link SunburstSlice} per non-root node in the same * angular/ring order the SVG renderer has always used, so the two * backends stay pixel-equivalent modulo rasterisation. * * Colour handling follows the original `renderSunburstNode` * "increment on every visit" rule so sibling slices and their * descendants walk through `COLORS` in the same sequence regardless of * which backend is driving. */ export interface SunburstSlice { cx: number; cy: number; /** Outer ring radius, always >= `inner`. */ outer: number; /** Inner ring radius; 0 for the innermost ring. */ inner: number; /** Start angle in radians, 0 = +X axis. */ start: number; /** End angle in radians. */ end: number; color: string; } export declare function collectSunburstSlices(root: HierarchyNode, plot: SvgRect): SunburstSlice[]; /** * Serialise a `cx:legend` element to XML. Exported so the xlsx raw- * patch path (`buildRawChartExLegendXml` in `xlsx.browser.ts`) can * produce identical output to the structured writer. Previously the * raw patcher emitted a self-closing ``, dropping * `align`, `cx:legendEntry*`, `cx:spPr`, `cx:txPr`, and `cx:extLst` * on every styled-legend round-trip. */ export declare function renderChartExLegendXml(l: NonNullable): string; export {};