Make the slide show behave like PowerPoint for interactive decks.
- Hit testing resolves the topmost visible shape under the pointer.
Non-interactive shapes block shapes beneath them; the hand cursor
shows only over interactive shapes.
- Click-triggered animations (interactive sequences) play on shape
click, repeat after their last step, and apply in click order so
cycling "score ring" shapes work.
- Each slide keeps its own progress: returning to a slide through a
link or Back restores hidden shapes and animation state.
- A shape with a link and an animation follows the link immediately;
its animation clock only runs while the slide is shown and resumes
with the remaining time on return.
- With advance-on-click off, background clicks still play animation
steps but never change slide.
- A click on a playing step completes it at once.
Docs (gaps, animation and slide show parity, roadmap) are updated.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A default export is 2 pixels per point. Without a resolution, Preview
treats those pixels as 72 dpi and the picture opens at twice the slide's
size. PNG pHYs and JPEG JFIF density now say scale times 72, so the
default is 144 dpi. Screenshots stay untagged.
Co-authored-by: Cursor <cursoragent@cursor.com>
The preedit was already stored in the cell. It is now laid out the same
way the cell is drawn, and the editor underlines it in place, thicker
under the part being converted. The caret and the input method's
candidate window sit in that cell. Notes stay an egui text field.
Co-authored-by: Cursor <cursoragent@cursor.com>
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>
sp3d extrusionH (with extrusionClr, srgb or scheme) under a camera that
turns the shape now draws the shape's sides: its outline swept from the
back face to the front along the camera's view of the depth axis, in the
side colour shaded, before the face. camera::project3 projects points
off the shape's plane.
Notes pages and handouts lay out the master's header, date, footer and
page-number placeholders with deckcraft-text (render::place_master_texts),
so their text wraps in the placeholder and keeps mixed run formatting,
drawn as visible glyphs. Stacked on #580.
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>
ui_soak_tests.rs drives the app through the egui test harness with seeded
random clicks, drags, keys (plain, Ctrl, Shift), typing and scrolling over the
sample deck. Every ten actions it checks that every document validates, the
selection is in range, undo, journal, thumbnail and texture caches stay
bounded, and no command or render panic was caught; at the end, that input
really reached the editor and the mean frame stays under 250 ms. Two seeds x
150 actions run in CI; DECKCRAFT_UI_SOAK_STEPS/SEED run it long.
Panics swallowed by the guards were invisible to tests: Session now counts
them (panics_caught) and deckcraft_render::panics_caught() counts render
panics drawn as blank. Textures::thumb_count exposes the thumbnail cache size.
Co-authored-by: Cursor <cursoragent@cursor.com>
A read-only command, {slide?, x, y (slide units), scale?}: the slide is rendered and
the pixel at the point is returned as {color: "RRGGBB", alpha, x, y}. This is what the
Eyedropper takes, and what scripts and MCP use to read a colour off a slide. A point
outside the slide, a missing or non-numeric coordinate or an unknown slide is an error.
A shape seen through a 3-D camera preset (isometric, perspective...) or
turned with a:camera/a:rot drew flat and front-on. PowerPoint turns the
shape's plane in space and projects it. Fitted black-box to its exports
(a picture with coloured corner markers under every preset and several
rotations; every fit within half a point on a 100 x 75 pt shape): points
about the centre are turned Rz(-rev) Rx(lat) Ry(lon), perspective cameras
then dividing by D / (D - z) with D about 5-16 shape sizes; a:rot turns
the other way about the horizontal and vertical axes. DeckCraft now draws
the shape under the affine transform that best fits its turned corners:
exact for orthographic cameras, within 2% of the size for perspective
ones (an affine map can't foreshorten). Oblique cameras leave a flat
shape as it is; depth (extrusion) is not drawn.
Wild synthetic set: camera presets 15.02 -> 6.35, 3-D picture styles
16.00 -> 7.72, extruded cameras 21.41 -> 19.74.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A reflection on a picture (PowerPoint's "reflected" picture styles) drew
nothing: the reflection painted the shape's fill, and a picture has none.
It now mirrors the picture itself, clipped to its outline, under the same
fade.
Wild synthetic set: picture effects slide 16.77 -> 16.00 (the rest is
3-D camera rotation, not modelled).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
An outline naming no join was always rounded. PowerPoint rounds most
presets but mitres some by default: classified per preset by comparing
its export (8 pt outline, no join) with round- and miter-joined renders:
the plus, right/up/down block arrows (not the left one), chevrons, stars
from five points up, the equation shapes, curved ribbons and the action
buttons. Miter joins also take PowerPoint's default limit of 8 widths
(kurbo's default was 4), so sharp star points no longer bevel off.
Wild synthetic set: joins slide 0.43 -> 0.21, outline-on-pattern slide
3.95 -> 3.76, preset galleries slightly better.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The shadow of a picture is the picture recoloured to the shadow colour,
but drawing the picture left its pixel-space transform set, so the
recolouring rectangle (sized in points) covered only part of a picture
whose bitmap is bigger than it is shown: a 400 px photo at 240 pt cast a
shadow of its top-left corner only. The shape's transform is restored
before recolouring.
Wild synthetic set: framed pictures with shadows 7.67 -> 5.95, rotated
picture with a shadow 10.67 -> 10.07.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Explicit cell borders were stroked as plain solid lines (no dash, compound
or cap), and diagonal borders (lnTlToBr, lnBlToTr) were read but never
drawn. Both now go through the shape line stroker; diagonals are drawn
under the cell edges.
Wild synthetic set: border styles slide 5.67 -> 2.26, thick merged-cell
borders 1.20 -> 0.69.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A shape with a top bevel seen through a 3-D scene drew flat. Fitted to
PowerPoint's export of the bevel presets on a solid fill with the default
three-point light rig and matte material, DeckCraft now lights the face
and a band as wide as the bevel inside the outline as surfaces: Lambert
light from the upper left (azimuth 240, 45 degrees up), c * (0.453 +
0.731 * n.L) + 14.7 per channel, the band's normal tilting outwards by
the profile's slope (quarter circle by default, straight for angle).
Within about 15 grey levels RMS of PowerPoint on the circle bevel; other
profiles use the circle's, pictures get light and dark veils, and other
light rigs and materials (and anything without a scene) stay flat.
Wild synthetic set: bevel presets slide 5.20 -> 2.48, materials/rigs
13.25 -> 12.73.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
An outer shadow set on a group (grpSpPr effectLst) was ignored. PowerPoint
casts it from everything in the group: the children are now drawn once
more under the shadow's offset, scale and skew (anchored on the group's
box), recoloured to the shadow colour and blurred, below the group.
Wild synthetic set: combined-effects slide (shadowed group) 2.00 -> 0.98.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A line filled with a gradient drew in its first stop's colour only. As
PowerPoint draws it, the gradient is laid out over the box the stroke
covers (the outline's bounds grown by half the line width, before the
line is cut back under its arrowheads), so a horizontal line's 90 degree
gradient runs across its width; arrowheads take the gradient where they
sit.
Wild synthetic set: gradient lines slide 8.43 -> 0.40; picture with a
gradient border 8.54 -> 7.67.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Follow-up to drawing picture borders outside the picture: PowerPoint does
that for flat pictures only. A picture seen through a 3-D scene with a
bevel (a common picture style) gets its border centred on the edge like
any shape: observed with an 18 pt border, which then covers 9 pt of the
picture. The corpus deck 60810 (white-framed bevelled screenshots) showed
the screenshots' own edges once the border moved out; it now matches
PowerPoint again.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Left/right brackets and braces drew only their curve: a filled bracket
showed no fill. PowerPoint fills them out to the straight side they open
to (the fill path is the curve closed), outlining only the curve.
- Arrowheads were drawn on any shape with nothing filled (brackets among
them) but not on open freeforms that had a fill. PowerPoint puts them on
lines, arcs and open freeforms whether filled or not, never on brackets.
Wild synthetic set: preset galleries 9.44 -> 4.65, 9.55 -> 4.94,
9.60 -> 5.38; extreme-adjust galleries 10.7 -> 6.6.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A shape inside a group whose fill is grpFill drew nothing (the fill was
read but the renderer skipped it). PowerPoint fills it with the group's
fill laid out over the whole group: a gradient or pattern runs on across
the children rather than restarting in each. Groups without a fill of
their own pass their parent's on.
Wild synthetic set: group fills slide 27.33 -> 7.88.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
DeckCraft centred a picture's outline on its edge, covering half the
border's width of the picture. PowerPoint draws picture borders wholly
outside: an 18 pt white photo frame leaves the whole photo showing and
reaches 18 pt out (measured on its export; a 2 pt border on a cropped
picture covers 18-20 pt for a picture starting at 20). Pictures now stroke
their border twice as wide, clipped to outside the outline, keeping dash
lengths; the border's shadow is cast from there too. Compound borders
stay centred.
Wild synthetic set: picture frames 13.12 -> 8.54, cropped/flipped pictures
with borders 5.79 -> 2.57, crop-to-shape 8.03 -> 5.25.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
An outer shadow was always the shape's filled silhouette at the shadow's
opacity: an outline-only shape cast a solid block, a 40% fill cast a full
shadow that darkened it from behind, and lines (and outlines) cast none.
PowerPoint casts the shadow from the drawn shape: the filled part as
see-through as its fill (nothing for no fill) plus the outline, which is
now stroked into the shadow layer with the line's width, dash and opacity.
Wild synthetic set: combined effects slide (no-fill frame, 40% fill,
shadows) 21.88 -> 2.34.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A shadow's sx/sy/kx/ky were applied about the shape's centre with the
skew unscaled, so a perspective shadow (algn=b, sy 23%, kx -20 deg) floated
in the middle of the shape instead of lying along its bottom edge. As
PowerPoint draws it, the shadow is skewed then scaled about the point of
the box its algn names (b: middle of the bottom edge, tl: top-left...).
Wild synthetic set: shadow alignment/scale/skew slide 5.57 -> 0.41,
picture frames 13.71 -> 12.71.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- A wide line poked its corners (and square caps) out past a triangle,
stealth or open arrowhead: the line now stops under the head (at a
triangle's base, inside a stealth notch, where an open arrow's legs meet).
- A see-through line darkened where it overlapped its heads; PowerPoint
draws line and heads as one shape, so they are drawn opaque into a
faded layer.
- Heads on lines thinner than 2 pt were too small: PowerPoint sizes them
as for a 2 pt line at least (measured 6 pt for a medium head on 0.25 to
2 pt lines).
- An open arrow's point sat a miter past the line's end, with flat-ended
legs; PowerPoint puts the point's outside on the end and rounds the legs.
Wild synthetic set: open arrows by width 6.85 -> 3.78, 8 pt open arrows
3.84 -> 1.89, triangles by width 3.62 -> 2.17, stealth by width 3.45 -> 2.38.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A round-capped dashed line (PowerPoint's "Round Dot" is sysDot with round
caps) drew as a solid line: each dash grew by its caps and closed the
one-width gaps. PowerPoint keeps the caps inside each dash, so dots stay
separate circles. Square-capped dashes end flat in PowerPoint; only the
line's own start (and its end, when it ends in a dash) is squared off.
Wild synthetic set: 12 pt round-cap dashes 12.69 -> 7.05, 12 pt square-cap
dashes 11.76 -> 6.12, custom dashes 2.12 -> 0.10.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A freeform whose path holds a sub-path inside another (an icon, outlined
text, a frame drawn as two rectangles) showed the inner one filled when
both wound the same way: DeckCraft filled custom paths non-zero.
PowerPoint fills every custom path alternately (even-odd), so the inner
sub-path is a hole whichever way it winds.
Wild synthetic set: holes slide 7.60 -> 2.84 mean diff.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
eaVert text was laid out exactly like vert: the whole text turned a quarter turn, so Japanese and
Chinese lay on their side. PowerPoint draws ideographs, kana, Hangul, full-width forms, CJK
punctuation, circled numbers and emoji upright, each turned back about the centre of its em box,
while Latin letters and digits stay on their side ("英字123も": 123 sideways). It keeps the glyphs'
horizontal forms (no vert alternates: "、" "「" are simply turned), which DeckCraft now matches.
Glyph runs carry an `upright` flag; the renderer turns each such glyph about its em box centre
(0.38 em above the baseline). w01-vertical s3 (eaVert) 9.70 -> 8.98, s6/s7 (eaVert rotated,
flipped, bulleted) 1.58 -> 1.45, 2.30 -> 1.76.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Every underline was a solid line 0.06 em thick at 0.12 em below the baseline, whatever a:rPr/@u
asked for. Underlines now sit at the font's own underline position and thickness (post table),
where PowerPoint draws them (Arial 96 pt: 10 px below the baseline, 7 px thick), and each style
is drawn as measured on PowerPoint's export: dbl two lines 0.55 thick spanning one thickness above
to the single line's bottom; heavy from one thickness above to 0.55 below; dotted dots and gaps one
thickness long; dashes three long with gaps of two; wavy a thin zigzag every 3.9 thicknesses. The
"words" style underlines spaces too, as PowerPoint draws it. Dashes and waves are new Deco line
kinds the renderer fills or strokes (warped text draws their boxes).
Underline slides: w14-xml s10 11.49 -> 10.43, s11 6.64 -> 4.06; w06-charfmt s3 9.66 -> 9.51,
s4 7.63 -> 7.44.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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>