With rotateWithShape false, the renderer lays linear and radial gradients
out upright on the slide, while rectangular and path gradients still turn
with the shape. The shape.fill params doc now says so.
* Ogg: include recovered tail packets in Opus duration
Keep the existing missing-granule recovery cursor in step with the packet ends it assigns. Add a regression for a partially and entirely unanchored stream; existing valid end-trimming coverage remains unchanged.
Validation: rustc --edition=2024 --test crates/ogg/src/lib.rs: all 12 tests pass. Scoped rustfmt check passes. Full cargo --offline xtask ci is blocked before build by the uncached pinned egui checkout.
* Ogg: record recovery duration correction
* Fonts: bound font-controlled work in enumeration, outlines and carets
An embedded font could make each lookup do far more than real fonts need:
- enumerating a collection read up to 256 faces times 1024 named instances,
each then built with its own shaper; now 4096 per file across all faces,
with a set for the duplicate-style check instead of a scan;
- composite and VARC glyphs could expand one dense outline without limit,
and the outline cache only counted entries; outlines now stop at 32768
path elements (drawing nothing past it) and the cache is also bounded by
the elements it holds;
- the 64-caret limit applied after filtering, so a ligature lookup could
read every caret record; it now applies to the records read.
* address review: bound thread-local glyph cache by path elements
* render: look up a table's style once, keep the skip list as a set, count each dash
* render: index chart point fills, scatter x presence and waterfall bars once per chart
* PPTX export: index animation targets, cache a paragraph's build roles, serialize run properties once per text run
* address review: warn once when a by-paragraph build is truncated
* av1: count repeated-frame outputs as they are added
* hevc: give each slice segment its own entry-point list instead of keeping the copied one's allocation
- presentation.json gets its own 256 MiB inflation limit instead of the 2 GiB
per-entry allowance, and is parsed in place: only a file that needs its
null-number repair is copied.
- A media member that fails decoding or its CRC is charged for the bytes it
inflated, so later members cannot reuse the shared media budget.
- repair() and Presentation::validate() check slide layouts against a set
built once instead of scanning every layout per slide.
The shaper lets one call grow to 256 glyphs per input character, as an
embedded font's substitutions decide, and every glyph was then copied out.
Items longer than 1 KiB are now shaped in pieces (cut at a space where one
is near, never before a combining mark or after a joiner), each with the
rest of the paragraph as context and the item's script, and a piece that
expands past 32 glyphs per character falls back to one glyph per character
from the cmap.
* Animations: index morph matching and timeline lookups by shape
Morph pairing searched every shape of the next slide for each shape of the
current one, four times over, rebuilding shape text inside each comparison.
Timeline state looked up a shape's effects, paragraph owner and base colour
by scanning every effect, group and colour on the slide, once per shape and
paragraph drawn. Both are now indexed once, keeping the same match order.
* Animations: drop wall-clock bounds from the large morph and paragraph tests
On a loaded runner a ten-second bound can fail after every functional
assertion passed. The inputs stay large enough that a quadratic regression
hangs the test instead.
Found while testing crates/engine/src/cmd/file.rs:489 (save, with save_bytes at :341-349 and format_for_path at :440)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The round trip now also checks the written presProps.xml: inside p:showPr, the extension uri and
p14:showMediaCtrls with its namespace declared on the element; the default writes nothing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review of #1693 found that cast_effects built the picture content that a shadow,
a glow and a reflection are drawn from without converting a tiled fill to
points, so inside a scaled group the reflection of a tiled picture showed
child-space tiles while its face showed the right ones.
The content now goes through paint::tiled_picture_per_point with per_point_xy,
as the face does.
Test: a tiled picture's reflection in groups scaled 0.25, 1600 and 2x0.5 shows
the same colours as in an unscaled group; it fails without the change.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Review of #1693 found two more places that drew a tiled picture fill in the
shape's own (child-space) units inside a scaled group.
A group nested in a scaled group stored its own tiled fill unconverted, so the
members that take it (grpFill) got oversized tiles. The owning group now
converts the fill with per_point_xy when it stores it, so inheriting members,
directly or through a chain of grpFill groups, get the converted tile.
A picture shape (p:pic) whose blip fill is a tile passed its own fill straight
to paint::picture. It now goes through paint::tiled_picture_per_point, which
tiled_per_point also uses.
Tests: a group's tile passed to its members and a picture shape's own tile, each
in outer groups scaled 1, 0.25, 1600 and 2x0.5; both fail without the change.
Docs: the Picture and texture fill checklist row is re-assessed (remains P) with
its status line and revision history, and the ROADMAP progress log row mentions
both cases.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A comment card's reply row reserved a fixed 70 px for its Resolve and
delete buttons, which need more. The row overflowed the card, the pane
grew by the overflow every frame until it stuck at its widest, and
dragging its edge no longer changed it. The buttons are now laid out
first, from the right, and the reply field takes the width they leave.
A tiled picture fill (a:blipFill with a:tile) was sized in the shape's own
units. Inside a group whose child space differs from its box (old decks write
child spaces ~1800 times smaller) one tile covered hundreds of boxes, so the
fill showed a single flat texel instead of the texture.
PowerPoint's own PNG export of a synthetic probe deck shows the tile keeps its
size, offset, anchor and mirroring in slide points whatever the group's scale,
uniform or stretched unevenly, nested or flipped. The tile is now converted
from points to shape units per axis (Renderer::per_point_xy, paint::
tiled_per_point), and snapped to whole device pixels per axis.
Tiles with rotWithShape="0" are drawn in device pixels and were sized in
pixels, ignoring the zoom (even outside groups); they are now sized to pixels
first.
Tests: a tile in groups of seven scales (uniform and uneven, wide and tall
tile), and an upright tile in a turned shape at zoom 1 and 2.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/engine/src/cmd/design/master_view.rs:8 (master_view; `master` read via usize_param, `layout` at :14)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Use render_frame with timeline.steps() and t = 0.0 so the previous slide
is rendered in its final completed state during transition preview.
- Pass duration: 1000 integer ms in test to explicitly test the requested duration.
Found while testing crates/engine/src/cmd/file.rs:362 (pdf_options) with crates/pdf/src/lib.rs:364-371 (handout_boxes)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- When Preview is clicked on the Transitions ribbon, initialize Show with
start_transition_preview from the prior slide into the selected slide
(or from black for slide 0).
- If tr.old is unset for a non-part transition with tr.from, render the
previous slide texture on the first frame so the transition blends cleanly.
- Indicate active playback on the Preview button while previewing.
- Regression tests for transitions from previous slide and from black on slide 0.
PowerPoint stores Show media controls as the p14:showMediaCtrls extension inside
p:showPr (uri {2FDB2607-...}); absent means shown. Write it when hidden, read it back.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/format/src/rtf.rs:301-326 (symbol / text, reached via escape)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
/// PowerPoint's slide show magnifier goes up to 400%.
constWHEEL_ZOOM_MAX: f32=4.0;
pub(super)constGRID_CAP: usize=48;
pub(crate)constGRID_CAP: usize=48;
constTOOL_BAR_W: f32=520.0;
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.