forked from 1b-agent/opencadstudio-upstream
Plot: thin lineweights keep their true width (#1749)
Every weight under 0.26 mm was clamped to the screen's 1 px floor before the PDF and SVG exporters saw it, so 0.00, 0.09, 0.13 and 0.25 mm all plotted alike. The floor now applies on the GPU only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2c062daa03
commit
2ba2d1c0a7
5 files changed
+10
-8
No files matched your search
@@ -2907,8 +2907,8 @@ mod tests {
|
|||||||
assert_eq!(response["status"], "completed", "{response}");
|
assert_eq!(response["status"], "completed", "{response}");
|
||||||
|
|
||||||
// The plotted PDF carries two distinct pen widths — the per-layer
|
// The plotted PDF carries two distinct pen widths — the per-layer
|
||||||
// 0.13 mm / 0.50 mm hierarchy survives the plot style (thin clamps to
|
// 0.13 mm / 0.50 mm hierarchy survives the plot style at its true
|
||||||
// the 1 px floor, so the ratio is the clamped-pixel ratio 1.889).
|
// ratio; the screen's 1 px floor does not reach the plot (#1749).
|
||||||
let text =
|
let text =
|
||||||
crate::io::pdf_export::pdf_stream_text(&std::fs::read(&pdf).expect("pdf written"));
|
crate::io::pdf_export::pdf_stream_text(&std::fs::read(&pdf).expect("pdf written"));
|
||||||
let tokens: Vec<&str> = text.split_whitespace().collect();
|
let tokens: Vec<&str> = text.split_whitespace().collect();
|
||||||
@@ -2931,7 +2931,7 @@ mod tests {
|
|||||||
"two layer weights in the plotted PDF: {widths:?}"
|
"two layer weights in the plotted PDF: {widths:?}"
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
(widths[1] / widths[0] - 1.889).abs() < 0.15,
|
(widths[1] / widths[0] - 50.0 / 13.0).abs() < 0.15,
|
||||||
"0.50 mm vs 0.13 mm hierarchy: {widths:?}"
|
"0.50 mm vs 0.13 mm hierarchy: {widths:?}"
|
||||||
);
|
);
|
||||||
let _ = std::fs::remove_file(&pdf);
|
let _ = std::fs::remove_file(&pdf);
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ pub fn extract_circle_instance_from_geom_indexed(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let (ch, cl) = split_ds_xyz(center[0], center[1], center[2]);
|
let (ch, cl) = split_ds_xyz(center[0], center[1], center[2]);
|
||||||
let hw = wire.line_weight_px * 0.5;
|
let hw = wire.line_weight_px.max(1.0) * 0.5;
|
||||||
let pat0 = [
|
let pat0 = [
|
||||||
wire.pattern[0],
|
wire.pattern[0],
|
||||||
wire.pattern[1],
|
wire.pattern[1],
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ pub fn extract_ellipse_instance_from_geom(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let (ch, cl) = split_ds_xyz(center[0], center[1], center[2]);
|
let (ch, cl) = split_ds_xyz(center[0], center[1], center[2]);
|
||||||
let hw = wire.line_weight_px * 0.5;
|
let hw = wire.line_weight_px.max(1.0) * 0.5;
|
||||||
let pat0 = [
|
let pat0 = [
|
||||||
wire.pattern[0],
|
wire.pattern[0],
|
||||||
wire.pattern[1],
|
wire.pattern[1],
|
||||||
|
|||||||
@@ -863,7 +863,7 @@ pub(crate) fn emit_wire_packed(
|
|||||||
wire.pattern[6],
|
wire.pattern[6],
|
||||||
wire.pattern[7],
|
wire.pattern[7],
|
||||||
];
|
];
|
||||||
let half_width = wire.line_weight_px * 0.5;
|
let half_width = wire.line_weight_px.max(1.0) * 0.5;
|
||||||
let n = wire.points.len();
|
let n = wire.points.len();
|
||||||
let seg_count = n.saturating_sub(1);
|
let seg_count = n.saturating_sub(1);
|
||||||
if seg_count == 0 {
|
if seg_count == 0 {
|
||||||
@@ -965,7 +965,7 @@ pub(crate) fn emit_wire_native(
|
|||||||
wire.pattern[6],
|
wire.pattern[6],
|
||||||
wire.pattern[7],
|
wire.pattern[7],
|
||||||
],
|
],
|
||||||
half_width: wire.line_weight_px * 0.5,
|
half_width: wire.line_weight_px.max(1.0) * 0.5,
|
||||||
pattern_length: wire.pattern_length,
|
pattern_length: wire.pattern_length,
|
||||||
draw_depth,
|
draw_depth,
|
||||||
align_end,
|
align_end,
|
||||||
|
|||||||
@@ -3589,9 +3589,11 @@ pub struct InheritStyle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convert a concrete (already layer-resolved) lineweight to display pixels.
|
/// Convert a concrete (already layer-resolved) lineweight to display pixels.
|
||||||
|
/// Kept below 1 px for thin weights so plots and SVG get the true width;
|
||||||
|
/// the GPU paths draw at least 1 px (#1749).
|
||||||
pub(crate) fn lineweight_to_px(lw: &LineWeight) -> f32 {
|
pub(crate) fn lineweight_to_px(lw: &LineWeight) -> f32 {
|
||||||
lw.millimeters()
|
lw.millimeters()
|
||||||
.map(|mm| (mm as f32 * MM_TO_PX).max(1.0))
|
.map(|mm| mm as f32 * MM_TO_PX)
|
||||||
.unwrap_or(1.0)
|
.unwrap_or(1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user