diff --git a/src/entities/spline.rs b/src/entities/spline.rs index 908085e63..55f27a0fe 100644 --- a/src/entities/spline.rs +++ b/src/entities/spline.rs @@ -37,11 +37,24 @@ fn to_truck(spl: &Spline) -> TruckEntity { let v_start = builder::vertex(p_start); let v_end = builder::vertex(p_end); let edge = Edge::new(&v_start, &v_end, Curve::BSplineCurve(bspline)); + + // Expose fit_points (preferred) or control_points as key_vertices so that + // Endpoint/Midpoint snap can reach spline construction points. + let snap_source = if !spl.fit_points.is_empty() { + &spl.fit_points + } else { + &spl.control_points + }; + let key_vertices: Vec<[f32; 3]> = snap_source + .iter() + .map(|p| [p.x as f32, p.y as f32, p.z as f32]) + .collect(); + TruckEntity { object: TruckObject::Curve(edge), snap_pts: vec![], tangent_geoms: vec![], - key_vertices: vec![], + key_vertices, } } diff --git a/src/entities/text.rs b/src/entities/text.rs index 47c94d958..74c7ad1e1 100644 --- a/src/entities/text.rs +++ b/src/entities/text.rs @@ -54,12 +54,17 @@ fn to_truck(t: &Text, document: &acadrust::CadDocument) -> TruckEntity { ); let resolved_style = resolve_text_style(&t.style, document); let font_name = resolved_style.font_name; - let width_factor = (if t.width_factor > 0.0 { - t.width_factor as f32 - } else { - 1.0 - } * resolved_style.width_factor.max(0.01)) + let base_wf = (if t.width_factor > 0.0 { t.width_factor as f32 } else { 1.0 } + * resolved_style.width_factor.max(0.01)) .clamp(0.01, 100.0); + // is_backward mirrors text left-right via negative width factor. + let width_factor = if resolved_style.is_backward { -base_wf } else { base_wf }; + // is_upside_down rotates 180° around the insertion point. + let rotation = if resolved_style.is_upside_down { + t.rotation as f32 + std::f32::consts::PI + } else { + t.rotation as f32 + }; let oblique_angle = t.oblique_angle as f32 + resolved_style.oblique_angle; let anchor = match ( &t.horizontal_alignment, @@ -96,7 +101,7 @@ fn to_truck(t: &Text, document: &acadrust::CadDocument) -> TruckEntity { } else { (0.0, 0.0) }; - let (cos_r, sin_r) = ((t.rotation as f32).cos(), (t.rotation as f32).sin()); + let (cos_r, sin_r) = (rotation.cos(), rotation.sin()); let origin = [ anchor[0] - (anchor_local_x * cos_r - anchor_local_y * sin_r), anchor[1] - (anchor_local_x * sin_r + anchor_local_y * cos_r), @@ -105,7 +110,7 @@ fn to_truck(t: &Text, document: &acadrust::CadDocument) -> TruckEntity { let strokes_2d = cxf::tessellate_text_ex( origin, t.height as f32, - t.rotation as f32, + rotation, width_factor, oblique_angle, &font_name, diff --git a/src/entities/text_support.rs b/src/entities/text_support.rs index 078bdc04c..067cf07e5 100644 --- a/src/entities/text_support.rs +++ b/src/entities/text_support.rs @@ -6,6 +6,8 @@ pub struct ResolvedTextStyle { pub font_name: String, pub width_factor: f32, pub oblique_angle: f32, + pub is_backward: bool, + pub is_upside_down: bool, } pub fn resolve_text_style(style_name: &str, document: &CadDocument) -> ResolvedTextStyle { @@ -45,6 +47,8 @@ pub fn resolve_text_style(style_name: &str, document: &CadDocument) -> ResolvedT font_name, width_factor: style.map(|s| s.width_factor as f32).unwrap_or(1.0), oblique_angle: style.map(|s| s.oblique_angle as f32).unwrap_or(0.0), + is_backward: style.map(|s| s.is_backward()).unwrap_or(false), + is_upside_down: style.map(|s| s.is_upside_down()).unwrap_or(false), } } @@ -61,7 +65,7 @@ pub fn text_local_bounds( let font = cxf::get_font(font_name); let scale = height / 9.0; - let wf = width_factor.clamp(0.01, 100.0); + let wf = width_factor.abs().clamp(0.01, 100.0); let ob = oblique_angle.tan(); let mut cursor_x = 0.0_f32; let mut min_x = f32::INFINITY; diff --git a/src/scene/cxf.rs b/src/scene/cxf.rs index 81b5400d2..687dc2b10 100644 --- a/src/scene/cxf.rs +++ b/src/scene/cxf.rs @@ -215,7 +215,12 @@ pub fn tessellate_text_ex( let font = get_font(font_name); let scale = height / 9.0; - let wf = width_factor.clamp(0.01, 100.0); + // Negative width_factor produces mirrored (backward) text. + let wf = if width_factor < 0.0 { + width_factor.clamp(-100.0, -0.01) + } else { + width_factor.clamp(0.01, 100.0) + }; let ob = oblique_angle.tan(); let (cos_r, sin_r) = (rotation.cos(), rotation.sin());