1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//! Unknown entity type for round-trip preservation.
//!
//! When the reader encounters an entity type that is not directly supported,
//! it captures the common entity properties (handle, layer, color, …) and
//! the raw record data so the entity can be written back losslessly.
//!
//! For DWG files, the entire merged-stream record is stored in
//! [`raw_dwg_data`](UnknownEntity::raw_dwg_data) together with the
//! original DWG type code. The writer emits these bytes verbatim,
//! preserving the entity exactly as it was in the source file.
//!
//! For DXF files, the entity-specific group-code pairs are stored in
//! [`raw_dxf_codes`](UnknownEntity::raw_dxf_codes) so they can be
//! written back alongside the common entity data.
use crate::entities::{Entity, EntityCommon};
use crate::types::{BoundingBox3D, Color, Handle, LineWeight, Transform, Transparency, Vector3};
/// An entity whose type is not directly supported by the library.
///
/// Preserves the DXF/DWG type name and common entity properties.
/// When raw data is available (DWG `raw_dwg_data` or DXF
/// `raw_dxf_codes`), the entity is written back losslessly.
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct UnknownEntity {
/// Common entity data (handle, layer, color, reactors, …).
pub common: EntityCommon,
/// The DXF type name as it appeared in the file (e.g. `"ACAD_PROXY_ENTITY"`).
pub dxf_name: String,
/// DWG object type code (from the binary record header).
/// `0` if the entity did not come from a DWG file.
pub dwg_type_code: i16,
/// Raw DWG merged-stream record bytes.
///
/// This is the exact payload between the ModularShort length prefix
/// and the CRC-16 trailer. When present the writer emits these
/// bytes verbatim (with fresh framing) so the entity survives a
/// roundtrip without any data loss.
#[cfg_attr(feature = "serde", serde(skip))]
pub raw_dwg_data: Option<Vec<u8>>,
/// Handle-stream bit count for R2010+ DWG records.
///
/// Stored alongside `raw_dwg_data` because R2010+ records require
/// a ModularChar(handle_bits) field in the framing header.
pub dwg_handle_bits: i64,
/// Raw DXF entity-specific group-code pairs.
///
/// Each entry is `(group_code, value_string)`. When present the
/// DXF writer emits the common entity header followed by these
/// pairs, reproducing the original entity content.
#[cfg_attr(feature = "serde", serde(skip))]
pub raw_dxf_codes: Option<Vec<(i32, String)>>,
/// DWG version `raw_dwg_data` was read from (drop on incompatible cross-version save).
#[cfg_attr(feature = "serde", serde(skip))]
pub dwg_source_version: Option<crate::types::DxfVersion>,
}
impl UnknownEntity {
/// Create a new unknown entity with the given DXF type name.
pub fn new(dxf_name: impl Into<String>) -> Self {
Self {
common: EntityCommon::new(),
dxf_name: dxf_name.into(),
dwg_type_code: 0,
raw_dwg_data: None,
dwg_handle_bits: 0,
raw_dxf_codes: None,
dwg_source_version: None,
}
}
}
impl Entity for UnknownEntity {
fn handle(&self) -> Handle {
self.common.handle
}
fn set_handle(&mut self, handle: Handle) {
self.common.handle = handle;
}
fn layer(&self) -> &str {
&self.common.layer
}
fn set_layer(&mut self, layer: String) {
self.common.layer = layer;
}
fn color(&self) -> Color {
self.common.color
}
fn set_color(&mut self, color: Color) {
self.common.color = color;
}
fn line_weight(&self) -> LineWeight {
self.common.line_weight
}
fn set_line_weight(&mut self, weight: LineWeight) {
self.common.line_weight = weight;
}
fn transparency(&self) -> Transparency {
self.common.transparency
}
fn set_transparency(&mut self, transparency: Transparency) {
self.common.transparency = transparency;
}
fn is_invisible(&self) -> bool {
self.common.invisible
}
fn set_invisible(&mut self, invisible: bool) {
self.common.invisible = invisible;
}
fn bounding_box(&self) -> BoundingBox3D {
BoundingBox3D::from_point(Vector3::ZERO)
}
fn translate(&mut self, _offset: Vector3) {
super::translate::translate_unknown(self, _offset);
}
fn entity_type(&self) -> &'static str {
"UNKNOWN"
}
fn apply_transform(&mut self, _transform: &Transform) {
super::transform::transform_unknown(self, _transform);
}
}