Skip to content

.ai save: text wrap fixes for cut-away clipping fills and symbols without room - #7466

Merged
bflatastic merged 6 commits into
storytold:mainfrom
dotCooCoo:fix/ai-wrap-options-edge-cases
Nov 14, 2026
Merged

bflatastic merged 6 commits into
storytold:mainfrom
dotCooCoo:fix/ai-wrap-options-edge-cases

Conversation

@dotCooCoo

Copy link
Copy Markdown
Contributor

What and why

Two faults in the .ai editing-data writer's text wrap handling, a follow-up to #7319.

  • A clipping path whose fill is cut away lost its text wrap options. Inside art cut to an outer clipping object, a clipping path is written as its fill and its stroke, and its options go with the fill. clip_contents (crates/eps/src/ai_editing/writer.rs:1041) removed them from the stroke whenever the path had a fill, before knowing whether the fill wrote anything. When the outer object cut the fill away entirely, nothing carried the options. The stroke now drops them only when the fill writes an object, counted with the writer's object count rather than the text length, since a lock or hide state line can be written without an object.
  • A symbol definition without room under the object limit corrupted the drawn-art counter. define_symbol clears drawn while it writes a definition and restores it on every exit except the one where take_objects(1) fails (crates/eps/src/ai_editing/writer/symbols.rs:233). A live instance inside drawn art, such as a stained instance's art, then returned with the counter at zero, and the art around it subtracted from zero at crates/eps/src/ai_editing/writer.rs:714: a panic in a debug build, a wrapped counter otherwise. That exit now restores it as the others do.

How it was tested

New tests in crates/eps/src/ai_editing/tests.rs, each shown failing without its fix:

  • a_clipping_path_written_as_its_paint_keeps_one_text_wrap gains a case: an outer clipping object ending at x = 100 and a clipping path whose fill starts at x = 101 with a 4 pt stroke, unlocked and locked. The saved file has the options once and they are read back on the stroke. Without the fix the count is 0; with a text-length check the locked case fails.
  • a_definition_without_room_inside_drawn_art_is_left_out: a stained instance whose symbol's art holds a live instance, exported with room for every count of objects below what it needs. Each export warns about the limit and stays within it. Without the fix it panics with "attempt to subtract with overflow".

Focused checks on Linux. The branch is one commit on main at 1e4e3534f5 and merges cleanly with it and with open #7268, #7254, #7394 and #7425, which also change writer.rs.

  • cargo test -p vectorcraft-eps --lib -- ai_editing: 262 passed.
  • cargo clippy -p vectorcraft-eps --all-targets -- -D warnings: no warnings.
  • cargo fmt --all -- --check reports only crates/svg/src/lib.rs:491, which this branch does not touch; it is unformatted on main at 1e4e3534f5, and open fmt: format crates/svg/src/lib.rs #7400 formats it.
  • cargo xtask ci runs in this pull request's CI.

Checklist

  • cargo xtask ci passes (fmt, clippy, tests, assets, brands, layers, wasm).
  • No panics in shipped code: no unwrap(), expect(), panic!, unreachable!, todo! or
    unimplemented! outside tests, and no unchecked indexing on data from files, parameters or
    messages. Errors are returned as Result and shown to the user
    (why and how).
  • Clean-room: nothing copied from Adobe products or GPL/AGPL code (AGENTS.md).
  • Every new asset has a row in ASSETS.md.

…hout room

Two faults in the editing data writer's text wrap handling:

- A clipping path inside art cut to an outer clipping object is written
  as its fill and its stroke. The stroke's text wrap options were
  dropped whenever the path had a fill, so when the outer object cut
  the fill away entirely, the stroke was written without them and the
  options were lost. The stroke now drops them only after the fill
  writes an object.
- When a symbol definition had no room left under the object limit,
  `define_symbol` returned without restoring the drawn-art counter it
  had cleared. A live instance inside drawn art (a stained instance's
  art) then left the counter at zero, and the art around it subtracted
  from zero: a panic in a debug build. That path now restores the
  counter as the other exits do.
@coderabbitai

coderabbitai Bot commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 17 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

Learn how review limits work.

Review configuration:

Run configuration

Commits

Reviewing files that changed from the base of the PR and between 67f6d3a and 37f06a8.

Files selected for processing: 1

  • crates/eps/src/ai_editing/tests.rs
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@bflatastic
bflatastic merged commit 3ccafde into storytold:main Nov 14, 2026
7 checks passed
@bflatastic

Copy link
Copy Markdown
Member

Merged, thanks @dotCooCoo! It passed its CI checks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants