Fix #3085: DXF LAYOUT objects write only the group codes the DXF Reference defines

The PLOTSETTINGS part of each LAYOUT wrote the paper image origin as a point
(148 and 158), but the origin is two values at 148 (x) and 149 (y), and 158 is
not a PLOTSETTINGS code. Strict readers such as Autodesk Fusion can reject the
file. The ezdxf re-save the reporter found Fusion accepts differs from our export in
these objects, not in the geometry.

- 148/149 for the paper image origin
- shade plot mode, resolution level and DPI (76/77/78) from DXF 2004
- plot flag 1024 (model type) on the Model layout
- the plot style ACDBPLACEHOLDER without a subclass marker

Test r2000_and_later_files_have_the_structure_cad_apps_require checks the
required sections and table entries, handles below $HANDSEED, references
that resolve, and LAYOUT group codes.

# Conflicts:
#	docs/file-format-parity.md
This commit is contained in:
Don Omondi
2026-10-31 19:43:17 +07:00
committed by bflatastic
parent 4861fb9d85
commit 22b1c6bc2e
3 changed files with 83 additions and 5 deletions
+3 -2
View File
@@ -1,6 +1,6 @@
# File format parity
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-31 · **Change:** minor (an Illustrator envelope whose contents are being edited no longer draws its undistorted contents over its result) · **Target:** Adobe Illustrator 2026 (30.x)
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-31 · **Change:** minor (DXF export: LAYOUT objects write only DXF Reference group codes, for strict readers such as Autodesk Fusion, #3085) · **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
@@ -98,7 +98,7 @@ the app's own editing copy of a file (an EPS after its `%%EOF`, a `.ai`'s `AIPri
| EPS | open, place, save | yes (own PostScript L3 interpreter, Illustrator EPS editing data structure) | yes (L2/L3, TIFF previews) | CID-keyed CJK type not read; #505; images encoded with `CCITTFaxDecode` (ITU-T T.4 Group 3 and T.6 Group 4, with `K`, `Columns`, `Rows`, `EndOfBlock`, `EndOfLine`, `EncodedByteAlign` and `BlackIs1`) draw, and damaged data keeps the rows decoded before its first damaged row; Type 42 (TrueType) fonts set type at its size (#1553); a clip only counts as covering the page when its shape does (#1542); an EPS another app copied pastes as editable vector art (`clipboard.importEps`, #1499); a stitched shading keeps its hard colour changes on import (#1654); CMYK images, CMYK JPEGs included, keep their ink amounts on import, as from PDF, and the pixels a `MaskColor` or `ImageType 3` mask hides become a grayscale opacity mask; ruzstd 0.9.1 for compressed editing data (#1807, RUSTSEC-2026-0344) |
| PostScript `.ps` | open, place | yes (the EPS reader reads its first page; `.epsf` files open and place as EPS) | via Print to PostScript | `tests_epsimport.rs` |
| SVG / SVGZ | open, place, save | yes | yes (SVG Options, Preserve Editing, symbols, filters, rich text) | strongest format; tests in `crates/svg/tests`; text on a path follows basic shapes as their SVG 2 equivalent paths (#1527); CSS transforms and the `font` shorthand (#1565), percentage lengths in symbols (#1596), Inkscape flowed text as area type (#1568) and Inkscape pages as artboards (#1601) import; an unsupported filter is named in its warning (#1598); an artboard exported on its own (Export As with Use Artboards, Export for Screens, Asset Export) has the artboard's name as `<title>`, Save the document's (#3544); attributes in other applications' XML namespaces (`plotter:pen="2"`) kept on their objects from import to export, as `data-*` attributes are (`crates/svg/tests/it/foreign_attributes.rs`); simple shapes export as `<rect>`, `<circle>`, `<ellipse>`, `<line>`, `<polygon>` and `<polyline>` where they draw the same as the path (#4652, `crates/svg/tests/it/basic_shapes.rs`) |
| DXF | open, export | yes | yes (R12–2018) | R13–2018 closed SPLINE flags and control-point closure on import verified (#1299); circular cubic paths export as native CIRCLE/ARC where stroke semantics permit; R12 weighted strokes remain POLYLINE while non-circular curves keep the existing fallback (`crates/cad/src/tests.rs`); [Autodesk group 70](https://help.autodesk.com/cloudhelp/2024/ENU/AutoCAD-DXF/files/GUID-E1F884F8-AA90-4864-A215-3182D47A9C74.htm). CNC preset and VCarve QA remain open |
| DXF | open, export | yes | yes (R12–2018) | R13–2018 closed SPLINE flags and control-point closure on import verified (#1299); circular cubic paths export as native CIRCLE/ARC where stroke semantics permit; R12 weighted strokes remain POLYLINE while non-circular curves keep the existing fallback (`crates/cad/src/tests.rs`); [Autodesk group 70](https://help.autodesk.com/cloudhelp/2024/ENU/AutoCAD-DXF/files/GUID-E1F884F8-AA90-4864-A215-3182D47A9C74.htm). DXF 2000–2018 LAYOUT objects write the paper image origin as 148/149 (was a stray 158), the shade plot codes (2004+) and the model type flag, and the plot style placeholder carries no subclass marker (#3085; structure test `r2000_and_later_files_have_the_structure_cad_apps_require`, checked with ezdxf's audit; not yet confirmed in Autodesk Fusion). CNC preset and VCarve QA remain open |
| DWG | open, export | no | no | no open spec; DXF instead |
| EMF / WMF | open, export | yes | yes | an oversized embedded PNG or JPEG is refused from its header, before any pixels are decoded (#1776) |
| PSD | open, place, export | yes (merged image, every mode and depth) | yes (layered, max editability) | placing as layers (Photoshop Import Options) missing; the embedded ICC profile's tags are 4-byte aligned (#1584) |
@@ -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-31 | minor | DXF export (2000–2018): the LAYOUT objects wrote the paper image origin as a point at group codes 148 and 158, but PLOTSETTINGS defines 148 and 149 and no 158, so strict readers could reject the file (Autodesk Fusion reported "DXF File failed to insert", #3085). They now write 148/149, the shade plot mode, resolution and DPI (76–78, 2004 and later) and flag 1024 on the Model layout; the plot style ACDBPLACEHOLDER no longer carries a subclass marker. Test `r2000_and_later_files_have_the_structure_cad_apps_require` (required sections and table entries, handles and references, LAYOUT group codes); exports pass ezdxf's recover and audit; not tested in Fusion itself; scores unchanged |
| 2026-10-31 | minor | `.ai`/EPS editing data: an envelope whose contents are being edited is written the other way round from one that isn't: its contents, a group on `%_` lines, then its dictionary, which holds the mesh that shapes them. Those contents were read as art, so the undistorted art drew over the distorted art the page draws. The group on `%_` lines before an envelope's dictionary is now left out whatever it holds (text in it stays as hidden text, as the dictionary's own does), as the envelope's mesh already was (#2405). Test `import::ai::tests::an_envelope_s_contents_being_edited_are_not_read_as_art`; checked locally against a user's file: it opens from its layers, 0.0% from its page (it was 9.7%, over the 5% limit); scores unchanged |
| 2026-10-31 | minor | `.ai`/EPS editing data: a transparency (`Xy`) set by art inside a dictionary, as an area text's frame (its `/ConfiningPath`) or a mask's art sets one, stays the current one after the dictionary: the writer goes on from it, so the objects after such a text have no `Xy` of their own. It was dropped when the dictionary closed, and a user's file drew its logo, calligraphy, footer and type after an area text with the Lighten of the glow before it, so they faded into the light background. Test `import::ai::tests::a_transparency_set_in_a_dictionary_s_art_stays_after_it`; checked locally against that file: 8.1% → 1.7% from its page, so it opens from its layers (5% is the limit); scores unchanged |
| 2026-10-31 | minor | `.ai`/EPS editing data: area type made from the file's text document put its first baseline the font's ascent below the frame's top, where the file's own layout (and its page) can have it higher: Oswald's and Urbanist's headings came in a third and an eighth of their size lower than on the page, and each text over them was taken to differ. When the text document's first line is more than half a point from where it is laid out here, the first baseline is fixed (Area Type Options › First Baseline › Fixed) where the file has it; the type's own font metrics aren't changed. Test `import::ate::tests::area_type_s_first_line_goes_where_the_file_lays_it_out`; checked locally against users' files: two election posters come 5.4% → 1.1% and 8.6% → 4.3% from their pages, so they open from their layers, and another 1.7% → 0.3%; scores unchanged |