From 600ce68bc7d69481c588120cf3c883f04317d1f4 Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Sat, 7 Nov 2026 12:28:17 -0800 Subject: [PATCH 1/3] Docs: only filled even-odd paths lose their live effects in a saved .ai A stroke-only path or compound path that uses the even-odd rule keeps its live effects in the editing copy; the art-style writer leaves out only paths that fill by the even-odd rule. --- README.md | 2 +- ROADMAP.md | 2 +- docs/gaps.md | 2 +- docs/roadmap.md | 2 +- docs/target-app-parity.md | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3a34bb7f99..d71e5b23af 100644 --- a/README.md +++ b/README.md @@ -253,7 +253,7 @@ The scores are self-assessed from our code against public documentation; [target-app-parity.md](docs/target-app-parity.md#how-this-was-measured-2026-10-10) explains how far to trust them. **What's missing:** -- reliable exchange of .ai files (layer structure in real files; the editing copy a save writes keeps live effects only on paths, compound paths and groups that qualify (at most a fill and a stroke, a non-zero fill rule, no large canvas) and whose appearance and effects the art-style writer supports (see [docs/file-format-parity.md](docs/file-format-parity.md)), leaves out other objects' effects other than geometry effects, and writes live objects as their art); +- reliable exchange of .ai files (layer structure in real files; the editing copy a save writes keeps live effects only on paths, compound paths and groups that qualify (at most a fill and a stroke, a non-zero fill rule when filled, no large canvas) and whose appearance and effects the art-style writer supports (see [docs/file-format-parity.md](docs/file-format-parity.md)), leaves out other objects' effects other than geometry effects, and writes live objects as their art); - an interaction-fidelity pass covering every tool's modifiers and small behaviours; - 3D and Materials beyond the initial live Revolve (Extrude & Bevel, Inflate, Rotate, materials); - filter thumbnails and a preview area inside the Effect Gallery (the gallery itself and all 57 Photoshop-style raster filters, approximated, are in); diff --git a/ROADMAP.md b/ROADMAP.md index 3f2882bc4b..0f9267e0e3 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -24,7 +24,7 @@ and the work list in [`docs/gaps.md`](docs/gaps.md). **Why alpha:** the core workflows exist end to end (drawing and path editing, Pathfinder, paint and appearance, type, SVG/PDF/EPS, print, export) and feature depth is ~75%, but a professional can't yet switch: Illustrator's own `.ai` files open with a wrong layer structure in real cases and are saved back with an editing copy that -keeps live effects only on paths, compound paths and groups that qualify (at most a fill and a stroke, a non-zero fill rule, no large canvas) and whose appearance and effects the art-style writer supports (see [docs/file-format-parity.md](docs/file-format-parity.md)), and writes live objects as their art, the interaction details have never been checked side by side, and some machines fail to start the +keeps live effects only on paths, compound paths and groups that qualify (at most a fill and a stroke, a non-zero fill rule when filled, no large canvas) and whose appearance and effects the art-style writer supports (see [docs/file-format-parity.md](docs/file-format-parity.md)), and writes live objects as their art, the interaction details have never been checked side by side, and some machines fail to start the app. Beta needs those closed (the beta list in [gaps.md](docs/gaps.md)). It passes the core-workflow gate: all six core workflows (path drawing and editing, paint and style, type, layers/artboards/export, print production, file exchange) work end to end on macOS with save and reopen, and only the last is partial, without diff --git a/docs/gaps.md b/docs/gaps.md index e09887bc87..e5e57ebd77 100644 --- a/docs/gaps.md +++ b/docs/gaps.md @@ -204,7 +204,7 @@ from G14 and the budget run of G15: **~170–270 h** one agent, ~50–80 h wall path's own Calligraphic brush settings, and symbols as live objects (#637; plain art styles read Drop Shadow, Outer Glow and Feather as live effects; pattern fills and global colours are read since #1025, placed (linked) files since #1264). A PDF-compatible `.ai` carries an editing copy of the art in the form VectorCraft's reader reads (layers, groups, paths, colors, gradients, patterns, images, transparency, opacity masks, clipping, type as text and symbols), with live effects kept only on paths, compound paths and groups that - qualify (at most a fill and a stroke, a non-zero fill rule, no large canvas) and whose appearance and effects the art-style writer supports, other objects' effects other than geometry effects left out, and live objects written as their art + qualify (at most a fill and a stroke, a non-zero fill rule when filled, no large canvas) and whose appearance and effects the art-style writer supports, other objects' effects other than geometry effects left out, and live objects written as their art ([file-format-parity.md](file-format-parity.md)). Save As `.ai` › Version: Legacy (version 7) writes the PostScript form from the published version 7 specification, keeping layers (names, order, visibility, lock), groups, compound paths, clipping groups, gradients and diff --git a/docs/roadmap.md b/docs/roadmap.md index 1c177d2946..d01c002ae4 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -89,7 +89,7 @@ Checked 2026-10-10 from the code, tests and open issues; no workflow fails, so V | Set type: point and area type, Character and Paragraph styles, threading, outlines | yes | type core 80%; styles, threading, Create Outlines and font matching tested ([type-parity.md](type-parity.md)); justification options missing (not blocking) | 0 | | Organise layers and artboards and export assets (Export for Screens, SVG, PNG, PDF per artboard) | yes | Layers panel rework, Artboards panel and tool, Export for Screens and Asset Export done; Art Optimized supersample closes ghost borders (#983 / #1037) | 0 | | Print production: CMYK and spot colour, bleed and marks, PDF/X out, separations preview | yes | PDF/X-1a/3/4, presets, marks and bleed, ICC output intent, Separations Preview, Print with PostScript output | 0 | -| Exchange files with Illustrator users: open their `.ai`/EPS/PDF, hand back a file they can open | partial (doesn't block alpha) | `.ai`, EPS and PDF open as editable art, but real files can get the wrong layer structure (#951); Save As `.ai` is PDF-compatible with an editing copy of the art (layers, groups, paths, colors, gradients, patterns, images, transparency, opacity masks, clipping, type as text and symbols, with live effects kept only on paths, compound paths and groups that qualify (at most a fill and a stroke, a non-zero fill rule, no large canvas) and whose appearance and effects the art-style writer supports ([file-format-parity.md](file-format-parity.md)), other objects' effects other than geometry effects left out, and live objects written as their art; #868), or legacy version 7, which keeps layers, groups and type as text, one artboard per file, and waits for users' testing. EPS legacy mesh corners, vector opacity masks and raster print-page comparison now preserve editable art under synthetic regressions. This is the beta main-format gap ([gaps.md](gaps.md) G9) | 10–20 (for beta) | +| Exchange files with Illustrator users: open their `.ai`/EPS/PDF, hand back a file they can open | partial (doesn't block alpha) | `.ai`, EPS and PDF open as editable art, but real files can get the wrong layer structure (#951); Save As `.ai` is PDF-compatible with an editing copy of the art (layers, groups, paths, colors, gradients, patterns, images, transparency, opacity masks, clipping, type as text and symbols, with live effects kept only on paths, compound paths and groups that qualify (at most a fill and a stroke, a non-zero fill rule when filled, no large canvas) and whose appearance and effects the art-style writer supports ([file-format-parity.md](file-format-parity.md)), other objects' effects other than geometry effects left out, and live objects written as their art; #868), or legacy version 7, which keeps layers, groups and type as text, one artboard per file, and waits for users' testing. EPS legacy mesh corners, vector opacity masks and raster print-page comparison now preserve editable art under synthetic regressions. This is the beta main-format gap ([gaps.md](gaps.md) G9) | 10–20 (for beta) | Hindi interface follow-up (2026-11-06): the catalog and zero/one plural rule are implemented; native wording review, layout checks and a web Devanagari font remain. [Notes](localization-hi.md). diff --git a/docs/target-app-parity.md b/docs/target-app-parity.md index 04feefc13e..9710d9e168 100644 --- a/docs/target-app-parity.md +++ b/docs/target-app-parity.md @@ -201,7 +201,7 @@ dominate; 3D, graphs and automation are specialist). They sum to 105. Feature de | Image Trace, graphs, image tools | 3 | 75% | graph Column designs, Image Trace Create Strokes depth (Create Object Mosaic is done; junction-returning piece survival has source-generated regressions in `image-trace-quality.md`; large images trace with a warning; Auto Color keeps rare distinct colours) | 5–8 | estimated (raised from 72%); quick presets reveal adjustment controls, Properties reopens them | | Layers, artboards, document setup | 5 | 78% | Selected-artboard deletion is consistent across panel actions (all-selected retains artboard 1); history prunes removed indices while preserving valid multiselection; remaining: 30.0's artboard locking and colours and managing artboards from the canvas, Layers panel row context menus and Collect for Export (click-to-fit objects is done, #1227) | 5–8 | estimated (lowered from 82%: target moved); Artboard deletion keys keep artwork and the first of an all-selected set; Artboard Options' Show Center Mark and Show Cross Hairs draw on the canvas only (exports and print leave them out), regression-tested; Artboard Options' Show Video Safe Areas and Video Ruler Pixel Aspect Ratio (per artboard, native format) are done ([video display options](#evidence-what-ships-today-by-area)), score unchanged | | View & navigation | 3 | 70% | multiple windows and the rest of Arrange (Cascade, Float in Window, Float All in Windows) | 9–14 | estimated; Window › Arrange › Tile and Consolidate All Windows done (score/hours unchanged); document-tab artwork hover/copy and lossless transfer tested (2026-10-22; score/hours unchanged); cached canvas reprojection preserves scale during resize, rotation and DPI changes (regression and contributor original-file evidence below; scores/hours unchanged); cached canvas dimensions match the renderer limit before cache-key creation, view construction and worker submission (regression evidence below) | -| File formats | 6 | 75% | `.ai` files open with a flattened or wrong layer structure in real cases (#951), a saved `.ai`'s editing copy without live effects on objects other than paths, compound paths and groups that qualify (at most a fill and a stroke, a non-zero fill rule, no large canvas) and whose appearance and effects the art-style writer supports, and with live objects as their art (#868), FreeHand/CorelDRAW/DWG/HEIC import, 3D export; see [file-format-parity.md](file-format-parity.md); EPS legacy mesh/opacity-mask and raster comparison follow-up verified | 10–20 | estimated (lowered from 85%: open issues); DXF control-point SPLINE import closure regression-tested (#1299 follow-up after #1320); PDF writer metadata, reader streaming and immutable backend checks in `crates/pdf/src/tests.rs`, `crates/pdf/src/tests/reader_streaming.rs` and `xtask/src/pdf_deps.rs`; PDF Place and clipboard paste retain live text (synthetic regressions); EPS ordinary Save retains the page frame and editable document (2026-10-26); `.ai`/EPS editing data checked against a user's files (2026-10-30): case setting (`ate::tests`, `tests_native::type_from_the_text_document_keeps_its_case_setting`), placed-file placements (`tests_native::a_small_placed_file_goes_where_it_draws_closer_to_the_page`), pages cropped to the art (`tests_native::type_on_the_copies_of_a_page_cropped_to_the_art_is_read_once`), mesh corner weights and state (`ai::mesh::tests::corners_with_handle_weights_of_zero_are_read`, `ai::tests::a_gradient_mesh_takes_the_transparency_written_after_it`), type on a path spacing (`tests_native::type_round_a_circle_is_spaced_as_the_file_lays_it_out`), blend state (`ai::tests::a_blends_transparency_follows_its_record`); scores and estimates unchanged. | +| File formats | 6 | 75% | `.ai` files open with a flattened or wrong layer structure in real cases (#951), a saved `.ai`'s editing copy without live effects on objects other than paths, compound paths and groups that qualify (at most a fill and a stroke, a non-zero fill rule when filled, no large canvas) and whose appearance and effects the art-style writer supports, and with live objects as their art (#868), FreeHand/CorelDRAW/DWG/HEIC import, 3D export; see [file-format-parity.md](file-format-parity.md); EPS legacy mesh/opacity-mask and raster comparison follow-up verified | 10–20 | estimated (lowered from 85%: open issues); DXF control-point SPLINE import closure regression-tested (#1299 follow-up after #1320); PDF writer metadata, reader streaming and immutable backend checks in `crates/pdf/src/tests.rs`, `crates/pdf/src/tests/reader_streaming.rs` and `xtask/src/pdf_deps.rs`; PDF Place and clipboard paste retain live text (synthetic regressions); EPS ordinary Save retains the page frame and editable document (2026-10-26); `.ai`/EPS editing data checked against a user's files (2026-10-30): case setting (`ate::tests`, `tests_native::type_from_the_text_document_keeps_its_case_setting`), placed-file placements (`tests_native::a_small_placed_file_goes_where_it_draws_closer_to_the_page`), pages cropped to the art (`tests_native::type_on_the_copies_of_a_page_cropped_to_the_art_is_read_once`), mesh corner weights and state (`ai::mesh::tests::corners_with_handle_weights_of_zero_are_read`, `ai::tests::a_gradient_mesh_takes_the_transparency_written_after_it`), type on a path spacing (`tests_native::type_round_a_circle_is_spaced_as_the_file_lays_it_out`), blend state (`ai::tests::a_blends_transparency_follows_its_record`); scores and estimates unchanged. | | View & navigation | 3 | 70% | multiple windows and the rest of Arrange (Cascade, Float in Window, Float All in Windows) | 9–14 | estimated; Window › Arrange › Tile and Consolidate All Windows done (score/hours unchanged); document-tab artwork hover/copy and lossless transfer tested (2026-10-22; score/hours unchanged); cached canvas reprojection preserves scale during resize, rotation and DPI changes (regression and contributor original-file evidence below; scores/hours unchanged) | | View & navigation | 3 | 70% | multiple windows and the rest of Arrange (Cascade, Float in Window, Float All in Windows) | 9–14 | estimated; Window › Arrange › Tile and Consolidate All Windows done (score/hours unchanged) | | Guides, grids, smart guides, snapping, rulers | 3 | 80% | "intersect" smart guides for a moved selection's anchors (drawn points and dragged anchors snap to intersections, #1658), distance readouts while drawing | 4–7 | estimated (lowered from 85%: target moved); new ruler-guide Alt orientation implemented; video rulers (View › Rulers › Show Video Rulers, #2849) done, score unchanged | @@ -283,7 +283,7 @@ The discounts, with the evidence: #868), guides lost (#779), slower opening (#758), live effects, brushes and symbols as their drawn look (#637). VectorCraft's PDF-compatible `.ai` carries an editing copy of the art (layers, groups, paths, colors, gradients, patterns, images, transparency, opacity masks, clipping, type as text and symbols), with live effects kept only - on paths, compound paths and groups that qualify (at most a fill and a stroke, a non-zero fill rule, no large canvas) and whose appearance and effects the art-style writer supports, other objects' effects other than geometry + on paths, compound paths and groups that qualify (at most a fill and a stroke, a non-zero fill rule when filled, no large canvas) and whose appearance and effects the art-style writer supports, other objects' effects other than geometry effects left out, and live objects written as their art; the legacy `.ai` of version 7 it also writes keeps layers, groups and type as text (one artboard per file, no transparency) but hasn't been tested by users yet (#868). That blocks beta (the main-format rule) for people who hand files back to Illustrator users, but it doesn't stop someone opening and reworking their own archive. From 66b4c171d4c5ecce50e838559e50aa8783ba217a Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Sat, 7 Nov 2026 14:52:43 -0800 Subject: [PATCH 2/3] .ai save: the large-canvas warning says what the editing copy keeps On a large canvas no art style is written, so objects with live effects are written as their vector art with their geometry effects applied, and their shadows, glows and feathers are left out. The warning now says that, as file-format-parity.md does, instead of "written as their drawn look". --- crates/eps/src/ai_editing/writer/styles.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/eps/src/ai_editing/writer/styles.rs b/crates/eps/src/ai_editing/writer/styles.rs index de74bc99ee..ffd4b4fcf3 100644 --- a/crates/eps/src/ai_editing/writer/styles.rs +++ b/crates/eps/src/ai_editing/writer/styles.rs @@ -18,8 +18,7 @@ use super::{Writer, Xy, blend_code, compound_path, hide}; use crate::ai_ops; use crate::ps; -pub(in crate::ai_editing) const LARGE_CANVAS_STYLES: &str = - "on a large canvas, objects with live effects are written as their drawn look in the editing data for other apps"; +pub(in crate::ai_editing) const LARGE_CANVAS_STYLES: &str = "on a large canvas, objects with live effects are written as their vector art with their geometry effects applied, without shadows, glows or feathers, in the editing data for other apps"; pub(in crate::ai_editing) const GRAPHIC_STYLES: &str = "graphic styles and links to them are left out of the editing data for other apps"; /// Does `doc` have graphic styles other than a new document's, or an object in its layers, opacity From a1842028daa7ea708fd0c74a8961f03959dd2e35 Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Sat, 7 Nov 2026 14:52:43 -0800 Subject: [PATCH 3/3] Tests: compare the RGB values of colors in the art-style round trip art_styles_write_the_same_bytes_again failed on Windows (MSVC) on the Pink swatch: the first save wrote its CMYK equivalent as 0 0.9317 0.1527 0 and the save of the reopened file as 0 0.9389 0.1629 0. The writer computes the CMYK equivalent of an RGB color from its RGB values, and the save of the reopened file computes it from the RGB values read back at four decimals; for this out-of-gamut color the Generic CMYK conversion moves by more than the test's 0.002 there. On macOS the two saves of this document differ by at most 0.0016 in these numbers. The test now blanks the CMYK equivalents of RGB colors (the first four numbers of `c m y k r g b Xa` and of an RGB gradient stop's `c m y k r g b 2 ... Bs`) and compares every other number, the RGB values included. With them blanked, the two saves are identical on macOS. The large-canvas test's comment also says what such objects are written as. --- crates/eps/src/ai_editing/tests.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/crates/eps/src/ai_editing/tests.rs b/crates/eps/src/ai_editing/tests.rs index fca9eef02e..a26463c96c 100644 --- a/crates/eps/src/ai_editing/tests.rs +++ b/crates/eps/src/ai_editing/tests.rs @@ -5549,7 +5549,8 @@ fn effects_in_a_styled_objects_mask_are_warned_about() { } /// On a large canvas no art style is written (the reader scales the styles of a large canvas): -/// objects with effects are their drawn look, with a warning. +/// objects with effects are written as their vector art with their geometry effects applied, with a +/// warning. #[test] fn a_large_canvas_writes_no_art_styles() { let mut doc = Document::new(20000.0, 100.0); @@ -5577,7 +5578,23 @@ fn art_styles_write_the_same_bytes_again() { assert_eq!(private_data(&doc, &opts()).unwrap().0, private_data(&doc, &opts()).unwrap().0); // What is read back is written as it was. let again = export_ai_editing(&read_back(&doc), &opts()).unwrap().program; - near_lines(&shown(&again), &shown(&first.program)); + near_lines(&rgb_without_cmyk(&shown(&again)), &rgb_without_cmyk(&shown(&first.program))); +} + +/// `program` with the CMYK equivalents of RGB colors blanked out: the first four numbers of an RGB +/// color's `c m y k r g b Xa` (or `XA`) and of an RGB gradient stop's `c m y k r g b 2 ... Bs`. A +/// save of the reopened file computes them again from the RGB values read back at four decimals, +/// and on some platforms the CMYK conversion moves them by more than [`near_lines`] allows. The RGB +/// values stay compared. +fn rgb_without_cmyk(program: &str) -> String { + let blank = |line: &str| { + let (prefix, rest) = line.strip_prefix("%_").map_or(("", line), |r| ("%_", r)); + let t: Vec<&str> = rest.split(' ').collect(); + let color = t.len() == 8 && matches!(t[7], "Xa" | "XA"); + let stop = t.len() > 8 && t[7] == "2" && t.last() == Some(&"Bs"); + if color || stop { format!("{prefix}_ _ _ _ {}", t[4..].join(" ")) } else { line.to_string() } + }; + program.lines().map(blank).collect::>().join("\n") } /// `n` on the first layer of `doc`.