fix(eps): a masked gradient mesh takes the transparency after its mask

A gradient mesh with an opacity mask has its own state (`Xy`) after the
mask's dictionary, not right after its `/End X!`. The operators of the
mask's art, on `%_` lines, cleared the flag that says a mesh just ended,
so the state was read as the next object's and each masked mesh in a
run drew with the blend mode of the one before it.

The flag now goes back to what it was when a dictionary opened once it
closes, as `after_object` does.
This commit is contained in:
Don Omondi
2026-10-31 04:21:56 +07:00
committed by bflatastic
parent c9dc4fa857
commit a1fc3cfdb1
5 changed files with 34 additions and 4 deletions
+2 -1
View File
@@ -1,6 +1,6 @@
# File format parity
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-30 · **Change:** minor (`.ai`/EPS editing data: a layer's state block with the stroke style in it keeps the layer's opacity) · **Target:** Adobe Illustrator 2026 (30.x)
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-30 · **Change:** minor (`.ai`/EPS editing data: a gradient mesh with an opacity mask takes the transparency written after the mask) · **Target:** Adobe Illustrator 2026 (30.x)
Every format Illustrator opens, places, saves or exports, against VectorCraft's format table (`FORMATS`,
`OPEN_EXTS`, `PLACE_EXTS` in `crates/engine/src/cmd/fileio/formats.rs`). Illustrator's list comes from its public
@@ -132,6 +132,7 @@ the app's own editing copy of a file (an EPS after its `%%EOF`, a `.ai`'s `AIPri
| Date | Change | Summary |
|---|---|---|
| 2026-10-30 | minor | `.ai`/EPS editing data: a gradient mesh with an opacity mask takes the transparency (`Xy`) written after the mask's dictionary, as one without a mask takes the one right after its `/End X!`; the operators of the mask's art (on `%_` lines) hid it, so the state was read as the next object's and each masked mesh in a run drew with the blend mode of the one before it (a Multiply shading drawn Normal, an Overlay tint drawn Multiply over the art below). Test `import::ai::tests::a_masked_gradient_mesh_takes_the_transparency_written_after_its_mask`; checked locally against a user's files: one opens from its layers 0.1% from its page (it was 0.6%, just inside the limit), another comes 1.6% → 1.3% nearer; scores unchanged |
| 2026-10-30 | minor | `.ai`/EPS editing data: a layer's own state block (`Xy`, `Xd`, `7 () XW` before `LB`) can have the stroke style (`J`, `j`, `w`, `M`, `d`, `XR`) between its `Xy` and `Xd`; read as the art moving on, it lost the layer's opacity, so a layer at 17% drew opaque over the art under it and the file came in as its page. When the layer's last object is a gradient mesh, the mesh keeps its own state through the stroke style too (#4748). An object's own state block (`6 () XW`) still isn't the layer's. Of 408 users' files whose editing data was checked, 3 have such a block: an EPS that now opens from its layers 0.5% from its page (it was 18.8%), one whose layer now draws at 85% as its page does, and one whose layers are all at 100%; the others draw as before. Test `import::ai::tests::a_layers_state_keeps_through_the_stroke_style_written_in_it`; scores unchanged |
| 2026-10-30 | minor | EPS and `.ai` import: editing data whose type is in the legacy format (`To` … `TO`, as an EPS saved for Illustrator 10 keeps it, with no `/AI11Text` for the page's type to go in) is read through its layers when the page has text: its text objects are the layers' own, and the comparison with the page says whether the layers draw it. Before, such a file came in as its page ("its layers have no text objects to put it in"). Type the editing data keeps only as outlines (what the legacy format can't hold) stays outlines, with a note counting the page's text objects that are; a file whose layers have no text object at all still comes in as its page. Test `import::tests_native::type_in_the_legacy_format_is_the_layers_own_and_the_page_has_text`; checked locally against a user's files (of 6 such EPS that came in as their page, 3 now come in through their layers, within the comparison's limits; 1 is still refused by the comparison for art that isn't type, and 2 have their type only as outlines; no change in the other 284 EPS with editing data and 117 `.ai` files checked); scores unchanged |
| 2026-10-30 | minor | `.ai`/EPS editing data: an `Xy` right after a gradient mesh's `/End X!` is the mesh's only when its own `6 () XW` follows; when the layer's `LB` follows (directly or after the layer's `Xd` and `7 () XW`) it is the layer's, as before #4744, and the mesh keeps the state it had. Test `import::ai::tests::a_layer_keeps_its_own_transparency`; scores unchanged |