Commit Graph
182 Commits
Author SHA1 Message Date
Nikita RakitinandCursor c5a63fc8b7 SmartArt: node pictures from the data model, Brick Scene camera, four more layouts
Node pictures are written on the data model's presentation points (blip through the data part's rels) and read back into the outline on import. Picture Accent Process is hProcess10, not pList2 (checked against PowerPoint's layout list); pList2 is now Horizontal Picture List. Brick Scene looks through an isometric camera. New layouts: Horizontal Picture List, Basic Timeline, Basic Venn, Basic Target.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 02:02:42 +03:00
Nikita RakitinandCursor 6f19e0bd07 SmartArt: shrink text to fit, picture layouts, 3-D styles and more colours
Each shape's text shrinks so its longest word fits on a line (the pyramid tip no longer breaks words). Three picture layouts (Vertical Picture List, Picture Caption List, Picture Accent Process) with a picture placeholder per node and smartArt.picture to fill it. Five 3-D SmartArt Styles (Polished, Inset, Cartoon, Powder, Brick Scene) drawn with lit bevels, and Colorful Range and Gradient Range colours; all written to and read from the .pptx quickStyle and colors parts.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 01:56:36 +03:00
Nikita RakitinandCursor 1a0ffc6413 Draw: pen pressure scales ink width
A pen reading of 1 is the full pen width. A lighter touch draws a thinner
stroke, and a zero reading stays visible at 8% of the pen. A mouse, a
missing or non-finite reading, and a stroke whose samples are all the old
placeholder 0.5 still draw at the pen width. PPTX keeps one width per
stroke: the mean of the samples for a pressured stroke, the pen width for
a legacy one. Tilt is not read.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 01:56:23 +03:00
Nikita RakitinandCursor 1866de9895 SmartArt: 15 layouts, SmartArt Styles and Change Colors
Layouts now include Vertical and Horizontal Bullet List, Basic Block List,
Basic/Chevron/Vertical/Step Up Process, Basic and Block Cycle, Basic Radial,
Basic and Inverted Pyramid (bands drawn as polygons so the slope and the
text stay right), Basic and Titled Matrix, and Hierarchy. Each layout says
which nodes each shape shows, so typed text maps back for any layout.

SmartArt Styles (flat, subtle, intense, white outline) and Change Colors
(colourful or one accent) are kept on the diagram, offered in the SmartArt
Design tab, and written to .pptx as quick style / colour definition ids
(and read back from them).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 01:42:52 +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 RakitinandCursor b03b19bca7 SmartArt: write the outline to .pptx as a diagram; read it back from the data model
Export: a group with a diagram becomes a graphicFrame naming ppt/diagrams
data, layout, quickStyle and colors parts, plus the group's shapes as the
cached drawing (dsp). The data model is built from the outline (doc, node,
parTrans/sibTrans points and parOf links). A diagram read from a file keeps
its own layout, quick style and colour parts until its layout is switched.

Import: the outline is rebuilt from the data model's parOf tree, so
PowerPoint diagrams get the Text Pane. Their shapes stay the file's drawing
until the first outline edit (typed text isn't mapped back to nodes then).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 01:29:49 +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 Rakitin 9f8c860f90 PPTX corpus: themes, masters, effects and links; keep text Mouse Over actions
New owned corpus test on PowerPoint-shaped XML: a custom-theme deck with
shadow, glow, soft-edge and reflection effects and every common text and
shape hyperlink, and a two-master deck with its own themes and layouts.
The one loss it found: a:hlinkMouseOver on text runs was dropped; it is
now read into RunProps::hover and written back.
2026-10-14 00:52:25 +03:00
Nikita Rakitin c94b5c8d1e PPTX: round-trip 3-D models and animation bounce end
An owned corpus opens, saves and reopens SmartArt and OLE kept as XML, audio and video bookmarks and trims, a section with a hidden slide, slide-number and date fields, ink, .glb models and animation repeat, bounce end and triggers. Relationship-bearing SmartArt and OLE, playback options and rewind stay with their open PRs.
2026-10-14 00:35:12 +03:00
Nikita Rakitin 184b76e2a7 Round-trip text effects, layout, fills, bevels and connectors
An owned corpus of those kinds survives open, save and reopen. A run's
inner shadow, reflection and soft edge were dropped, and a bevel preset
with no kept 3-D XML was not written back, so import and export now keep
them.
2026-10-14 00:04:22 +03:00
Nikita RakitinandCursor b763579d94 View: movable drawing guides saved with the presentation
View > Guides used to paint two fixed centre lines. Guides now belong
to the presentation (DrawGuide, read from and written to p:guideLst in
viewProps.xml, in eighths of a point), so they survive a save and
reopen in PowerPoint.

- Turning Guides on gives a deck without guides PowerPoint's two
  centre guides.
- A guide can be dragged anywhere away from shapes. It moves in whole
  points, unless Alt is held or snapping is off, and shows its
  distance from the centre while it moves.
- A guide dropped off the slide is deleted.
- The slide context menu's Grid and Guides submenu has Add Vertical
  Guide and Add Horizontal Guide.
- While guides are shown, moving and resizing shapes snaps to them.

New commands guide.add, guide.move and guide.delete are undoable;
guide.list is a query.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 23:55:59 +03:00
Nikita Rakitin f9d5a43174 Round-trip comments, links, shows, groups and inherited placeholders
An owned corpus of those element kinds survives open, save and reopen.
Paragraph default run properties, including a link, and action sounds
were dropped on save, so import and export now keep them.
2026-10-13 23:43:03 +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 5c1432b362 PPTX: keep custom XML, the sensitivity label and custom properties
Decks from SharePoint and Microsoft 365 carry customXml items (document
library metadata and content types), docMetadata/LabelInfo.xml (the
Microsoft Purview sensitivity label) and docProps/custom.xml. All were
dropped on save, so a labelled corporate deck came back unlabelled. They
are now kept verbatim with their content types, their own relationships
(itemProps) and the root or presentation relationship linking them. Kept
parts never replace a part the writer makes.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 23:12:18 +03:00
Nikita RakitinandCursor 3f31f9951c PPTX: read Office 2016 charts (waterfall, funnel, treemap…) and keep them
Waterfall, funnel, treemap, sunburst, histogram, Pareto and box &
whisker charts live in a chartEx part behind an mc:AlternateContent
choice requiring cx1. DeckCraft took the fallback, usually a text box
saying the chart isn't available, so these charts were lost on open
and on save.

The cx1 choice is now taken for chartEx frames and the part is read
into the chart model: categories (innermost level), values, number
format, series name, title, legend and data labels. Unchanged charts
are written back as their chartEx part in a cx1 choice with a plain
chart of the same data as fallback, as PowerPoint writes them; an
edited one is saved as a plain chart. Region maps are not read.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 23:08:56 +03:00
Nikita Rakitin 034b312a64 Round-trip tables, charts, animation, media, sections and masters
An owned corpus of those deck kinds survives open, save and reopen. The
check found the handout master — printed header, footer, date and slide
number — was dropped on save, so import and export now keep that part.
2026-10-13 23:08:31 +03:00
Nikita RakitinandCursor e8a383effa PPTX: keep add-in tags on the presentation, slides and shapes
p:custDataLst points at ppt/tags/tagN.xml parts that add-ins such as
think-cell, Mekko Graphics and Office Timeline use to recognise their
decks, slides and shapes. They were dropped on open, so a saved deck lost
its add-in identity. The model now carries name/value tags on the
presentation, slides and shapes; the reader resolves every tags part and
the writer emits one tags part per holder, in the schema's element order.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 23:07:50 +03:00
Nikita RakitinandCursor 30c2fe4b6d Design: Browse for Themes from a .thmx, .pptx or .potx file
deckcraft_pptx::import_theme reads the theme of a .thmx (its main document is
a theme part) or of a presentation's first master, with the media its format
scheme uses. design.browseTheme {path | name, data} applies it to the current
master as one undo step, giving the theme's pictures ids of this deck.

Design tab: Browse for Themes… next to the theme gallery and in the Slide
Master Themes menu; the desktop picker offers Office Theme (.thmx) and
presentations. Ribbon small buttons expose their label to accessibility (same
change as #512). Parity row Browse themes M → D.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 23:04:41 +03:00
Nikita RakitinandCursor 5007c6919e Insert: Summary, Section and Slide Zoom with Return to Zoom
Insert › Links gains Zoom, with PowerPoint's three kinds: Slide Zoom
(pictures of chosen slides on the current slide), Section Zoom (one per
chosen section) and Summary Zoom (a new Title Only slide in front of
the chosen parts). Each zoom is a picture of its target that jumps to
it in the show. With Return to Zoom, on by default for section and
summary zooms as in PowerPoint, the show comes back to the zoom slide,
fully built, after the target slide or the section's last slide; going
elsewhere (a slide number, See All Slides) forgets it. Hyperlink gains
zoom_return for this; .pptx saves zooms as the linked pictures
PowerPoint writes as their fallback, so the return flag is DeckCraft-
only for now. Live thumbnails, the zoom-in animation and the native
p166:sldZm element are still missing; gaps.md says so.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 22:40:37 +03:00
Nikita RakitinandCursor 9af5a7d17b Pictures: Artistic Effects — apply, change, remove and keep in PPTX
New picture.artisticEffect applies one of 7 effects (blur, pencil
grayscale, line drawing, film grain, cutout, glow edges, photocopy) to a
picture's pixels, as PowerPoint does: the processed PNG becomes the
picture and the original is kept on PictureFill::artistic, so another
effect starts from the original and `none` (or Reset Picture) restores
it. Change Picture drops the effect.

PPTX: written and read as PowerPoint does, the blip being the processed
picture with the original and the effect name in
a:extLst/a14:imgProps/a14:imgLayer, so a deck from PowerPoint keeps its
effect, original and all, when saved again.

Picture Format gets an Artistic Effects menu.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 22:35:55 +03:00
Nikita RakitinandCursor 6a85afa236 Pptx: round-trip an owned corpus and keep notes-master text
Open, save and reopen decks we author, and compare package parts and
text. The check showed a notes master's header and footer were replaced
by an empty notes master on save.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 22:34:29 +03:00
Nikita RakitinandCursor 69a4424e75 Transitions: built-in sounds, Stop Previous Sound and Loop Until Next
Follow-up to the transition sound picker. The Sound box now lists
[Stop Previous Sound] and six built-in sounds (Chime, Click, Camera,
Whoosh, Drum Roll, Laser) that are synthesised as small WAVs when
chosen, so no sound files ship with the app; the same built-in sound is
embedded once however many slides use it. Loop Until Next Sound repeats
a sound in the show until another slide's sound or Stop Previous Sound.
PPTX reads and writes p:stSnd loop="1" and p:endSnd, keeps the sound's
file name in p:snd/@name, and setting a slide's transition to None no
longer drops its sound.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 22:30:19 +03:00
Nikita RakitinandCursor 5eef9fb55a Pictures: compress pictures to a target resolution
Picture Format › Adjust gains Compress Pictures, with PowerPoint's
options: HD 330, Print 220, Web 150 or E-mail 96 ppi, apply to the
selected pictures or all, and delete cropped areas. The new
picture.compress command downsamples each PNG, JPEG, BMP, TIFF or WebP
picture to the pixels its shown size needs at that resolution (JPEG
stays JPEG at quality 85, the rest become PNG), cuts away cropped areas
when asked, and only replaces a picture when the result is smaller or a
crop was removed. Originals nothing else uses are dropped so the saved
file shrinks; one shared with a picture that wasn't compressed stays.
One undo step restores everything.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 22:21:57 +03:00
Nikita RakitinandCursor 7432c61665 Slides: reuse slides from another presentation
Home › New Slide gains Reuse Slides… and Reuse Slides (Keep Source
Formatting)…, backed by a new slide.reuse command that inserts the
slides of a .pptx or .deckcraft file (all, a list, or a range) after the
current slide in one undo step. By default each slide moves to the
destination layout with the same name or kind, so it takes this deck's
theme; keepFormatting brings the source master and its layouts along.
Pictures, media and sounds are copied under fresh media ids, so ids
that clash between the two decks no longer mix up pictures, and shape
ids are renumbered with animations, triggers and connector ends
following them.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 22:14:46 +03:00
Nikita RakitinandCursor 460a2712e4 Transitions: choose a transition sound and play it in the show
Transition sounds were read from and written to .pptx but could not be
set and never played. Transitions › Timing gets a Sound box ([No Sound]
or Other Sound…), backed by a new transition.sound command that embeds
an audio file on the selected slides (or removes it with none). In the
slide show the sound plays as its slide comes in and, as in PowerPoint,
keeps playing into the next slide unless that slide has a sound of its
own. Built-in sounds, Stop Previous Sound and Loop Until Next Sound are
still missing; the parity docs say so.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 22:07:06 +03:00
Nikita RakitinandCursor 607ffc5591 Text: set text transparency from Text Fill (#32)
There was no way to make text see-through: the only Transparency
slider was the shape fill's. The new format.textTransparency command
keeps the text's colour and sets its alpha (replacing any it had, and
dropping it at 0). A run without its own colour takes the colour it
shows now, so inherited placeholder or theme colours stay as they are.
Gradient text gets the alpha on every stop. The Format Shape pane's
Text Options page gains a Text Fill section (colour and Transparency),
and the Shape Format › Text Fill dropdown has the same slider.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 21:55:21 +03:00
Nikita RakitinandCursor d2066a1f07 Pptx: budget chart points, chart XML size, inflate work and VML lookups (#401)
- Charts: every category/value/size cache draws from one chart-wide
  budget of 1M decoded slots, so sparse ptCount/idx declarations across
  many series can't expand far beyond the XML.
- Chart parts go through the same 96 MiB XML size guard as other XML.
- Package::open charges every inflated byte, including parts it then
  discards, against a 4 GiB decompression budget and stops reading
  entries once it is spent.
- Legacy OLE previews index each VML drawing once (shape id -> picture
  part) instead of reparsing it and its rels for every object.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 20:53:49 +03:00
MarekSpodBiedry 09b72e4b70 Pptx: keep the math namespace equations inherit from the slide root or a wrapper (#412) 2026-10-13 17:41:28 +02:00
NikitaandCursor 82dcd86c88 Pptx: read and write embedded fonts
A deck that embeds a TrueType or OpenType face, including one wrapped as Embedded OpenType, now draws with that face and saves it back. MicroType Express subsets stay in the file and still draw in a stand-in.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 18:22:48 +03:00
Sazid Al Bayazid e70fce996b Model: an exhausted id space refuses growth instead of duplicating ids (#407)
alloc_id bumped next_id with saturating_add: a presentation whose
next_id reached u32::MAX (a hostile file can arrive that way;
fix_next_id imports it) handed out that same id to every new slide,
shape, layout and media - duplicate ids, ambiguous references, silent
corruption on every later insert.

alloc_id now returns Option<u32> via checked_add, and every caller
refuses: the engine's insert/duplicate/media/layout commands answer
with a clear error naming the command, paste and duplicate re-id
helpers propagate it, media addition is fallible, and a fresh slide is
Option. The pptx export's synthesized blank layout is guarded the same
way. Loading keeps such a deck viewable: repair re-ids duplicate
slides while it can, and a duplicate it cannot re-id stays as it is -
growth is refused, and only that duplicate keeps its ambiguous id.

Renumbering the loaded graph was rejected: it needs the
cross-document reference remapping that issue #406 tracks.

Tests: model exhaustion (alloc_id None, fresh media refused, a new
slide refused), engine (slide.new, shape.insert, slide.duplicate and
edit.duplicate all refuse; the document holds no duplicate ids),
format repair (an unre-id-able duplicate stays visible).
2026-10-13 21:13:25 +06:00
Sazid Al Bayazid 69d4893689 Comments: threads and resolved state survive a .pptx round trip (#70)
The writer emitted the legacy comment part only: replies were flattened
into sibling comments, the resolved flag was dropped. Modern PowerPoint
decks carry a second, threaded part (p188) as well - and DeckCraft read
both, importing every comment twice.

Export now writes the modern threaded part (p188:cmLst, with the slide's
commentRel anchor ext and the modern authors part) next to the flattened
legacy part, the same pair of parts PowerPoint itself writes: older
readers keep the legacy view, PowerPoint 2021+ and DeckCraft read
threads, replies and resolved state. The reader prefers the modern part
when both are present and scales modern positions as EMU instead of
legacy 1/8 pt, so real PowerPoint decks stop double-importing their
comments and keep their marker positions.

Comment ids are deterministic GUIDs from the existing tables::guid, so
exports stay reproducible without a new dependency.

Known limitation for a follow-up: comments anchor with
p188:unknownAnchor (schema-valid) rather than a slide moniker, which
needs part identity the model does not have yet.

Tests: threads plus resolved state round-trip on top-level comments and
replies, both parts and the anchor-rel wiring asserted in the raw
package, part numbering with comment-free slides skipped, legacy-only
and modern-only packages import each with their own position units, and
XML-special characters survive the trip.
2026-10-13 19:25:04 +06:00
Brandon ThomasandClaude Opus 5.5 7cb62d5197 Pptx/Render: picture fills with rotWithShape=0 stay upright
A shape's picture fill marked not to rotate with the shape turned and
flipped with it (rotWithShape was neither kept nor written: always 1).
PowerPoint keeps such a picture upright, stretched (or tiled) over the
box the rotated shape covers on the slide and clipped to the shape. Now
read, written (PictureFill::upright) and drawn so.

Wild synthetic set: picture fills on rotated/flipped shapes 12.89 ->
3.87.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 08:16:41 -04:00
Brandon ThomasandClaude Opus 5.5 675d20417e Pictures: black and white, inverted alpha, and PowerPoint's grey weights
- a:biLevel (Color > Black and White) was ignored. It is now read, written
  and drawn: white where the luminance reaches the threshold, else black
  (observed thresholds at 30/50/70% on colour swatches).
- a:alphaInv was ignored; an opaque picture with it is invisible in
  PowerPoint. Now read, written and drawn.
- Grayscale, duotone and saturation weighed channels 0.299/0.587/0.114;
  PowerPoint's export greys pure red to 54 and green to 182: Rec. 709
  weights (0.2126/0.7152/0.0722).

Wild synthetic set: recolour slide 7.60 -> 1.15, picture corrections
13.36 -> 7.36.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 08:16:41 -04:00
Brandon ThomasandClaude Opus 5.5 754841aaa4 Pptx: a table naming no style reads as the table grid style
A table whose tblPr names no tableStyleId drew without any lines.
PowerPoint draws such a table with thin dark grid lines (as its "No Style,
Table Grid"); observed on a synthetic deck with and without the explicit
"No Style, No Grid" GUID. Such tables now read as the grid style.

Wild synthetic set: tables with cell margins/fills/styles 4.80 -> 2.82,
11.28 -> 10.15, 6.86 -> 3.16.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 08:16:41 -04:00
Brandon ThomasandClaude Opus 5.5 0c5ddb5dea Gradients: read, write and draw a:tileRect
Gradient tile rectangles were dropped on import. PowerPoint's "from
corner" radial presets depend on them: fillToRect puts the focus on a
corner and tileRect stretches the gradient's box a whole size past it, so
the circle is centred on that corner and reaches the far one. Without it
(after the two-point radial change) such fills washed out. A linear
gradient now spans its tile rectangle; a radial one ends on the circle
around it, with the focus still placed in the shape's own box (fitted to
PowerPoint's export of the corpus deck tdf114848: mean diff over the
filled box 0.77). Round-trips through pptx.

Wild synthetic set: tile-rect gradients 16.74 -> 2.48.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 08:16:41 -04:00
Brandon ThomasandClaude Opus 5.5 f5fef50364 Text: rtlCol puts the first column on the right; just/dist anchoring at the bottom; wordArtVertRtl
Observed on PowerPoint's export (w14-xml s12):
- a two-column body with rtlCol="1" starts its first column on the right; DeckCraft read and
  saved the attribute but laid columns out left to right;
- anchor="just" and anchor="dist" place the text at the bottom of the box, like anchor="b";
  DeckCraft drew them at the top;
- wordArtVertRtl stacks characters like wordArtVert but runs its lines from right to left; it was
  read as wordArtVert (and saved back as it). It is now its own TextDir, kept on save.

w14-xml s12 9.47 -> 5.39.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 06:48:43 -04:00
Brandon ThomasandClaude Opus 5.5 b8a665f0ca Text: mongolianVert and wordArtVert (stacked) text as PowerPoint draws them
mongolianVert was read as vert (and saved back as vert). PowerPoint turns it like vert but runs
its lines from left to right, the anchor mirrored with them (bottom-anchored text sits on the
right). It is now its own TextDir, kept on save; its lines' places are mirrored across the box.

wordArtVert (Stacked) was turned like vert. PowerPoint stands every character upright, one
under the other (Latin letters about one em apart, spaces their own width), with lines running
left to right. Stacked text now stands each character upright in an em of its own and mirrors
the line order.

Also: a bullet in the second or later column of a multi-column body is drawn on its line's
baseline (it kept the first column's).

w01-vertical s4 (mongolianVert) 11.54 -> 9.38, s5 (wordArtVert) 13.84 -> 13.56; w14-xml s13
6.78 -> 6.60.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 06:48:43 -04:00
Brandon ThomasandClaude Opus 5.5 d5e30557eb Transitions like PowerPoint: measured frame by frame and retuned (#366)
Every transition and Effect Option was built in PowerPoint (COM), exported as
video and compared frame by frame with DeckCraft at the same progress
(mean abs diff over 150 variants 35.7 -> 15.0, 0-255).

- anim: transition_frame(kind, option, t, aspect) with measured curves
  (smoothstep fades, ease-in-out moves, Cover/Uncover/Pan curves), directions
  and option meanings, soft edges as per-corner opacity, 3-D effects as
  perspective-projected cards, Dynamic Content moving slide contents over
  cross-fading backgrounds (Source::OldBack/NewBack/OldContent/NewContent);
  layer_mesh subdivides perspective quads so textures stay straight.
- New options: Page Curl Single, Glitter Hexagons, Shred In/Out, Zoom and
  Rotate; PowerPoint-style Effect Options labels.
- render: composite_transition (CPU twin of the show), render_slide_part,
  render_transition; deckcraft-cli render-transition FILE --slide N --t T.
- show: per-vertex opacity meshes, slide parts rendered once per transition.
- pptx: PowerPoint's elements and defaults (p:strips diagonal wipes, p14:warp
  and p:newsflash for Zoom, p:zoom for Shape In/Out, glitter pattern, shred
  rectangle/dir, prstTrans invX per preset, pageCurlSingle, defaults for
  randomBar/doors/window/pan/zoom); PowerPoint reopens DeckCraft's files with
  the same effects.
- Tests: measured curves, probes of which slide shows where at t, option
  coverage, per-frame triangle budget, PowerPoint XML and defaults round trip.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 05:31:13 -04:00
pierrevbc 8a4342757b SmartArt: text is laid out on its text rectangle (dsp:txXfrm), not in columns
A SmartArt drawing shape keeps its text rectangle in dsp:txXfrm, apart
from the shape's own box. The importer ignored it and laid the text out
in the shape itself. In list layouts the shape is a tall, narrow box
turned by 90 degrees, so the text came out as narrow vertical columns,
in the editor and in the exported PPTX.

The text rectangle uses the shape's coordinate space and is turned by
the shape's rotation plus its own:

- When it is the shape's text area shrunk by some margin, with the same
  orientation, the shape keeps its text and the margin is added to its
  insets.
- Otherwise (a rectangle reaching outside the shape, or turned against
  it) the text moves to a new shape without fill or outline, placed on
  the rectangle right above its shape in the diagram's group.

Both export as plain DrawingML (positive insets, an ordinary rotated
shape), which other readers lay out the same way.

Test: a SmartArt drawing built in the test, with a text rectangle wider
than its shape, a turned shape with upright text, and a rectangle
inside its shape; the laid-out text box is checked on import and after
a PPTX round trip.
2026-10-13 11:23:30 +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
Brandon ThomasandClaude Opus 5.5 7d8bb05374 rustfmt
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 04:20:52 -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
Brandon ThomasandClaude Opus 5.5 67b7f82cff Chart legend test: a chart with a real namespace and a bar chart, as the reader needs
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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
natocool2andClaude Opus 5.5 0d6301cb7c Bump quick-xml to 0.41 (RUSTSEC-2026-0194, RUSTSEC-2026-0195)
RUSTSEC-2026-0194 (quadratic duplicate-attribute check) and RUSTSEC-2026-0195 (unbounded NsReader
namespace allocation) are fixed in quick-xml 0.41. deckcraft-pptx already reads attributes with
with_checks(false) and does not use NsReader, so neither is reachable today; the bump keeps the
workspace on a supported quick-xml and leaves one copy (wayland-scanner already locks 0.41.0).

decode_and_unescape_value() is deprecated in 0.41 (clippy -D warnings); decoded_and_normalized_value
(Implicit1_0, ...) is what the deprecated method now does.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 09:07:44 +01:00
NikitaandCursor 71c5b1712a Charts: ignore relationships that point outside a chart's own parts (#335)
A chart relationship must not be able to replace a slide or another package part when the deck is saved.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 10:53:08 +03:00