Commit Graph
44 Commits
Author SHA1 Message Date
Dylan M. TaylorandClaude Opus 5.5 fc1f475e50 fix: restore compile and behaviour in Sonar refactors
- fonts: char::is_alphanumeric takes &self, so filter needs a closure
- h264: keep the mvd accumulator as i32 (prefix is usize)
- model: annotate the non-stacked range accumulators as f64
- engine: chart.options still clears the raw chart XML for upDownBars
  and quartiles; smartart goes back to the glob import (cmd! macro)
- web: keep the original viewport meta (behaviour change)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 02:35:02 +00:00
Dylan M. Taylor 3ef6433309 style: apply rustfmt formatting 2026-10-24 02:23:12 +00:00
Dylan M. Taylor f665887094 chore: resolve SonarCloud maintainability issues 2026-10-24 02:18:38 +00:00
NetterSilverandClaude Haiku 5.5 e843309280 Fix extra empty histogram bin with a fixed bin count
Found while testing crates/model/src/chart.rs:1129-1135 (histogram_bins)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 08:28:08 +00:00
Mexandskylar taylor-barrick f34f4121c8 Format: retain imported chart parts through native saves (#851)
* M2.1: preserve chart parts through native saves

Serialize retained chart relationships and payloads in native files.
Add native and headless file-command round-trip regressions.

Contribution on behalf of @MMexicann.

* Format: bound opaque chart parts as native ZIP entries

Address maintainer feedback on the existing PR. Preserve upstream work and document tested scope and validation limits.

* Model: track transient native chart part entries

Address maintainer feedback on the existing PR. Preserve upstream work and document tested scope and validation limits.

* PPTX: initialize native chart entry metadata

Address maintainer feedback on the existing PR. Preserve upstream work and document tested scope and validation limits.

* Engine: adapt chart native roundtrip fixtures

Address maintainer feedback on the existing PR. Preserve upstream work and document tested scope and validation limits.

* Docs: describe bounded chart sidecars and validation

Address maintainer feedback on the existing PR. Preserve upstream work and document tested scope and validation limits.

* Roadmap: record bounded chart persistence evidence

Address maintainer feedback on the existing PR. Preserve upstream work and document tested scope and validation limits.

---------

Co-authored-by: skylar taylor-barrick <hi@skylar.cc>
2026-10-19 11:44:16 -06:00
Brandon ThomasandClaude Opus 5.5 f403c65c94 Fix up #355: kept chart parts get fresh names; chartex keeps its workbook
A chart's kept parts were written under the names the source file gave them,
so a relationship to ppt/media/image1.png (or any name the writer generates)
produced a second zip entry with that name on save. Kept parts are now written
as ppt/<folder>/keptN.<ext> with a content-type override each, the chart's and
the kept parts' own relationships are rewritten to the new names (relationships
to parts that were not kept are dropped), and the package writer skips any
second entry under a name it already wrote. externalData/userShapes are dropped
only when their relationship is not written back.

