Skip to content

Fix DWG/DXF round-trip and version-conversion defects (R2007 output, tables, dimensions, SHAPE, XDATA, transforms) - #1324

Closed
Sring65 wants to merge 833 commits into
DomCR:issue-854_transform-rotation-fixfrom
Sring65:master
Closed

Sring65 wants to merge 833 commits into
DomCR:issue-854_transform-rotation-fixfrom
Sring65:master

Conversation

@Sring65

@Sring65 Sring65 commented Oct 22, 2026 •

Copy link
Copy Markdown

Note: all modifications in this PR are AI-generated code (written by an AI
coding agent, then verified behaviorally against AutoCAD and ODA
FileConverter). The diff is large — 134 files, +16,411/−1,014 — and mixes
several independent fix streams. I cannot point at each hunk and say exactly
which symptom it fixes, so I have grouped the changes by theme and mapped each
commit to its theme below. Please review at whatever granularity is
comfortable for you, and feel free to adopt a subset.

Resubmission

Dependency: DomCR/CSUtilities PR #29

This PR depends on a companion change in DomCR/CSUtilities — a fix to the
Matrix3(Matrix4) constructor, which was copying the linear part transposed,
so every derived transform came out mirrored. Without it, the transform fixes
in this PR (ellipses, text rotation, arc angles, spline tangents) are wrong.

What's fixed

