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>
An off-centre radial gradient ("from corner", or any fillToRect focus
other than the middle) spread from its focus out to the farthest corner,
so the near side stayed light. Fitted to PowerPoint's export: the first
stop is a point at the focus and the last is the circle through the box's
corners (centre of the box, half its diagonal), with the circles between
moving from one to the other (a two-point radial). A corner focus thus
reaches its last colour at its own corner too. Centred gradients are
unchanged.
Wild synthetic set: off-centre radial background 20.66 -> 1.22, radial
focus grid 6.34 -> 5.69.
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>
"Z̴̡̛͓a̸̧̘l̵̩g̶̞o̸̤" in an Aptos run drew its marks as missing-glyph boxes: no face in the chain
covered the whole cluster and the fallback for its base letter neither, so the run's own font was
kept. PowerPoint draws the marks stacked. A loaded plain face that covers the whole cluster is
now taken before falling back to the run's font. w09-scripts s1 8.40 -> 7.86.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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>
The strikethrough was drawn 0.3 em above the baseline, 0.05 em thick, for every font. PowerPoint
uses the font's own strikeout metrics (OS/2): Arial 96 pt strikes rows 347-351, 24.8 px above the
baseline (530/2048 em) and 4.8 px thick; DeckCraft drew 343-347. Faces now carry their strikeout
metrics (0.26/0.05 em when a font has none) and the line matches PowerPoint's rows exactly.
w14-xml s11 4.06 -> 3.24.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The previous change sent every text-presentation pictograph to a symbol font, which also moved
bullets such as "▪" (Wingdings substitutes) from the face they had to a wider one: necc-
presentation-0 s13 18.78 -> 19.72. Now a pictograph is redirected to a plain face only when its
fallback would be the colour emoji font; keycaps and U+FE0E sequences still take a plain face.
necc s12-s14 back to 26.38 / 18.78 / 20.91; w14-xml s7 (pictographs) 9.79 -> 7.49 overall.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A wider probe (Arial, Aptos, Calibri, Segoe UI, Times New Roman, Verdana at 40 pt, each box with
one paragraph spaced 2 pt) shows the earlier rule holds for Arial alone: Calibri, Segoe UI and
Times New Roman keep "AVATAR" kerned beside and inside spaced runs (121 vs 131 px for Calibri).
The rule made spaced Aptos and Calibri text too wide (w15-mixed s9 5.46 -> 7.86), so it is
removed; Arial's behaviour stays a known difference.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Line height and baseline were the largest over every face on the line, fallback faces included,
so a line with an emoji, a math symbol or Thai in an Aptos run sat 1-5 px lower than PowerPoint's
and pushed the lines below it down. PowerPoint keeps the run's own font metrics (measured: the
second line of six boxes starts at the same height whatever the first line holds). Faces that are
the run's Latin, East Asian, complex-script or symbol font still count.
w14-xml s8 (baselines) 5.54 -> 3.21, w09-scripts s1 10.27 -> 8.39, s2 9.37 -> 7.46,
w15-mixed s8 13.65 -> 8.77; w15-mixed s2 (Arabic) 6.57 -> 7.05.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Observed on PowerPoint's export of pictographs in Aptos, Arial and Segoe UI:
- characters that default to emoji presentation draw in colour without a selector: ⭐✅☔⌚⏩
and the other BMP Emoji_Presentation characters (DeckCraft only knew the supplementary-plane
ones and drew ⭐✅ as text);
- text-presentation pictographs (⚠ ♥ ✔ ☎ ⬆ ➡ ▶ ⤴) draw as text even where the colour font is the
first installed font that has them: they now come from a plain symbol font, symbol families
first, never the colour one; and a symbol after an emoji no longer inherits its colour face;
- keycap sequences ("1️⃣", "#⃣") draw as text, an outlined key, not the colour keycap.
w14-xml s7 (pictographs) 9.79 -> 6.16, w09-scripts s1 (emoji) 11.56 -> 10.27.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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>
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 scheme other than the Latin, Roman and circled ones drew Arabic digits ("4." for
ea1ChsPeriod, "- 10 -" for arabic2Minus). Each is now written as PowerPoint's export draws it
(probe deck: one box per a:buAutoNum type and start value): Chinese numerals for ea1Chs/ea1Cht
(十, 十一, 二十一), digit-by-digit kanji with 〇 for ea1Jpn* (一〇), full-width digits for
arabicDb*, a full-width full stop after the East Asian ones, Thai letters (without ฃ ฅ ฆ) and
digits, Devanagari vowels, consonants and digits, the Arabic alphabet (arabic1Minus) and abjad
(arabic2Minus) and the Hebrew alphabet with a hyphen, and the Wingdings-style circles that go to
ten (circleNumWdWhite 13 → ③, circleNumWdBlack → ❶…). w04-lists s2-s4 drew wrong labels in 24 of
36 boxes.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Observed on PowerPoint's export of a wrapped Japanese paragraph (24 pt, 11 characters a line):
it breaks "けません(禁則処" / "理)。ー長音もで" / "す。っゃゅょ小書き文字", i.e. small kana
(っゃゅょ…), the prolonged sound mark and iteration marks never start a line (strict kinsoku),
where UAX #14's default allows it. And "し、句読点「、」や" / "「。」は…": with hanging punctuation on,
a closing bracket that overflows does not hang; only the ideographic comma and full stop (and
their full-width and half-width forms) do.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Observed on PowerPoint's export of long joined words:
- a line broken at a soft hyphen (U+00AD) ends with a visible hyphen ("Softhyphenatedwordsina-");
DeckCraft broke there but drew nothing. The hyphen now takes its room on the line;
- PowerPoint does not break after a zero-width space (it splits the word where it overflows
instead), where UAX #14 allows a break;
- an em dash ends a line but never starts one ("Em—dash—joined—" / "words—that—are—long—"),
where UAX #14 allows a break before it too.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Follow-up to the kerning rule: on the real corpus (ms6: titles condensed by 1 pt from the
master's title style) PowerPoint kerns condensed text, and a closer probe agrees for -0.6, -1,
-1.5, -2 and -3 pt (only -1.2 and -2.5 pt came out unkerned, which no simple rule explains). Only
spacing out by 0.6 pt or more now switches kerning off for the box. ms6 slides 2/7: 4.97 -> 6.44
-> back to 4.97, 7.05 -> 8.10 -> 7.05.
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>
Tab stops were all left stops: a:tab/@algn was read and saved but ignored. As PowerPoint draws
them, the text after a tab (up to the next tab or line break) now ends at a right stop, is
centred on a centre stop, and has its first "." on a decimal stop (text without one ends there);
when that text is wider than the room before the stop it starts where the tab is, never further
left. Measured on PowerPoint's export: "right" ends at 180 pt, "12.5" and "1234.567" put the
point on the stop, "12,5" and "nodot" end at it.
A tab whose stop lies past the end of the line now starts the next line, so the text after it
sits on that line's first stop, as PowerPoint wraps "abcdefghij<tab>k<tab>l<tab>m…".
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A run's solid fill with a:alpha was resolved into the glyph colour's alpha and also kept as the
run's fill opacity, and the renderer multiplied both: text at 60 % transparency drew at 16 %
opacity instead of 40 %. The colour now carries the transparency alone. PowerPoint's export of
"Transparent 60% text" (red) is a light red that now matches.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Small capitals were drawn at the full size of the run's first character: glyph runs grouped
cells by style and face only, so "HxHx" drew every letter at the capital's size on the small
capitals' narrower advances (letters overlapped). A lowercase letter in small caps now starts a
run of its own at 80 % (PowerPoint's small capital "X" is 0.81 of the capital "H" in Arial).
All caps and small caps mapped "ß" to "S" (the first character of "SS"); PowerPoint leaves a
character whose capital is a sequence as it is ("ß", "fi", "ʼn"), and maps the rest one to one.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
PowerPoint kerns pairs (a:rPr/@kern) only while no run of the text body is spaced out by 0.6 pt
or more or condensed by 1 pt or more; then no run of that box is kerned, even runs without
spacing. Measured on Arial 40 pt "AVATAR": spacing 0, 0.01, 0.5, -0.6 and -0.99 pt keep the pairs
(146 px wide), 0.6, 0.8, 1, 1.5 and -1 pt drop them in every paragraph of the box (158 px plus the
spacing). DeckCraft kerned spaced titles, making "AVATAR"-like words 12 px too narrow at 40 pt.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
PowerPoint does not resolve neutral characters with plain UAX #9: the language of each run
(a:rPr/@lang) decides. Measured with every space highlighted in its own colour:
- in a run of a left-to-right language (or none) punctuation and digits are left to right and a
space takes the direction of the character before it, so "abc HE1 HE2 def" shows the space after
the Hebrew words on their left, and an English sentence in an RTL paragraph keeps its full stop
at its end;
- in a Hebrew/Arabic run, neutrals between text of one direction take it, all others are right
to left, and digits are a number in the right-to-left text unless left-to-right text precedes.
Paragraphs with explicit embeddings keep the full algorithm. Bidi probe deck: mean diff 11.1 ->
10.0 on the four mixed-direction slides; corpus poi 6.660 -> 6.654, others unchanged.
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>
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.
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.
* Engine: file.info and PowerPoint-style print slide ranges (#76)
file.info reports what File › Info shows (name, path, format, unsaved
changes, slide and hidden-slide counts, sections, size on disk,
properties). file.export's PDF `slides` also takes the range typed in
PowerPoint's Print page ("1-3, 5", 1-based); bad or out-of-range text is
an error instead of a silent full export.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* UI: the File tab (Backstage) like PowerPoint's (#76)
File (first ribbon tab) or Alt+F opens a full-window view in place of the
ribbon, slides and status bar: a side menu (Back, Home, New, Open, Info,
Save, Save As, Print, Export, Close; Account and Options at the bottom)
and the chosen page. Esc or Back returns; Up/Down walk the side menu and
show each page as it gets the focus; Enter runs Save/Close/Options.
Laid out after PowerPoint for Windows as observed: 160-pt menu a step
darker than the page, outline icons, current page in the accent colour.
The start screen is now File › Home (as in PowerPoint), with only Home,
New and Open at the top and no Back. Pages call existing commands and
file helpers: file.new {theme} and the sample deck (Home, New); recent
files with search, Browse and Recover Unsaved (Open); file.info and
file.properties, Accessibility Checker, Revert (Info); file.save /
file.saveAs / file.export by type (Save, Save As); a PDF with the Print
page's slides, layout (full page, notes, handouts 1-9), hidden slides and
frames, opened in the system viewer or downloaded on the web, with a
page preview (Print, Ctrl+P); Create PDF, Create Handouts and Change File
Type (Export); appearance and About (Account); Preferences (Options).
Share (cloud) is left out.
Close and Ctrl+W now ask Save / Don't Save / Cancel about unsaved
changes instead of closing at once. The Export dialog shares
SlideApp::export_as with the Export page. New UI commands: app.backstage
{page}, app.closePresentation, app.print; ui.inspect reports the page.
New icons drawn in code: back, save as, account, recent, new file, open
folder.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Docs: File tab (Backstage) in ui-parity, gaps, checklist and progress log (#76)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Outlines, dashes, arrowheads and ink strokes were drawn under the full
transform, including the mapping of the group's child coordinate space onto its
box. A group whose children use small legacy child coordinates (scale ~1600)
therefore stroked 0.75 pt lines about 1200 pt wide and covered the slide. Inside
a group the outline is now carried through that mapping and stroked under the
slide-level view, so the line width, dash lengths and arrowhead sizes stay in
points, also for groups scaled unevenly.
* ActiveX controls show their pictures
A slide's p:controls are read: each control with a p:pic (the image PowerPoint shows for it,
often a WMF) becomes a picture above the slide's shapes.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Metafiles draw their text, pattern and hatch brushes
deckcraft-metafile (still kurbo + thiserror only, so it builds for wasm):
- Text: WMF EXTTEXTOUT/TEXTOUT and EMF EXTTEXTOUTW/EXTTEXTOUTA/SMALLTEXTOUT with the
selected font (CREATEFONTINDIRECT, EXTCREATEFONTINDIRECTW: face, signed LOGFONT height,
width, weight, italic, underline, strike-out, escapement, charset), text and background
colour, background mode, TA_* alignment and TA_UPDATECP, the dx array (ETO_PDY pairs too),
ETO_OPAQUE fills and ETO_CLIPPED clips. 8-bit strings decode through their charset
(Windows-1252/1250/1251; symbol fonts keep their codes at U+F000; double-byte sets keep
their advances). The neutral Item::Text carries a text-space-to-picture transform, so the
mapping and escapement are folded in and glyphs are never mirrored.
- Brushes: WMF DIBCREATEPATTERNBRUSH, EMF CREATEDIBPATTERNBRUSHPT and CREATEMONOBRUSH, and
BS_HATCHED, as Item::Pattern tiles in 96-dpi pixels; WMF PATBLT. The XOR / AND-pattern /
XOR see-through shadow of old PowerPoint WMFs draws its pattern in the XOR colour.
- MFCOMMENT escapes with an embedded EMF are ignored: PowerPoint draws the WMF's records.
- Pattern pixels and text count against the byte budget; strings are capped.
deckcraft-render draws text through deckcraft-fonts with the face slide text would use
(document_face), symbol fonts mapped as bullets map them (deckcraft_text::symbol_char, now
public, with Webdings), per-character fallback, the file's advances, GDI cell metrics for
top/bottom alignment, underline/strike-out and synthetic bold/italic. Tiles below 1.5 output
pixels per cell are drawn as their average colour.
On the 24 corpus slides that show a metafile, mean abs diff against PowerPoint goes from
28.31 to 5.06 (with the OLE/ActiveX preview commits).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Text: Ctrl+arrows, Ctrl+Backspace/Delete and the other text keys work like PowerPoint (#268)
Observed black-box in PowerPoint for Windows on synthetic text:
- Word stops (crates/model/src/words.rs): words, punctuation runs, symbol
runs, tabs, line breaks and each CJK character are tokens; trailing spaces
join the token before. it's, a-b, 3.14, 1,000 are one word; e.g., a_b and
x@y.com are not. Grapheme clusters never split.
- Ctrl+Left/Right and Ctrl+Shift+Left/Right move by those stops, across
paragraphs; with a selection they go on from its start/end. In a
right-to-left paragraph Left and Right swap.
- Ctrl+Backspace deletes to the previous stop; Ctrl+Delete deletes the rest
of the word, or spaces plus the next word, then applies PowerPoint's smart
spacing. With a selection both work from its start.
- Ctrl+Up/Down by paragraph, Ctrl+Home/End to the text's ends.
- End on a wrapped line goes past the trailing space and the caret stays
drawn at that line's end (TextSel::line_end); End again stays, Home
returns to the same line.
- Ctrl+]/[ and Ctrl+Shift+>/< change font size (egui's Period/Comma/
bracket key names now match registry shortcuts).
- Shift+F3 cycles lower -> Title -> UPPER; a caret changes its word.
- Double-click selects the word without trailing spaces; triple-click
includes the paragraph mark.
- Mac keeps Option for words and Cmd for line/text ends (Session::mac_keys).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* rustfmt
* Canvas: one caret, drawn at a wrapped line's end after End
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* #133: Selection pane engine: restack inside groups, Show/Hide All, Lock like PowerPoint
- arrange.bringForward/sendBackward/bringToFront/sendToBack and arrange.reorder work on a
group's children, which stay in their group (as PowerPoint's pane arrows and drag do);
steps that change nothing leave no undo step.
- selection.select (pane click: Ctrl toggles, children and top-level objects don't mix,
picking a hidden object shows it), selection.showAll (everything, children too) and
selection.hideAll (top level).
- shape.lock cascades through groups; locked objects can be selected, formatted and typed
in, but not moved, sized, rotated, flipped, reshaped or cropped (commands and canvas).
- PPTX: Lock reads and writes PowerPoint's full locking attribute set per element kind
(observed by saving locked objects from PowerPoint); partial locks aren't Lock.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Front-most first with groups folding; drag a row to restack among its siblings (accent
insertion line); Bring Forward / Send Backward arrows; Show All / Hide All; per-row eye and
padlock; double-click or F2 renames in place; Ctrl+click toggles, Shift+click selects a run;
arrows, Home, End and Esc in the list; right-click menu. Lock/Unlock on the canvas menu,
greyed handles on locked objects. egui_kittest tests drive the pane.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Text: input method composition as commands, one undo step per composition (#101)
text.compose shows an input method's preedit in place at the insertion point and replaces it on
each update; an empty preedit cancels and restores the text and selection. text.commit replaces
the composition with the result as one undo step. Any other edit, key or click settles an open
composition first. The composition is underlined under the baseline (thicker under the part being
converted), and the caret line is measured for empty placeholders too.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* UI: Korean, Japanese and Chinese input and interface text (#101)
The slide turns the input method on while it takes typing, with the candidate window at the
caret, and forwards egui Ime events to text.compose / text.commit, so a Korean keyboard composes
syllables instead of separate jamo. Interface text in scripts the interface fonts lack (Hangul,
Simplified Chinese, Thai...) borrows faces from the font database (installed fonts such as Malgun
Gothic; nothing bundled): file names, titles, notes, outline, sections, comments and typed text.
Ported and widened from WordCraft's #565/#840 fallback. The notes pane keeps text typed before
focus leaves in the same frame (Escape, another slide). Control channel: ui.ime.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
PowerPoint's Normal view draws shapes, pictures and text that sit partly
or wholly off the slide on the area around it, at full strength, with
their effects, master and layout graphics included; the slide show,
exports and thumbnails clip to the slide. DeckCraft clipped everything to
the slide in the editor too.
- render: `slide_extent`/`layout_extent` estimate how far a slide's
drawing reaches (boxes, outlines, shadow, glow, reflection);
`render_slide_drawn` also reports what a render actually drew (text
spilling out of its box, table rows that grew); `pasteboard_region`
picks the pixels the editor renders: the slide plus what reaches off
it and is in view, rounded to 256 px tiles so scrolling rarely
re-renders. A slide with nothing off it renders exactly as before.
- ui-egui: the canvas texture covers that region (slide and master
views); it re-renders only when the slide, zoom or the region changes,
and a second time only if text drew beyond the estimate.
- Hit testing, selection, marquee and moves already worked in slide
space; tests now cover them off the slide.
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Text: a missing font is drawn in Calibri, as PowerPoint does
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Fonts: Windows family names find their faces; PowerPoint's twins for missing fonts
"Segoe UI Semibold", "Arial Black" and the like are the faces' Windows (GDI) family
names; a family's installed files now load together; Liberation Sans and Serif draw as
Arial and Times New Roman when missing, as PowerPoint draws them.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Fonts: Office cloud fonts (Aptos…) keep their open substitute
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
lineInv, nonIsoscelesTrapezoid, pieWedge, the left-right / up-down / quad
arrow callouts, circularArrow / leftCircularArrow / leftRightCircularArrow,
the four curved arrows, swooshArrow, callout1-3, accentCallout1-3,
borderCallout2-3, accentBorderCallout1-3, ellipseRibbon / ellipseRibbon2,
leftRightRibbon, flowChartOfflineStorage, gear6 / gear9, funnel, the corner
tabs (corner, square, plaque) and chartX / chartStar / chartPlus no longer
fall back to plain rectangles.
Each outline is our own construction in crates/geom/src/preset/extra.rs,
fitted black-box against PowerPoint renders of synthetic probe decks at
default, changed and extreme adjust values and several aspect ratios
(outline within ~1pt on 300-480pt shapes). Tests cover catalog presence,
hostile sizes/adjusts and measured outline points.
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>