forked from 1b-agent/opencadstudio-upstream
fix: Spline snap points and TextStyle backward/upside-down rendering
Spline entities now expose fit_points (or control_points when no fit points are defined) as key_vertices, enabling Endpoint and Midpoint snap to reach spline construction points. TextStyle is_backward flag is applied by negating the width_factor, producing horizontally mirrored text. is_upside_down rotates the text 180°. Both tessellate_text_ex and text_local_bounds now handle negative width_factor without clamping it to zero. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
1 parent
045ab96eab
commit
5216c247c2
4 files changed
+37
-10
No files matched your search
+14
-1
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-7
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
+6
-1
@@ -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());
|
||||
|
||||
|
||||
Reference in new issue
Block a user