R2007 (AC1021) DWG write (new functionality; addresses the "AC1021 throws" part of #1323)

  • Implemented AC1021 output.
  • Page-record Checksum is computed over decompressed data and CRC over the
    compressed stored data (previously both over compressed data → "Error
    decrypting data").
  • enc=1 sections (SummaryInfo/Preview/AppInfo/AppInfoHistory/FileDepList) stored
    uncompressed for AC1021.
  • Encoded page physical size now accounts for the parity region instead of a fixed
    maxPageSize + 32, so large preview data no longer overflows and shifts pages.

Tables (AcDbTable) (addresses #1321: DWG with TableEntity that AutoCAD cannot open / table count drops)

  • DXF read of inlined cell contents now marks ContentType so R2010+ doesn't drop
    the whole table (Error 34 eWrongObjectType).
  • R2004 table write: 4th override bit / object-stream alignment.
  • R2010+ cached block reference restored (table not displaying).
  • Pre-R2007/R2007 legacy table-level override section preserved on write.
  • Default AcDbTableStyle no longer serialized in a way that makes AutoCAD
    AUDIT reject the file; TableEntity cloning no longer leaves a dangling
    TableStyle pointer.

Dimensions & DIMASSOC

  • Dimension association read field order corrected to match the ODA spec
    (associativity / trans_space / rotated_type / dimension object) — was reversed,
    so native files' associations came out misaligned.
  • Dimension geometry follows transforms; OsnapPointRef last-point-ref bit kept.

SHAPE

  • DXF/DWG group code 2 writes the shape name (not the style name) so AutoCAD
    doesn't drop it.
  • Added shape-file index and search next to the drawing; fixes AutoCAD AUDIT
    "shape number/index <= 0".

Coordinate / transform (ApplyTransform / TransformBy) (fully resolves #854; fixes #1250)

  • Fixed for Arc, Shape, Text, Underlay, MLine, Point, Hatch, Leader, Dimension
    series, Spline, TableEntity; Insert scaling/rotation; Ellipse axis vectors +
    normal (with the CSUtilities Matrix3 transpose fix).
  • Arc angles are normalized to [0, 2π) after a transform, matching the
    representation AutoCAD stores (fixes Arc.ApplyTransform: rotation moves the center correctly but rotates the angles backwards #1250: angles rotated backwards).
  • Spline start/end tangents are treated as vectors (linear part only) and a
    zero tangent stays absent, instead of becoming phantom points.
  • Ellipse: center transformed as a point, major-axis endpoint as a vector
    relative to the center (scale + rotation only).

XDATA / string encoding

  • Pre-R2004 Chinese XDATA no longer garbled.
  • TV/TU strings now null-terminated (fixes class-name corruption).

Round-trip fidelity

  • Hatch origin/seed points, LWPOLYLINE width/const-width (43 flag), Leader
    hook line/association, PDFUnderlay scale/rotation, Text/Attrib/Shape default
    omission, Wipeout clip close, HatchPattern angle, Spline nodes.

Gradient fill

  • R2000 gradient definition parse, R2004+ → R2000 down-conversion, R/B channel
    order, LWDISPLAY header variable.

Object stream / handle alignment

  • ACDS dangling reference (file corruption), PolyFaceMesh owned handles
    (HardOwnership), UCS/VIEW control-object handle slots, table-style soft pointer.

Incremental save & read performance (new functionality)

  • Incremental (dirty-handle) save for the version-gated writers: unchanged
    objects are patched in place instead of re-serialized; a safety net falls
    back to a full re-serialize if the dirty tracking cannot cover the stream.
    A zero-change save is now byte-safe (previously it deterministically
    corrupted the file).
  • Parallel object decode on read, streaming DXF export, and save/read progress
    events with total counts (no overhead when no consumer subscribes).

Commit → theme map

Commit Theme
3fdda613 CSUtilities submodule pin (Matrix3 transpose fix — see CSUtilities PR #29)
588c9be2 Real font-metric text bounding boxes (SHX/TTF, CJK-aware)
c8701519 Incremental save, parallel object decode, streaming export
2001e83c Save/read progress events with total counts
61c854ad Coordinate transforms (#854, #1250), dimension flags, document APIs
715fd41d Version-gated writes R14–R2007 (incl. AC1021 output), proxy-graphics round-trip
37adbe70 DXF streaming export, XData interning, version-gated read/write
30ea54fc TableEntity clone: dangling TableStyle pointer
00fbc836 Default TableStyle serialization AUDIT error
e6d89440 Per-class clone: 5 association-preservation defects
78e00529 Zero-modification incremental save corruption (D4)

Issues addressed / possibly addressed

Issue Status with this PR
#854 — TransformBy support/behavior Fully resolved (transform fixes above)
#1250 — Arc.ApplyTransform rotates angles backwards Fixed — post-transform angles normalized to [0, 2π) like AutoCAD
#1321 — DwgWriter produces unopenable DWG with TableEntity, table count drops Fixed — table fixes above (default TableStyle AUDIT error, dangling TableStyle pointer on clone, R2004 override bits, R2010+ cached block reference)
#1323 — no-op round-trip: AC1021 throws, AC1015/AC1018/AC1024/AC1027 need AutoCAD recovery Partially addressed — AC1021 (R2007) output is newly implemented and writes cleanly; the other versions benefit from the version-gated write path but I have not verified each one, please confirm

Verification

  • Affected files open in AutoCAD without errors (and pass ODA FileConverter audit).
  • Round-trip output compared against AutoCAD-native files: entity counts,
    geometry, associations, and content match.
  • Where a defect existed, the produced file was diffed field-by-field against the
    AutoCAD reference.

Reference / reproduction (test harness)

The test tool and sample files used for the verification above are in a
test-only repo, free to browse:
https://github.com/Sring65/-ACadSharpTransformertest
image

  • dwgReadWrite — .NET 10 console harness. Run with no arguments and it
    executes the full default pipeline on the included sample.dwg (70-entity
    drawing): coordinate transform (scale + rotate + translate) → DWG save to
    every version AC1014–AC1032 → full document clone → per-class clone,
    then prints a pass/fail report.
  • Targeted subcommands: rt <in.dwg> <out.dwg> [version] (no-op round-trip —
    the check behind DWG write at AC1015/AC1018/AC1024/AC1027 requires AutoCAD recovery on a no-op round-trip (AC1032 is clean; AC1021 throws) #1323), empty <version> (empty file per version),
    mktypes <out.dwg> (synthetic linetypes with text fields),
    dump / classes / objinfo / layoutdump / inspect* (structural
    inspection of read/write output).
  • Test data included in the repo: sample.dwg, SHX shape fonts
    (Aaa.shx, shape.shx — for the SHAPE fixes), sample.pdf, image.jpg.

To reproduce: check out this branch, point the harness' ProjectReference at
your local ACadSharp checkout (it currently carries an absolute path — see
that repo's README), then dotnet build -c Release and run.

Notes for reviewer

  • All code is AI-generated (see note above); in-diff comments marked [FIX] /
    [PATCH] state the intent of each change. Behavior was verified against
    AutoCAD/ODA, not line-by-line human review — extra scrutiny on the write path
    is welcome.
  • R2007 output and incremental save are new functionality — worth a closer
    look on the write path.
  • Happy to split this into separate PRs per theme (or per commit, using the map
    above) if that is easier to review.

DomCR and others added 30 commits September 10, 2026 10:23
…reate-missing-layers

Create layers referenced by DXF entities but missing from the LAYER table
Moved Wall and WallJustification to new AecEntities namespace with a new AecEntity base class. Updated all references to the new namespace. Refactored CadHeader to flatten property structure and improve property handling. Added constructors to ImageDefinition and VisualStyle. Updated LwPolyline to accept IVector for vertices.
Replaced ACadSharp.Entities.AecObjects with ACadSharp.Entities.AecEntities. Added new using directives for ACadSharp.IO, System.IO, System.Linq, Xunit, and Xunit.Abstractions to support additional functionality and testing.
The Trace constant ("AcDbTrace") was removed from the DxfSubclassMarker class in DxfSubclassMarker.cs as it is no longer needed.
Refactored the ExplodePattern and emitDashedSegment methods in the Hatch class to return IEnumerable<Line> instead of IEnumerable<Entity>. Updated all related variables and logic to handle only Line entities, ensuring the output is restricted to lines rather than any entity type.
Set Hatch.Style default to HatchStyleType.Normal for clarity.
Removed unused MPolygon-related comments to clean up code.
…ormats

Add InternalsVisibleTo for ACadSharp.Formats assembly
Introduce AssertRoundtrip property to SingleCaseGenerator, enabling custom assertions on CadDocument after roundtrip operations. Update SingleLine test to use this mechanism and invoke it in DwgWriterSingleObjectTests, allowing more flexible and targeted validation in tests.
Renamed Has to HasVertices in MLineFlags for clarity, added None = 0, and improved XML documentation. Updated DwgObjectReader to use HasVertices flag.
Replaces flat SegmentIndex/StartEndPointPairs in LeaderLine with a BreakInfo class and a list of BreakInfo entries. Updates reading, writing, cloning, and document assignment logic to support multiple break info entries per leader line, improving structure and clarity.
Set default values for key MultiLeader and MultiLeaderObjectContextData properties to ensure valid initial states. Refactor LeaderContentType enum for clarity. Update DwgObjectReader to use _mergedReaders for color reading. Simplify DwgObjectWriter logic for writing leader roots and annotation context data. Perform minor code cleanup.
Add conditional logic for R2007Pre arrowhead handling in DwgObjectWriter. Refactor CadMLeaderTemplate for clarity: mark as internal, improve formatting, streamline constructors and build method, and clarify attribute handle resolution. Add placeholder for ArrowheadHandles processing.
Made CadDictionaryTemplate public, refactored constructors, and improved the build method for better root dictionary handling, entry resolution, and error notifications. Cleaned up redundant code for clarity.
DomCR and others added 17 commits October 27, 2026 09:06
Improve hatch DXF serialization for optional patterns and gradients, including gradient properties, colors, and supported-version handling. Initialize gradients when reading R2004+ DWG data, make pattern output null-safe, and add DXF generation to `LocalSampleTests`.
Initialize hatch gradients by default

Make `Hatch.GradientColor` create a `HatchGradientPattern` automatically and remove redundant reader initialization. Update `LocalSampleTests` to generate only DWG output and remove unused imports.
Use generic `readSurfaceEntity<T>` dispatch for each surface type and instantiate the correct concrete type during modeler geometry parsing, preserving existing SAT and surface-specific handling.
- Add shared ACDSDATA, ACIS/modeler geometry, proxy, surface, and AEC support.
- Expand DWG/DXF readers, writers, round-trip coverage, and malformed-data handling.
- Improve entities, dimensions, multileaders, dictionaries, styles, and API validation.
- Update configuration, contribution guidance, versioning workflow, and project version.
- Deprecate legacy Prototype 1b data APIs while retaining reader compatibility.
Omit default layer, linetype, scale, and visibility values.
Serialize line weight only for AC1015+ when non-ByLayer.
Reformat `LineWeightType` without changing its values.
Reformat table-writing code and add explicit `this.` qualification without changing serialization behavior.
…l-fields-optimization

Issue/1083 dxfwriter optional fields optimization
- Move shared DWG reader functionality into `DwgStreamReaders`
- Expand reader and writer support for values, colors, dates, handles, and text
- Update factories and merged streams across DWG versions
- Preserve trailing data when reading ACIS geometry
- Add conditional stream diagnostics and exploration helpers
@DomCR DomCR added the invalid This doesn't seem right label Oct 28, 2026
@DomCR

DomCR commented Oct 28, 2026

Copy link
Copy Markdown
Owner

Hi @Sring65, this PR is not valid to be merged sorry.

DomCR and others added 8 commits October 28, 2026 17:06
Lazily initialize extended data and reactors, preserve default layer and line type behavior, register defaults on document assignment, and make extended-data storage non-reassignable.
Avoid initializing reactors and extended data when cloning `CadObject`. Make reactor removal and clearing null-safe, and ensure `SetPositionByFlag` marks the DWG stream as non-empty.
Allow zero Insert scale factors in the object model while normalizing them to `1.0` for DWG output. Add roundtrip coverage, validate MText transparency values, and make reactor cleanup null-safe.
Lazily initialize `_reactors` in `AddReactor` before adding reactors, and improve spacing in `CleanReactors`.
Drop validation of positive, negative, and zero scale values
from the InsertTest class.
Use typed cloning for layer, linetype, and material references while preserving null backing fields. Add lazy `LineType.Continuous` defaults and safely handle reference removal during document assignment and unassignment.
Optimize lazy CAD object state initialization
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

invalid This doesn't seem right

Projects

None yet

Development

Successfully merging this pull request may close these issues.