forked from 1b-agent/opencadstudio-upstream
Merge remote-tracking branch 'origin/main' into codex/dwf-dgn-underlays
# Conflicts: # Cargo.lock
This commit is contained in:
commit
fecbcd8138
51 files changed
+4155
-294
No files matched your search
+123
@@ -2894,3 +2894,126 @@ mod corrupt_guard_tests {
|
||||
assert!(!is_entity_corrupt(&EntityType::Insert(i)));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod pre_r2000_layer_plot_tests {
|
||||
use super::*;
|
||||
use codec::tables::layer::Layer as DocLayer;
|
||||
use codec::types::DxfVersion;
|
||||
|
||||
fn drawing_with_layers() -> CadDocument {
|
||||
let mut doc = CadDocument::new();
|
||||
crate::io::linetypes::populate_document(&mut doc);
|
||||
for name in ["COARSE", "FINE"] {
|
||||
let mut layer = DocLayer::new(name);
|
||||
layer.handle = doc.allocate_handle();
|
||||
doc.layers.add(layer).unwrap();
|
||||
}
|
||||
doc
|
||||
}
|
||||
|
||||
/// Tests run in parallel, so each gets its own file.
|
||||
fn saved_path(test: &str, version: DxfVersion) -> std::path::PathBuf {
|
||||
std::env::temp_dir().join(format!(
|
||||
"ocs_plotflag_{test}_{}_{}.dwg",
|
||||
version.as_str(),
|
||||
std::process::id()
|
||||
))
|
||||
}
|
||||
|
||||
/// The LAYER record only grew a plot flag in R2000. Reading an R14 drawing
|
||||
/// must therefore leave every layer plottable — reading the missing bit as
|
||||
/// "don't plot" blanked the whole sheet in PLOT, the preview and QUICKPRINT
|
||||
/// while the drawing still looked right on screen (display and plot
|
||||
/// visibility are separate flags).
|
||||
#[test]
|
||||
fn an_r14_drawing_reads_back_with_every_layer_plottable() {
|
||||
let doc = drawing_with_layers();
|
||||
let path = saved_path("r14_bytes", DxfVersion::AC1014);
|
||||
save_as_version(&doc, &path, DxfVersion::AC1014).expect("save R14 DWG");
|
||||
let bytes = std::fs::read(&path).expect("read R14 DWG");
|
||||
let _ = std::fs::remove_file(&path);
|
||||
assert_eq!(&bytes[..6], b"AC1014", "writer did not emit an R14 header");
|
||||
|
||||
let loaded = load_bytes("r14.dwg", bytes).expect("load R14 DWG");
|
||||
assert_eq!(loaded.version, DxfVersion::AC1014);
|
||||
assert!(
|
||||
loaded.layers.iter().all(|layer| layer.is_plottable),
|
||||
"an R14 layer came back unplottable: {:?}",
|
||||
loaded
|
||||
.layers
|
||||
.iter()
|
||||
.filter(|layer| !layer.is_plottable)
|
||||
.map(|layer| layer.name.clone())
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
}
|
||||
|
||||
/// R13 carries the same four-bit LAYER record as R14, and a path-based open
|
||||
/// runs its fixes through `finalize_loaded_outcome` rather than
|
||||
/// `load_bytes`, so this covers that second entry point too.
|
||||
#[test]
|
||||
fn an_r13_drawing_reads_back_with_every_layer_plottable() {
|
||||
let doc = drawing_with_layers();
|
||||
let path = saved_path("r13_path", DxfVersion::AC1012);
|
||||
save_as_version(&doc, &path, DxfVersion::AC1012).expect("save R13 DWG");
|
||||
let loaded = load_file(&path).expect("load R13 DWG");
|
||||
let _ = std::fs::remove_file(&path);
|
||||
assert!(
|
||||
loaded.layers.iter().all(|layer| layer.is_plottable),
|
||||
"an R13 layer came back unplottable"
|
||||
);
|
||||
}
|
||||
|
||||
/// From R2000 on the flag is in the file, so what the file says wins — a
|
||||
/// layer stored unplottable (DEFPOINTS, say) must stay unplottable.
|
||||
#[test]
|
||||
fn a_modern_drawing_keeps_the_plot_flag_it_stored() {
|
||||
let mut doc = drawing_with_layers();
|
||||
doc.layers.get_mut("FINE").unwrap().is_plottable = false;
|
||||
let path = saved_path("modern", DxfVersion::AC1032);
|
||||
save_as_version(&doc, &path, DxfVersion::AC1032).expect("save R2018 DWG");
|
||||
let loaded = load_file(&path).expect("load R2018 DWG");
|
||||
let _ = std::fs::remove_file(&path);
|
||||
assert!(!loaded.layers.get("FINE").unwrap().is_plottable);
|
||||
assert!(loaded.layers.get("COARSE").unwrap().is_plottable);
|
||||
}
|
||||
|
||||
/// The plot pass keeps a wire only when it is marked plottable, so an R14
|
||||
/// drawing whose layers came back unplottable plotted a blank sheet while
|
||||
/// every entity still drew on screen. Lock the whole chain here: load an
|
||||
/// R14 drawing and check the wires the plot paths consume.
|
||||
#[test]
|
||||
fn every_wire_of_an_r14_drawing_stays_plottable() {
|
||||
use codec::entities::Line;
|
||||
use codec::types::Vector3;
|
||||
use codec::EntityType;
|
||||
|
||||
let mut doc = drawing_with_layers();
|
||||
for (index, layer) in ["COARSE", "FINE"].into_iter().enumerate() {
|
||||
let x = index as f64 * 10.0;
|
||||
let mut line = Line::from_points(
|
||||
Vector3::new(x, 0.0, 0.0),
|
||||
Vector3::new(x + 5.0, 5.0, 0.0),
|
||||
);
|
||||
line.common.layer = layer.to_string();
|
||||
doc.add_entity(EntityType::Line(line)).expect("add line");
|
||||
}
|
||||
let path = saved_path("r14_wires", DxfVersion::AC1014);
|
||||
save_as_version(&doc, &path, DxfVersion::AC1014).expect("save R14 DWG");
|
||||
let bytes = std::fs::read(&path).expect("read R14 DWG");
|
||||
let _ = std::fs::remove_file(&path);
|
||||
|
||||
let mut scene = crate::scene::Scene::new();
|
||||
scene.document = load_bytes("r14.dwg", bytes).expect("load R14 DWG");
|
||||
let (wires, _) = scene.plot_wire_groups(None);
|
||||
assert!(!wires.is_empty(), "the R14 drawing tessellated to no wires");
|
||||
let dropped = wires.iter().filter(|wire| !wire.plot_visible).count();
|
||||
assert_eq!(
|
||||
dropped,
|
||||
0,
|
||||
"{dropped} of {} wires would be dropped from the plot",
|
||||
wires.len()
|
||||
);
|
||||
}
|
||||
}
|
||||
+11
-2
@@ -242,8 +242,10 @@ fn emit_image(
|
||||
{
|
||||
return Err("Cannot plot bitmap: invalid coordinates, clip boundary, or opacity.".into());
|
||||
}
|
||||
// The low bit (free: the pixel buffer is aligned) keeps the opaque copy
|
||||
// of a picture apart from its transparent one.
|
||||
let key = (
|
||||
std::sync::Arc::as_ptr(&image.pixels) as usize,
|
||||
std::sync::Arc::as_ptr(&image.pixels) as usize | usize::from(!image.use_alpha),
|
||||
image.width,
|
||||
image.height,
|
||||
);
|
||||
@@ -255,7 +257,14 @@ fn emit_image(
|
||||
doc.resources.xobjects.map.insert(
|
||||
id.clone(),
|
||||
printpdf::XObject::Image(printpdf::RawImage {
|
||||
pixels: printpdf::RawImageData::U8(image.pixels.as_ref().clone()),
|
||||
pixels: printpdf::RawImageData::U8(if image.use_alpha {
|
||||
image.pixels.as_ref().clone()
|
||||
} else {
|
||||
// Transparency off: every pixel opaque in its colour.
|
||||
let mut opaque = image.pixels.as_ref().clone();
|
||||
opaque.chunks_exact_mut(4).for_each(|px| px[3] = 255);
|
||||
opaque
|
||||
}),
|
||||
width: image.width as usize,
|
||||
height: image.height as usize,
|
||||
data_format: printpdf::RawImageFormat::RGBA8,
|
||||
|
||||
Reference in new issue
Block a user