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 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 5.5 committed 2026-10-14 12:47:26 +03:00
1 parent 2c062daa03
commit 2ba2d1c0a7
5 files changed
+10 -8

No files matched your search

+3 -3
View File
@@ -2907,8 +2907,8 @@ mod tests {
assert_eq!(response["status"], "completed", "{response}");
// 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
// the 1 px floor, so the ratio is the clamped-pixel ratio 1.889).
// 0.13 mm / 0.50 mm hierarchy survives the plot style at its true
// ratio; the screen's 1 px floor does not reach the plot (#1749).
let text =
crate::io::pdf_export::pdf_stream_text(&std::fs::read(&pdf).expect("pdf written"));
let tokens: Vec<&str> = text.split_whitespace().collect();
@@ -2931,7 +2931,7 @@ mod tests {
"two layer weights in the plotted PDF: {widths:?}"
);
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:?}"
);
let _ = std::fs::remove_file(&pdf);
+1 -1
View File
@@ -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 hw = wire.line_weight_px * 0.5;
let hw = wire.line_weight_px.max(1.0) * 0.5;
let pat0 = [
wire.pattern[0],
wire.pattern[1],
+1 -1
View File
@@ -235,7 +235,7 @@ pub fn extract_ellipse_instance_from_geom(
}
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 = [
wire.pattern[0],
wire.pattern[1],
+2 -2
View File
@@ -863,7 +863,7 @@ pub(crate) fn emit_wire_packed(
wire.pattern[6],
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 seg_count = n.saturating_sub(1);
if seg_count == 0 {
@@ -965,7 +965,7 @@ pub(crate) fn emit_wire_native(
wire.pattern[6],
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,
draw_depth,
align_end,
+3 -1
View File
@@ -3589,9 +3589,11 @@ pub struct InheritStyle {
}
/// 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 {
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)
}