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:
2026-07-19 02:44:59 +03:00
parent e90cb2d31d
commit 5632c916ee
17 changed files with 1124 additions and 300 deletions
+55
View File
@@ -415,6 +415,39 @@ pub struct Engine {
std::sync::Arc<std::sync::Mutex<Vec<crate::stroke_cache::PendingHistoryItem>>>,
}
/// Create a `VectorShape::SvgShape` from a shape kind name and parameter map.
///
/// The `kind` string must be one of: "arrow", "star", "rhombus", "cylinder",
/// "heart", "bubble", "gear", "cross", "crescent", "bolt", "arrow4".
///
/// Shape-specific parameters (e.g. `points`, `inner_radius`, `thick`) are passed
/// via `params`.
pub fn create_vector_shape(
kind: &str,
x1: f32,
y1: f32,
x2: f32,
y2: f32,
params: &std::collections::HashMap<String, f32>,
) -> VectorShape {
let svg = hcie_vector::svg_templates::create_svg(kind, params);
VectorShape::SvgShape {
x1,
y1,
x2,
y2,
kind: kind.to_string(),
svg,
stroke: 2.0,
color: [0, 0, 0, 255],
fill_color: [255, 255, 255, 255],
fill: true,
angle: 0.0,
opacity: 1.0,
hardness: 1.0,
}
}
impl Engine {
/// Create a new engine with a default transparent document.
///
@@ -4038,6 +4071,14 @@ fn set_shape_color(
*color = stroke_color;
*fc = fill_color;
}
SvgShape {
color,
fill_color: fc,
..
} => {
*color = stroke_color;
*fc = fill_color;
}
FreePath {
color,
fill_color: fc,
@@ -4147,6 +4188,12 @@ fn move_shape(
*x2 += dx;
*y2 += dy;
}
SvgShape { x1, y1, x2, y2, .. } => {
*x1 += dx;
*y1 += dy;
*x2 += dx;
*y2 += dy;
}
FreePath { pts, .. } => {
for p in pts.iter_mut() {
p[0] += dx;
@@ -4279,6 +4326,14 @@ fn scale_shape(shape: &mut hcie_protocol::VectorShape, scale_x: f32, scale_y: f3
*x2 = cx + (*x2 - cx) * scale_x;
*y2 = cy + (*y2 - cy) * scale_y;
}
SvgShape { x1, y1, x2, y2, .. } => {
let cx = (*x1 + *x2) / 2.0;
let cy = (*y1 + *y2) / 2.0;
*x1 = cx + (*x1 - cx) * scale_x;
*y1 = cy + (*y1 - cy) * scale_y;
*x2 = cx + (*x2 - cx) * scale_x;
*y2 = cy + (*y2 - cy) * scale_y;
}
FreePath { pts, .. } => {
if pts.is_empty() {
return;