Skip to content

Commit

Permalink
fix binary DXF issue of XDATA in R2000+ files
Browse files Browse the repository at this point in the history
  • Loading branch information
mozman committed Apr 10, 2020
1 parent d6dc874 commit 3980393
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 15 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ Quick-Info
- additional required packages: [pyparsing](https://pypi.org/project/pyparsing/)
- MIT-License
- read/write/new support for DXF versions: R12, R2000, R2004, R2007, R2010, R2013 and R2018
- read/write support for ASCII DXF and Binary DXF, export of Binary DXF is experimental and can produce invalid files.
- additional read support for DXF versions R13/R14 (upgraded to R2000)
- additional read support for older DXF versions than R12 (upgraded to R12)
- read/write support for ASCII DXF and Binary DXF
- preserves third-party DXF content

Included extensions:
Expand Down
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Quick-Info
- read/write/new support for DXF versions: R12, R2000, R2004, R2007, R2010, R2013 and R2018
- additional read support for DXF versions R13/R14 (upgraded to R2000)
- additional read support for older DXF versions than R12 (upgraded to R12)
- read/write support for ASCII DXF and Binary DXF
- preserves third-party DXF content

Included Extensions
Expand Down
Binary file added integration_tests/data/bin_dxf_r2000.dxf
Binary file not shown.
14 changes: 14 additions & 0 deletions integration_tests/test_open_binary_DXF_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,20 @@ def test_open_R13_R14(filename, tmpdir):
assert os.path.exists(converted)


def test_open_R2000_with_xdata():
filename = os.path.join(BASEDIR, DATADIR, 'bin_dxf_r2000.dxf')
doc = ezdxf.readfile(filename)
assert 'Model' in doc.layouts, 'Model space not found'
assert 'Layout1' in doc.layouts, 'Paper space not found'
assert doc.dxfversion == 'AC1015'
msp = doc.modelspace()
text = msp.query('TEXT').first
assert text.dxf.text == 'ezdxf'
hyperlink, description, location = text.get_hyperlink()
assert hyperlink == 'http://ezdxf.mozman.at'
msp.add_line((0, 0), (10, 3))


def test_open_R12():
filename = os.path.join(BASEDIR, DATADIR, 'bin_dxf_r12.dxf')
doc = ezdxf.readfile(filename)
Expand Down
13 changes: 7 additions & 6 deletions src/ezdxf/lldxf/tagger.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,19 +140,20 @@ def scan_params():
return encoding, dxfversion

encoding, dxfversion = scan_params()
one_byte_group_code = dxfversion < 'AC1012'
r12 = dxfversion <= 'AC1009'
index = 22
data_length = len(data)
unpack = struct.unpack_from

while index < data_length:
# decode next group code
code = data[index]
if code == 255: # extended data
code = (data[index + 2] << 8) | data[index + 1]
index += 3
elif one_byte_group_code:
index += 1
if r12:
if code == 255: # extended data
code = (data[index + 2] << 8) | data[index + 1]
index += 3
else:
index += 1
else: # 2-byte group code
code = (data[index + 1] << 8) | code
index += 2
Expand Down
19 changes: 11 additions & 8 deletions src/ezdxf/lldxf/tagwriter.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def __init__(self, stream: BinaryIO, dxfversion=LATEST_DXF_VERSION, write_handle
super().__init__(None, dxfversion, write_handles)
self._stream = stream
self._encoding = encoding # output encoding
self._group_code_size = 1 if self.dxfversion <= 'AC1009' else 2
self._r12 = self.dxfversion <= 'AC1009'

def write_signature(self) -> None:
self._stream.write(b'AutoCAD Binary DXF\r\n\x1a\x00')
Expand Down Expand Up @@ -95,13 +95,16 @@ def write_tag2(self, code: int, value: Any) -> None:
stream = self._stream

# write group code
if code >= 1000: # extended data
stream.write(b'\xff')
# always 2-byte group code for extended data
if self._r12:
# Special group code handling if DXF R12 and older
if code >= 1000: # extended data
stream.write(b'\xff')
# always 2-byte group code for extended data
stream.write(code.to_bytes(2, 'little'))
else:
stream.write(code.to_bytes(1, 'little'))
else: # for R2000+ do not need a leading 0xff in front of extended data
stream.write(code.to_bytes(2, 'little'))
else:
stream.write(code.to_bytes(self._group_code_size, 'little'))

# write tag content
if code in BYTES:
stream.write(int(value).to_bytes(1, 'little'))
Expand All @@ -127,7 +130,7 @@ def _write_binary_chunks(self, code: int, data: bytes) -> None:

while index < size:
# write group code
if code >= 1000: # extended data, just 1004?
if self._r12 and code >= 1000: # extended data, just 1004?
stream.write(b'\xff') # extended data marker
# binary data does not exist in regular R12 entities,
# only 2-byte group codes required
Expand Down

0 comments on commit 3980393

Please sign in to comment.