Commit Graph
958 Commits
Author SHA1 Message Date
Nikita Rakitin 3ea696dc1a Charts: read, write and draw error bars 2026-10-14 04:48:33 +03:00
Nikita Rakitin 679ce03da4 Show: a first animation set to With/After Previous plays when the slide appears (#631) 2026-10-14 04:47:09 +03:00
Nikita RakitinandCursor 8fde746211 Format: never save a .deckcraft that can't be reopened over a NaN
serde_json writes NaN and infinity as null, which doesn't read back as a number, so one NaN
anywhere in the model (a rotation, position, crop, stroke width…) made the saved file (and its
AutoRecover copy) fail to open as "damaged".

- Writer: presentation.json goes through finite::Finite, a serializer adapter that writes
  non-finite floats as 0.
- Loader: files already written that way open; each null where a number belongs reads as 0
  (inside tagged enums, where serde only reports the enclosing object, candidates are tried
  nearest first and kept only when the parse gets further). Other damage still fails.
- repair() brings shape geometry into range: positions and sizes finite and within ±1e6 pt,
  rotation 0–360, picture crop -10..1, font sizes 1–4000 pt, line widths 0–1584 pt.

Animation timings are u32 and can't carry NaN.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 04:45:32 +03:00
Nikita Rakitin 4a7ad03eb0 Charts: logarithmic value axes 2026-10-14 04:45:26 +03:00
Nikita RakitinandCursor b6aa6ab4e4 UI: Date and Time dialog inserts a format in one step
Insert › Date & Time opens the format list instead of placing a date
immediately. With no format, update flag or language, insert.dateTime
opens the dialog and does not edit. OK applies one undo: a field when
Update automatically is on, or the shown text when it is off.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 04:41:01 +03:00
Nikita Rakitin aed386e269 Charts: draw, read and write value-axis minor gridlines 2026-10-14 04:39:00 +03:00
Nikita Rakitin f0647e1bd8 Review: previous and next comment
Walk every comment in the deck from the Review tab, and list every slide in the Comments pane.
2026-10-14 04:37:49 +03:00
Nikita RakitinandCursor 22074c4c69 Format: repair degenerate slide sizes on load
repair() brings each slide side into PowerPoint's 72–4032 pt (as Design › Slide Size allows;
it accepted 1–4000 before), and replaces a zero, negative or non-finite size with 16:9; a bad
notes size gets the default. The native reader takes a null, string or missing slide/notes
size as NaN for repair to fix, so such a file opens instead of failing as damaged (NaN and
infinity are saved as null). The canvas fit and slide show fit treat a zero or non-finite side
as 1 pt, so an in-memory bad size can't make layout infinite.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 04:35:13 +03:00
Nikita Rakitin 2702b48530 Show: show the slide number while typing it 2026-10-14 04:26:02 +03:00
Nikita Rakitin 8a5eec369f Render: skip laying out table cell text that lands wholly off the target 2026-10-14 04:22:37 +03:00
Nikita Rakitin ed20cebed8 Charts: scatter and bubble charts get a value x axis 2026-10-14 04:22:19 +03:00
Nikita RakitinandCursor fcb5eae1a5 Startup: fall back to Wayland when DISPLAY names no X server
DeckCraft forces X11 whenever DISPLAY is set. A stale DISPLAY (an ended ssh -X session, or
Xwayland turned off) made start-up fail with "failed to open display" while a Wayland
compositor was running. A local DISPLAY whose /tmp/.X11-unix socket is missing now starts on
Wayland when WAYLAND_DISPLAY is set; remote displays and live servers keep X11. Forcing Wayland
without a compositor keeps X11, and with no display at all the error says so plainly.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 04:21:30 +03:00
Nikita Rakitin dfee72e742 Show: play a custom show 2026-10-14 04:19:36 +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 RakitinandCursor dbffbab59d UI: Edit Photo Album reflows the album in one step
Reopen the Photo Album dialog on the current album and replace those slides
in one undo, with black and white, rotation, brightness, contrast and a theme.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 04:16:00 +03:00
Nikita Rakitin fd1b0a1965 Charts: draw the axes' titles 2026-10-14 04:12:18 +03:00
Nikita Rakitin f5fd324892 Show: presenter timer pause, reset and notes size 2026-10-14 04:06:50 +03:00
Nikita RakitinandCursor d31ed52bbe Show: presenter view keeps a portrait Next slide inside its column
The Next preview took the column's full width and the slide's aspect for its height, so a
portrait slide (up to 1:56) drew a white slab many times the window's height over the notes,
which were pushed below the window. It is now fitted into the top 60% of the column; 16:9
slides keep the full width as before.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 04:04:09 +03:00
Nikita Rakitin 0b66323765 PPTX: shape text without an anchor sits at the top (or the theme's spDef anchor); write ctr for the model's middle default 2026-10-14 04:03:35 +03:00
Nikita RakitinandCursor 05eb4c611b UI: keep every texture within the GPU's max texture side
Slide show, transition and morph frames, thumbnails, master-view canvas, master/layout
thumbnails, Design Ideas previews, presenter-view preview and video frames all upload through
textures::upload/replace, which shrinks a picture past max_texture_side (egui panicked on one).
Render sizes are fitted to the limit first, so a big screen, extreme DPI or a 1:56 slide
doesn't render a picture the GPU can't hold. The master canvas is cropped like the slide canvas.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 03:57:32 +03:00
Nikita Rakitin 77de43266e Text: shrink on overflow stops at once when even the smallest scale overflows 2026-10-14 03:56:19 +03:00
Nikita Rakitin dac0d054fe Show: See All Slides and zoom
During a show, G opens a thumbnail grid and a click jumps to that slide.
Z then a click zooms the slide to 2×. Presenter view has Black, White,
All slides and Zoom. Esc closes the grid, then the zoom, before it leaves.
2026-10-14 03:53:53 +03:00
Nikita RakitinandCursor ba71a40a39 Canvas: a trackpad swipe turns the page
A sideways flick changes slides when the slide fits the window, and any
flick does so during the show. One gesture turns one page. A zoomed slide
still pans. Pinch-zoom is unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 03:48:39 +03:00
Nikita RakitinandCursor 4575d19ac7 UI: Photo Album dialog inserts pictures as slides
Insert › Images opens Photo Album. insert.photoAlbum adds the pictures
and text boxes as slides in the open presentation, one undo step, with
layouts, frames and captions. Omitting pictures opens the dialog.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 03:43:28 +03:00
Nikita Rakitin 3fd1083468 Shapes: chevron text rectangle as presetShapeDefinitions give it 2026-10-14 03:27:58 +03:00
Nikita RakitinandCursor c583480010 Startup: survive damaged settings, font folders, recovery folders and small texture limits
- ui.json / prefs.json are read through a new settings module: regular files only, 4 MiB
  cap, parse errors logged, values sanitized (a saved zoom of 1e30 aborted start-up,
  1e4 panicked in egui); writes are atomic.
- The canvas and the control protocol clamp stray zooms; the status bar shows the zoom in use.
- The canvas texture is cut to the GPU's max texture side (zoom 400% on a 2048 limit panicked).
- The system font scan opens only regular files of sane size (a FIFO named *.ttf in ~/.fonts
  hung start-up), with depth and entry caps.
- AutoRecover skips non-regular entries and reopens at most 32 per start, newest first.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 03:27:57 +03:00
Nikita Rakitin 111f029112 Shapes: star4 and star5 text rectangles as ECMA-376 defines them 2026-10-14 03:23:17 +03:00
Nikita RakitinandCursor bd017b861d UI: Size and Position dialog sets geometry in one step
Shape Format › Size and the shape menu open a dialog for position,
size, rotation, scale and lock aspect ratio. One command writes them
together, so undo restores the whole change.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 03:20:35 +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 Rakitin ca2af8fe30 Render: cap a stroke's dash count so a tiny dash on a huge shape can't abort on open 2026-10-14 03:14:28 +03:00
Nikita Rakitin 8e124d32a8 Charts: clustered bar widths from gap width and overlap as fractions of one bar; schema defaults when absent 2026-10-14 03:09:16 +03:00
Nikita Rakitin cbc6cd0e34 Charts: draw data-point fills on columns and bars, smoothed lines, and the file's chart text colour 2026-10-14 03:03:16 +03:00
Nikita RakitinandCursor e4022e6702 UI: Paragraph dialog sets alignment, indents and spacing
format.paragraphDialog applies alignment, first-line and hanging
indents, spacing and line spacing in one undo step. With no fields it
opens the dialog from the Home › Paragraph launcher. Tabs… opens a
standalone Tabs dialog and returns to Paragraph.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 02:59:40 +03:00
Nikita RakitinandCursor fea8c1498f Metafile: EMF+ Clear, and the EMF+ record coverage written down
EmfPlusClear paints the whole picture frame in its colour, ignoring the
world transform and clip, as GDI+ does; a transparent clear draws nothing.
With it every drawing record of MS-EMFPLUS 2.3.4 is played. The module docs
list what is deliberately ignored (rendering hints, rendering origin,
serializable image effects, terminal-server records, and StrokeFillPath,
which the specification names but gives no layout for), and the parity docs
no longer say EMF+ isn't drawn.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 02:52:57 +03:00
Nikita RakitinandCursor 5fc8aaee7c Metafile: EMF+ cardinal curves and region fills
DrawCurve, DrawClosedCurve and FillClosedCurve (GDI+ cardinal splines, the
smoothed lines of charts and freehand shapes) draw as cubic Béziers with
the record's tension, offset and segment count; FillRegion fills the region
object's area. These records were skipped, so the shapes were missing.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 02:47:47 +03:00
Nikita Rakitin b1ce243806 Spelling: notes right-click menu, Review > Language with Do Not Check Spelling, repeated words 2026-10-14 02:47:34 +03:00
Nikita Rakitin a4ed08b687 SmartArt: layout thumbnails in galleries and live preview on hover 2026-10-14 02:47:28 +03:00
Nikita RakitinandCursor 68ab3a4839 UI: Font dialog sets character formatting in one step
format.fontDialog applies family, size, bold, italic, underline, colour,
strikethrough, baseline, caps and spacing together, so one undo restores
them. With no fields it asks the UI to open the dialog, seeded from the
selection. Home › Font, the shape menu and Cmd+T open it.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 02:41:28 +03:00
Nikita RakitinandCursor 33252f28db SmartArt: Convert to SmartArt gallery on Home, Convert to Text keeps the text size
Home > Paragraph gets a Convert to SmartArt button whose menu lists every layout by category (List, Process, Cycle, Hierarchy, Relationship, Matrix, Pyramid, Picture); a click converts the selected text. Convert to Text sets the text box's titles and bullets to the sizes the graphic showed them at. Icon toggles carry their tooltip as their accessible name.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 02:34:55 +03:00
Nikita Rakitin 8bc7e55561 Spelling: squiggles in table cells and notes; UI-thread checking on the web 2026-10-14 02:34:33 +03:00
Nikita RakitinandCursor 304bf06290 Insert: Lucide icon gallery as stroked shapes
Insert › Icons places seventy Lucide 1.56.0 stroke icons as custom
geometry: no fill, round caps, and a line width scaled from the
24-unit design. The gallery searches by name. SVG paths, including
arcs, are converted when the icon is inserted so the renderer strokes
the outline.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 02:31:54 +03:00
Nikita RakitinandCursor 7764c27cc4 SmartArt: Name and Title org chart, closer Half Circle, ten more layouts, convert to and from text and shapes
Name and Title Organization Chart with a title box per node (DiagramNode.title, smartArt.setNodes title; written as the title box's presentation point text and read back). Half Circle Org Chart draws two half rings per node. New layouts: Vertical Box List, Trapezoid List, Table List, Accent Process, Continuous Block Process, Basic Bending Process, Linear Venn, Stacked Venn, Nested Target. smartArt.fromText (Convert to SmartArt), smartArt.toText and smartArt.toShapes, with a Convert menu in SmartArt Design.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 02:26:58 +03:00
Nikita RakitinandCursor b4c03f0a75 SmartArt: organisation charts with assistants, segmented and multidirectional cycles, cycle matrix, segmented pyramid, pie
Organization Chart and Half Circle Organization Chart with elbow connectors; assistant nodes (Add Assistant, written as asst points and read back) sit beside their parent on a row of their own. Segmented Cycle, Multidirectional Cycle, Cycle Matrix, Segmented Pyramid and Basic Pie. Venn labels move further out so the third circle's no longer runs into the overlap.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 02:16:40 +03:00
Nikita RakitinandCursor 06c275d136 Animations: check effect options and accept direction words
animation.add stored any `option` string as given, and the renderer reads
direction codes letter by letter, so "fromBottom" (r, t, b) flew in from the
bottom right. The option is now checked against the effect's list; direction
words ("fromBottom", "topLeft", "upRight") map to the stored codes ("b", "lt",
"ru"), and anything else is an error listing the valid options.
animation.options applies the option to each target in its own effect's terms
and leaves targets without such an option alone.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 02:15:42 +03:00
Nikita RakitinandCursor eb7e346ea1 Text: underline an IME composition in a table cell
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>
2026-10-14 02:08:14 +03:00
Nikita RakitinandCursor 00dd069678 SmartArt: six more layouts, clear Venn labels, read back older Picture Accent Process files
Text Cycle, Continuous Cycle, Horizontal Hierarchy, Grid Matrix, Gear and Funnel. Venn labels sit further out, clear of the overlaps. Files where Picture Accent Process was written as pList2 (with DeckCraft's process-category layout part) import as Picture Accent Process again. Round shapes' text shrinks to the inscribed width.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 02:07:51 +03:00
Nikita Rakitin a29e200a4e Spelling: background squiggles, Add to Dictionary, per-run languages, compounds 2026-10-14 02:05:22 +03:00
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