feat: introduce SVG-based complex vector shapes
- Added `SvgShape` variant to `VectorShape` in `hcie-protocol`, allowing for SVG rendering of complex shapes. - Updated serialization to skip old shape variants for backward compatibility. - Implemented SVG generation functions in `svg_templates.rs` for various shapes (arrow, star, rhombus, etc.). - Created `svg_render.rs` to parse SVG strings and tessellate paths using `usvg`. - Modified rendering logic in `hcie-vector` to handle `SvgShape` and integrate with existing shape rendering. - Updated shape creation API in `hcie-engine-api` to support SVG shapes. - Enhanced property editing and shape synchronization in both `hcie-egui-app` and `hcie-iced-app` to accommodate new SVG shapes. - Added comprehensive documentation for new features and changes.
This commit is contained in:
@@ -352,6 +352,7 @@ pub enum VectorShape {
|
||||
#[serde(default = "default_hardness")]
|
||||
hardness: f32,
|
||||
},
|
||||
#[serde(skip_serializing)]
|
||||
Arrow {
|
||||
x1: f32,
|
||||
y1: f32,
|
||||
@@ -371,6 +372,7 @@ pub enum VectorShape {
|
||||
#[serde(default)]
|
||||
thick: bool,
|
||||
},
|
||||
#[serde(skip_serializing)]
|
||||
Star {
|
||||
x1: f32,
|
||||
y1: f32,
|
||||
@@ -411,6 +413,7 @@ pub enum VectorShape {
|
||||
#[serde(default)]
|
||||
sides: u32,
|
||||
},
|
||||
#[serde(skip_serializing)]
|
||||
Rhombus {
|
||||
x1: f32,
|
||||
y1: f32,
|
||||
@@ -428,6 +431,7 @@ pub enum VectorShape {
|
||||
#[serde(default = "default_hardness")]
|
||||
hardness: f32,
|
||||
},
|
||||
#[serde(skip_serializing)]
|
||||
Cylinder {
|
||||
x1: f32,
|
||||
y1: f32,
|
||||
@@ -445,6 +449,7 @@ pub enum VectorShape {
|
||||
#[serde(default = "default_hardness")]
|
||||
hardness: f32,
|
||||
},
|
||||
#[serde(skip_serializing)]
|
||||
Heart {
|
||||
x1: f32,
|
||||
y1: f32,
|
||||
@@ -462,6 +467,7 @@ pub enum VectorShape {
|
||||
#[serde(default = "default_hardness")]
|
||||
hardness: f32,
|
||||
},
|
||||
#[serde(skip_serializing)]
|
||||
Bubble {
|
||||
x1: f32,
|
||||
y1: f32,
|
||||
@@ -479,6 +485,7 @@ pub enum VectorShape {
|
||||
#[serde(default = "default_hardness")]
|
||||
hardness: f32,
|
||||
},
|
||||
#[serde(skip_serializing)]
|
||||
Gear {
|
||||
x1: f32,
|
||||
y1: f32,
|
||||
@@ -496,6 +503,7 @@ pub enum VectorShape {
|
||||
#[serde(default = "default_hardness")]
|
||||
hardness: f32,
|
||||
},
|
||||
#[serde(skip_serializing)]
|
||||
Cross {
|
||||
x1: f32,
|
||||
y1: f32,
|
||||
@@ -513,6 +521,7 @@ pub enum VectorShape {
|
||||
#[serde(default = "default_hardness")]
|
||||
hardness: f32,
|
||||
},
|
||||
#[serde(skip_serializing)]
|
||||
Crescent {
|
||||
x1: f32,
|
||||
y1: f32,
|
||||
@@ -530,6 +539,7 @@ pub enum VectorShape {
|
||||
#[serde(default = "default_hardness")]
|
||||
hardness: f32,
|
||||
},
|
||||
#[serde(skip_serializing)]
|
||||
Bolt {
|
||||
x1: f32,
|
||||
y1: f32,
|
||||
@@ -547,6 +557,7 @@ pub enum VectorShape {
|
||||
#[serde(default = "default_hardness")]
|
||||
hardness: f32,
|
||||
},
|
||||
#[serde(skip_serializing)]
|
||||
Arrow4 {
|
||||
x1: f32,
|
||||
y1: f32,
|
||||
@@ -564,6 +575,25 @@ pub enum VectorShape {
|
||||
#[serde(default = "default_hardness")]
|
||||
hardness: f32,
|
||||
},
|
||||
SvgShape {
|
||||
x1: f32,
|
||||
y1: f32,
|
||||
x2: f32,
|
||||
y2: f32,
|
||||
kind: String,
|
||||
svg: String,
|
||||
stroke: f32,
|
||||
color: [u8; 4],
|
||||
#[serde(default = "default_fill_color")]
|
||||
fill_color: [u8; 4],
|
||||
fill: bool,
|
||||
#[serde(default)]
|
||||
angle: f32,
|
||||
#[serde(default = "default_opacity")]
|
||||
opacity: f32,
|
||||
#[serde(default = "default_hardness")]
|
||||
hardness: f32,
|
||||
},
|
||||
FreePath {
|
||||
pts: Vec<[f32; 2]>,
|
||||
closed: bool,
|
||||
@@ -1986,6 +2016,7 @@ impl VectorShape {
|
||||
| VectorShape::Cross { x1, y1, x2, y2, .. }
|
||||
| VectorShape::Crescent { x1, y1, x2, y2, .. }
|
||||
| VectorShape::Arrow4 { x1, y1, x2, y2, .. }
|
||||
| VectorShape::SvgShape { x1, y1, x2, y2, .. }
|
||||
| VectorShape::Bolt { x1, y1, x2, y2, .. } => (*x1, *y1, *x2, *y2),
|
||||
VectorShape::FreePath { pts, .. } => {
|
||||
let x1 = pts.iter().map(|p| p[0]).fold(f32::INFINITY, f32::min);
|
||||
@@ -2024,6 +2055,7 @@ impl VectorShape {
|
||||
| VectorShape::Crescent { color, .. }
|
||||
| VectorShape::Arrow4 { color, .. }
|
||||
| VectorShape::Bolt { color, .. }
|
||||
| VectorShape::SvgShape { color, .. }
|
||||
| VectorShape::FreePath { color, .. } => *color,
|
||||
}
|
||||
}
|
||||
@@ -2045,6 +2077,7 @@ impl VectorShape {
|
||||
| VectorShape::Crescent { color, .. }
|
||||
| VectorShape::Arrow4 { color, .. }
|
||||
| VectorShape::Bolt { color, .. }
|
||||
| VectorShape::SvgShape { color, .. }
|
||||
| VectorShape::FreePath { color, .. } => *color = new_color,
|
||||
}
|
||||
}
|
||||
@@ -2066,6 +2099,7 @@ impl VectorShape {
|
||||
| VectorShape::Crescent { opacity, .. }
|
||||
| VectorShape::Arrow4 { opacity, .. }
|
||||
| VectorShape::Bolt { opacity, .. }
|
||||
| VectorShape::SvgShape { opacity, .. }
|
||||
| VectorShape::FreePath { opacity, .. } => *opacity,
|
||||
}
|
||||
}
|
||||
@@ -2088,6 +2122,7 @@ impl VectorShape {
|
||||
| VectorShape::Crescent { opacity, .. }
|
||||
| VectorShape::Arrow4 { opacity, .. }
|
||||
| VectorShape::Bolt { opacity, .. }
|
||||
| VectorShape::SvgShape { opacity, .. }
|
||||
| VectorShape::FreePath { opacity, .. } => *opacity = clamped,
|
||||
}
|
||||
}
|
||||
@@ -2109,6 +2144,7 @@ impl VectorShape {
|
||||
| VectorShape::Crescent { hardness, .. }
|
||||
| VectorShape::Arrow4 { hardness, .. }
|
||||
| VectorShape::Bolt { hardness, .. }
|
||||
| VectorShape::SvgShape { hardness, .. }
|
||||
| VectorShape::FreePath { hardness, .. } => *hardness,
|
||||
}
|
||||
}
|
||||
@@ -2131,6 +2167,7 @@ impl VectorShape {
|
||||
| VectorShape::Crescent { hardness, .. }
|
||||
| VectorShape::Arrow4 { hardness, .. }
|
||||
| VectorShape::Bolt { hardness, .. }
|
||||
| VectorShape::SvgShape { hardness, .. }
|
||||
| VectorShape::FreePath { hardness, .. } => *hardness = clamped,
|
||||
}
|
||||
}
|
||||
@@ -2152,6 +2189,7 @@ impl VectorShape {
|
||||
| VectorShape::Crescent { stroke, .. }
|
||||
| VectorShape::Arrow4 { stroke, .. }
|
||||
| VectorShape::Bolt { stroke, .. }
|
||||
| VectorShape::SvgShape { stroke, .. }
|
||||
| VectorShape::FreePath { stroke, .. } => *stroke,
|
||||
}
|
||||
}
|
||||
@@ -2174,6 +2212,7 @@ impl VectorShape {
|
||||
| VectorShape::Crescent { stroke, .. }
|
||||
| VectorShape::Arrow4 { stroke, .. }
|
||||
| VectorShape::Bolt { stroke, .. }
|
||||
| VectorShape::SvgShape { stroke, .. }
|
||||
| VectorShape::FreePath { stroke, .. } => *stroke = clamped,
|
||||
}
|
||||
}
|
||||
@@ -2387,6 +2426,7 @@ impl VectorShape {
|
||||
| VectorShape::Cross { angle, .. }
|
||||
| VectorShape::Crescent { angle, .. }
|
||||
| VectorShape::Arrow4 { angle, .. }
|
||||
| VectorShape::SvgShape { angle, .. }
|
||||
| VectorShape::Bolt { angle, .. } => *angle,
|
||||
VectorShape::FreePath { .. } => 0.0,
|
||||
}
|
||||
@@ -2408,6 +2448,7 @@ impl VectorShape {
|
||||
| VectorShape::Cross { angle, .. }
|
||||
| VectorShape::Crescent { angle, .. }
|
||||
| VectorShape::Arrow4 { angle, .. }
|
||||
| VectorShape::SvgShape { angle, .. }
|
||||
| VectorShape::Bolt { angle, .. } => {
|
||||
*angle += delta;
|
||||
}
|
||||
@@ -2431,6 +2472,7 @@ impl VectorShape {
|
||||
| VectorShape::Cross { angle, .. }
|
||||
| VectorShape::Crescent { angle, .. }
|
||||
| VectorShape::Arrow4 { angle, .. }
|
||||
| VectorShape::SvgShape { angle, .. }
|
||||
| VectorShape::Bolt { angle, .. } => {
|
||||
*angle = new_angle;
|
||||
}
|
||||
@@ -2454,6 +2496,7 @@ impl VectorShape {
|
||||
| VectorShape::Cross { angle, .. }
|
||||
| VectorShape::Crescent { angle, .. }
|
||||
| VectorShape::Arrow4 { angle, .. }
|
||||
| VectorShape::SvgShape { angle, .. }
|
||||
| VectorShape::Bolt { angle, .. } => Some(angle),
|
||||
VectorShape::FreePath { .. } => None,
|
||||
}
|
||||
@@ -2474,6 +2517,7 @@ impl VectorShape {
|
||||
| VectorShape::Cross { fill, .. }
|
||||
| VectorShape::Crescent { fill, .. }
|
||||
| VectorShape::Arrow4 { fill, .. }
|
||||
| VectorShape::SvgShape { fill, .. }
|
||||
| VectorShape::Bolt { fill, .. } => *fill,
|
||||
_ => false,
|
||||
}
|
||||
@@ -2494,6 +2538,7 @@ impl VectorShape {
|
||||
| VectorShape::Cross { fill_color, .. }
|
||||
| VectorShape::Crescent { fill_color, .. }
|
||||
| VectorShape::Arrow4 { fill_color, .. }
|
||||
| VectorShape::SvgShape { fill_color, .. }
|
||||
| VectorShape::Bolt { fill_color, .. } => Some(*fill_color),
|
||||
_ => None,
|
||||
}
|
||||
@@ -2514,6 +2559,7 @@ impl VectorShape {
|
||||
| VectorShape::Cross { fill, .. }
|
||||
| VectorShape::Crescent { fill, .. }
|
||||
| VectorShape::Arrow4 { fill, .. }
|
||||
| VectorShape::SvgShape { fill, .. }
|
||||
| VectorShape::Bolt { fill, .. } => Some(*fill),
|
||||
_ => None,
|
||||
}
|
||||
@@ -2534,6 +2580,7 @@ impl VectorShape {
|
||||
| VectorShape::Cross { fill, .. }
|
||||
| VectorShape::Crescent { fill, .. }
|
||||
| VectorShape::Arrow4 { fill, .. }
|
||||
| VectorShape::SvgShape { fill, .. }
|
||||
| VectorShape::Bolt { fill, .. } => Some(fill),
|
||||
_ => None,
|
||||
}
|
||||
@@ -2554,6 +2601,7 @@ impl VectorShape {
|
||||
| VectorShape::Cross { fill_color, .. }
|
||||
| VectorShape::Crescent { fill_color, .. }
|
||||
| VectorShape::Arrow4 { fill_color, .. }
|
||||
| VectorShape::SvgShape { fill_color, .. }
|
||||
| VectorShape::Bolt { fill_color, .. } => Some(fill_color),
|
||||
_ => None,
|
||||
}
|
||||
@@ -2576,6 +2624,7 @@ impl VectorShape {
|
||||
| VectorShape::Crescent { stroke, .. }
|
||||
| VectorShape::Arrow4 { stroke, .. }
|
||||
| VectorShape::Bolt { stroke, .. }
|
||||
| VectorShape::SvgShape { stroke, .. }
|
||||
| VectorShape::FreePath { stroke, .. } => Some(stroke),
|
||||
}
|
||||
}
|
||||
@@ -2659,6 +2708,7 @@ impl VectorShape {
|
||||
| VectorShape::Cross { x1, y1, x2, y2, .. }
|
||||
| VectorShape::Crescent { x1, y1, x2, y2, .. }
|
||||
| VectorShape::Arrow4 { x1, y1, x2, y2, .. }
|
||||
| VectorShape::SvgShape { x1, y1, x2, y2, .. }
|
||||
| VectorShape::Bolt { x1, y1, x2, y2, .. } => (x1, y1, x2, y2),
|
||||
VectorShape::FreePath { .. } => unreachable!("coords_mut not valid for FreePath"),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user