Office 2016 chartex charts (added on main since the PR) capture and write back
their kept parts the same way; the plain-chart fallback carries none.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 15:30:16 -04:00
Brandon Thomas b6a4343ec5 Merge PR #355 from NikitkaRa: Charts: keep the embedded workbook when a chart is saved unchanged (#335)
# Conflicts:
#	contributors/people.toml
#	crates/pptx/src/opc.rs
#	crates/pptx/src/read/chart.rs
#	crates/pptx/src/read/shapes.rs
#	crates/pptx/src/write/chart.rs
2026-10-14 15:23:07 -04:00
Brandon ThomasandClaude Opus 5.5 621efd0290 Merge PR #673 from NikitkaRa: Charts: error bars
Fix-ups in the merge: error-bar statistics are computed once per series (was once per point,
quadratic on long series); reading custom amounts uses the chart-wide point budget (#480).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 15:14:06 -04:00
Brandon Thomas 6d1b01b73d Merge PR #669 from NikitkaRa: Charts: logarithmic value axes
# Conflicts:
#	crates/pptx/src/read/chart.rs
#	crates/render/src/chart.rs
2026-10-14 13:51:30 -04:00
Brandon Thomas 808087e6a5 Merge PR #666 from NikitkaRa: Charts: value-axis minor gridlines
# Conflicts:
#	crates/pptx/src/read/chart.rs
2026-10-14 13:50:53 -04:00
Brandon Thomas 266da52dd9 Merge PR #640 from NikitkaRa: Charts: category axis orientation; horizontal bars list the first category at the bottom
# Conflicts:
#	crates/pptx/src/read/mod.rs
#	crates/pptx/src/write/chart.rs
#	crates/render/src/chart.rs
2026-10-14 13:48:09 -04:00
Brandon Thomas 8f0640a7b2 Merge PR #603 from NikitkaRa: Render: draw chart trendlines
# Conflicts:
#	crates/render/src/chart.rs
2026-10-14 13:47:08 -04:00
Brandon Thomas b0345cfaf2 Merge PR #602 from NikitkaRa: Charts: polar radar, stock high-low lines and up/down bars, combo sample 2026-10-14 13:42:48 -04:00
Brandon Thomas 82ea49bcf1 Merge PR #598 from NikitkaRa: Charts: keep and draw region map charts 2026-10-14 13:42:45 -04:00
Brandon Thomas 7c46b5b76a Merge PR #594 from NikitkaRa: Charts: multi-level treemaps and sunbursts; inclusive box quartiles 2026-10-14 13:42:41 -04:00
Brandon Thomas 6057715c2a Merge PR #591 from NikitkaRa: Charts: histograms, Pareto and box and whisker; Office 2016 charts save as themselves
# Conflicts:
#	crates/render/src/chart.rs
#	crates/ui-egui/src/ribbon.rs
2026-10-14 13:42:41 -04:00
Brandon ThomasandClaude Opus 5.5 b5499d7157 Fix up merged PRs: waterfall axis scale uses the running totals
main's axis_scale now reads plotted_extent rather than value_range, which #537
taught about waterfalls; route waterfall charts to value_range there too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 13:41:50 -04:00
Brandon Thomas 9479e3b17c Merge PR #537 from NikitkaRa: Charts: draw waterfall, funnel, treemap and sunburst layouts
# Conflicts:
#	crates/model/src/chart.rs
#	crates/render/src/tests.rs
2026-10-14 13:38:34 -04:00
Brandon Thomas f0d0e2a93b Merge PR #659 from NikitkaRa: Charts: percent axes for 100% stacked; source-linked axis number formats 2026-10-14 13:09:05 -04:00
Brandon Thomas 0bab72aff2 Merge PR #590 from NikitkaRa: PPTX: round-trip chart trendlines 2026-10-14 13:08:57 -04:00
Brandon Thomas bce94027ad Merge PR #486 from NikitkaRa: Charts: pie and doughnut data labels use the number format (#324) 2026-10-14 13:08:45 -04:00
Brandon Thomas 9fab337cd2 Merge PR #157 from LloydNicholson: Charts: value axes start above zero when the values sit high, as in Office 2026-10-14 12:57:19 -04:00
Nikita Rakitin 5398c2397c Merge remote-tracking branch 'origin/main' into m-pptx-chart-workbook
# Conflicts:
#	ROADMAP.md
#	crates/pptx/src/read/chart.rs
#	docs/gaps.md
2026-10-14 05:20:31 +03:00
Nikita Rakitin 3ea696dc1a Charts: read, write and draw error bars 2026-10-14 04:48:33 +03:00
Nikita Rakitin 4a7ad03eb0 Charts: logarithmic value axes 2026-10-14 04:45:26 +03:00
Nikita Rakitin aed386e269 Charts: draw, read and write value-axis minor gridlines 2026-10-14 04:39:00 +03:00
Nikita Rakitin 3960ea47cd Charts: 100 % stacked axes count in percent; linked axis formats come from the data 2026-10-14 04:19:16 +03:00
Nikita Rakitin 71b02327cf Charts: category axis orientation (maxMin) read, written and drawn; horizontal bars run bottom-up 2026-10-14 03:16:35 +03:00
Nikita RakitinandCursor c176d42bb4 Charts: polar radar, stock high-low lines and up/down bars, combo sample
Radar and filled radar charts are drawn polar: spokes per category,
polygon gridlines and value labels up the first spoke. Stock charts
draw high-low lines with close dashes, or up/down bars between open
and close, and are saved as c:stockChart (hiLowLines, upDownBars)
instead of a line chart; c:upDownBars is read, and chart.options takes
upDownBars. New stock charts start as high-low-close and new combo
charts as columns with a line.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 01:31:40 +03:00
Nikita Rakitin 768641615a Render: draw chart trendlines
Fit linear, exponential, logarithmic, polynomial, power and moving-average
lines, including forecast, and draw them with the equation and R² label.
2026-10-14 01:29:51 +03:00
Nikita RakitinandCursor 210df9a3d1 Charts: keep and draw region map charts
Read the regionMap chartEx layout as a RegionMap chart (regions and
their colour values), write the part back as read while unchanged, and
when edited rebuild it with the original geography (projection, culture
and cached boundaries) carried over. With no map data in the repo, the
renderer draws each region as a value-coloured tile with a colour scale
and a note that the map itself is not drawn.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 01:23:54 +03:00
Nikita RakitinandCursor b3420a0b04 Charts: multi-level treemaps and sunbursts; inclusive box quartiles
Read, keep and write every cx:lvl of a chartEx category dimension,
build a category tree from runs of parent labels, and draw treemaps as
nested squarified groups with banners and sunbursts as one ring per
level. Box & whisker honours quartileMethod="inclusive" (QUARTILE.INC)
on import, render, save and the chart.options command.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 01:16:09 +03:00
Nikita RakitinandCursor 15daed6ca4 Charts: histograms, Pareto and box and whisker; Office 2016 charts save as themselves
Histograms and Paretos bin their observations (bin count, bin width or
Scott's rule) and draw as touching columns, a Pareto with its cumulative
line on a percentage axis. Box and whisker charts draw exclusive-quartile
boxes, 1.5 IQR whiskers, means and outliers per category group.

Edited and new Office 2016 charts are written as chartEx parts from the
model (with the plain-chart fallback), so a waterfall stays a waterfall.
The chart menus list all seven types, and chart.options sets bins and
waterfall totals.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 01:08:13 +03:00
Nikita Rakitin 8fd04ebd92 PPTX: round-trip chart trendlines
An owned corpus slice checks combo charts with data labels, merged
tables with diagonal borders, and text columns, autofit, vertical text
and a WordArt warp. Trendlines (type, order, period, forecast,
intercept, equation and R²) are now read and written.
2026-10-14 00:58:20 +03:00
Nikita RakitinandCursor 0d47da07e5 Charts: draw waterfall, funnel, treemap and sunburst layouts
These Office 2016 charts were drawn as plain columns. Now:
- waterfall: bars float from the running total, total points
  (cx:subtotals, now read into Chart.subtotals) stand on the axis and
  reset it, increases/decreases/totals take accents 1-3 with a matching
  legend, and connectors join each bar to the next;
- funnel: centred bars as wide as their value, category labels on the
  left and values inside;
- treemap: squarified tiles in proportion to their value, labelled;
- sunburst: the innermost level as a ring with an open centre.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 23:16:23 +03:00
Nikita RakitinandCursor 7d23e4670b Charts: pie and doughnut data labels use the number format (#324)
Pie and doughnut data labels still went through fmt_num, which rounded
anything non-integral to one decimal (999.99 drew as "1000.0"). They now
use Chart::data_label like the other label paths (series format, else
axis format, else General), and fmt_num is gone.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 21:01:43 +03:00
lloydandClaude Opus 5.5 0f069ce351 Merge upstream/main into fix/chart-auto-axis
Upstream ce1c7b7 ("Charts: axis number formats, automatic major unit,
hidden axes") replaced the value-axis scaling this branch changed, and
already draws #144's chart as 0-45 in steps of 5. Take its structure and
API as they are (axis_scale with fixed bounds/unit and a room-based
interval count, Chart::axis_scale(secondary, max_intervals), axis_range,
combo charts' secondary axis) and drop this branch's auto_scale.

On top of it, the Office rules upstream lacked:

- Automatic minimum: zero only when every value is >= 0 and the smallest
  is below 5/6 of the largest; otherwise the first major unit at or below
  min - (max - min)/20. All-negative data mirrors it (the axis ends at
  zero only when the largest is above 5/6 of the smallest). Headroom is
  5 % of the data range, as documented. Chart::axis_scale feeds it the
  plotted extremes (stacked sums still count from zero, 100 % series are
  0-1); axis_range and value_range keep returning zero-inclusive ranges.
- A fixed limit beyond the data makes the automatic end give way instead
  of producing an inverted axis.
- The renderer stops values past the axis limits at the plot edge, on
  both value axes.

The model tests from this branch are ported to the new signature with
ten intervals of room.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 10:33:37 +02:00
Brandon ThomasandClaude Opus 5.5 735e16d93c Charts: text at the sizes the file sets, as in PowerPoint (#358)
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 04:30:41 -04:00
Магда М.Г. ce1c7b7759 Charts: axis number formats, automatic major unit, hidden axes
Value axes showed raw numbers ("800000") with a fixed ~5-interval scale and
fixed label gutters, deleted axes were still drawn, and data labels ignored
their number format, so Russian business charts read "516600000" where
PowerPoint shows "516 600 000 ₽".

- New deckcraft_model::numfmt: Excel number format codes (sections for
  positive/negative/zero, quoted and escaped literals, _x padding, *x fill,
  [$sym-lcid] currency, [colour]/conditions dropped, 0/#/? placeholders,
  grouping with ',' or the locale's literal space, trailing-comma scaling,
  %, General) with digit grouping and decimal mark from the chart's
  language (c:lang: ru-RU -> "800 000", "12,5%").
- Reading: each value axis' numFmt, c:delete, scaling min/max and
  majorUnit, for the primary and a combo chart's secondary axis; data
  labels' numFmt (series, then group, else the source data's formatCode);
  the chart's c:lang. The primary value axis is the one on the left
  (bottom) and the secondary the one on the right/top or crossing at max,
  whatever the plot groups' order.
- Scale (Chart::axis_scale): fixed bounds and unit where given, else the
  data plus 5% headroom rounded out to the smallest 1-2-5 unit that leaves
  as many intervals as the axis has room for labels, as PowerPoint does
  (0-800 000 by 100 000, 0-7 000 by 1 000 on the sample deck).
- Rendering: labels in the axis format, gutters sized to the longest label,
  deleted axes draw no labels and take no room, data labels in their own
  format.
2026-10-13 04:20:52 -04:00
Магда М.Г. 5c82c08847 Charts: draw combo charts with columns, lines and a secondary axis
A combo chart (columns plus lines, often with the lines on a second value
axis) was read with each series' type but drawn as lines only, on one
scale, so a spend-and-clicks chart showed the clicks as a flat line along
the bottom and no columns.

- Reading: a plot group whose value axis isn't the first group's is on the
  secondary axis (Series::secondary_axis, now set).
- Model: Chart::series_kind, on_secondary and axis_range (per axis; a combo
  stacks only its stacked series).
- Rendering: bar-like series are drawn as bars (clustered or stacked among
  themselves), the others as lines/areas over them, each against its own
  axis; the secondary axis' labels go on the right. Line series use their
  line's colour and width (where PowerPoint keeps them), also in the legend.
  Long category labels wrap onto two lines.
2026-10-13 04:20:52 -04:00
MarekSpodBiedry b585027de2 Chart legend: honour legendPos and overlay in the renderer (#262) 2026-10-13 04:20:52 -04:00
NikitaandCursor 8788f994ef Charts: keep the embedded workbook when a chart is saved unchanged (#335)
PowerPoint stores chart data in ppt/embeddings. Saving used to drop that part and the chart relationship, so the deck still rendered but the workbook was gone. An edit still omits the workbook rather than writing numbers that no longer match it.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 10:40:59 +03:00
lloydandClaude Opus 5.5 6a91164a5b Issue #144: automatic value axes scale like Office
The value axis used a generic "nice" scale: about five intervals and no
headroom, so data with a maximum of 42.1 got 0-50 in steps of 10, while
PowerPoint and LibreOffice draw 0-45 in steps of 5.

`auto_scale` now follows the rule Office documents for automatic limits:
the maximum is the first major unit at or above max + (max - min)/20, the
minimum is zero when all values are positive and the smallest is below 5/6
of the largest (otherwise the first major unit at or below min - the same
headroom), and all-negative data mirrors that. The major unit is the
smallest 1, 2 or 5 x 10^n that gives at most 10 intervals. Fixed
`<c:min>`/`<c:max>` limits are kept as they are and no longer get rounded
or padded; values beyond them stop at the plot edge. 100% charts get
0-1 in steps of 0.1.

Fixes #144

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 17:05:17 +02:00
Brandon ThomasandClaude Opus 5.5 6078b68e97 M0: workspace, model, geometry, fonts, text, renderer, engine, MCP and CLI
Clean-room PowerPoint-class presentation engine in pure Rust:
- geom: units, transforms and 150+ re-derived preset shapes with adjust handles
- color: theme slots and colour transforms
- model: presentations, masters, 11 layouts, placeholder inheritance, themes,
  text, tables, charts, transitions, animations, text edit operations
- fonts: font DB with craft-fonts, system fonts and open substitutes
- text: shaping, line breaking, bullets/numbering, alignment, autofit, caret hit tests
- render: vello_cpu slides with fills, gradients, pictures, effects, tables, charts
- format: native .slidecraft (zip + JSON)
- engine: ~200 commands, undo/redo, clipboard, pointer tools, keys, sample deck
- mcp: MCP server (headless or bridged to the app); slidecraft-cli

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 23:27:20 -04:00