use crate::renderer::GpuRenderer;
use crate::types::DrawCall;
use crate::vertex::{CustomStrokeVertexConstructor, InstanceData, Vertex};
use cvkg_core::Renderer;
use lyon::tessellation::{BuffersBuilder, StrokeOptions, StrokeTessellator, VertexBuffers};
use std::hash::Hasher;
impl GpuRenderer {
pub fn stroke_path_impl(
&mut self,
path: &lyon::path::Path,
color: [f32; 4],
stroke_width: f32,
) {
let c = self.apply_opacity(color);
let base_vertex_idx = self.vertices.len() as u32;
let base_index_idx = self.indices.len() as u32;
let path_hash = {
let mut h = std::collections::hash_map::DefaultHasher::new();
let num_elements = path.iter().count();
std::hash::Hash::hash(&num_elements, &mut h);
std::hash::Hash::hash(&stroke_width.to_bits(), &mut h);
h.finish()
};
let (vert_count, idx_count) = match self.path_geometry_cache.get(&path_hash) {
Some((cached_verts, cached_indices)) => {
self.vertices.extend_from_slice(cached_verts);
for idx in cached_indices {
self.indices.push(base_vertex_idx + *idx);
}
(cached_verts.len(), cached_indices.len())
}
None => {
let mut tessellator = StrokeTessellator::new();
let mut buffers: VertexBuffers<Vertex, u32> = VertexBuffers::new();
let result = tessellator.tessellate_path(
path,
&StrokeOptions::default().with_line_width(stroke_width),
&mut BuffersBuilder::new(
&mut buffers,
CustomStrokeVertexConstructor {
color: c,
clip: [0.0, 0.0, 0.0, 0.0],
path_length: 1.0,
},
),
);
if let Err(e) = result {
tracing::warn!("Failed to tessellate stroke path: {:?}", e);
return;
}
let vert_count = buffers.vertices.len();
let idx_count = buffers.indices.len();
let cached_verts = buffers.vertices.clone();
let cached_indices = buffers.indices.clone();
self.path_geometry_cache
.put(path_hash, (cached_verts, cached_indices));
self.vertices.extend(buffers.vertices);
for idx in &buffers.indices {
self.indices.push(base_vertex_idx + *idx);
}
(vert_count, idx_count)
}
};
let material = self.current_material();
let tid = self.get_texture_id("__mega_heim");
if self.draw_calls.last().is_none()
|| self.current_texture_id != tid
|| self.draw_calls.last().unwrap().scissor_rect != self.clip_stack.last().copied()
|| self.draw_calls.last().unwrap().material != material
{
self.current_texture_id = tid;
let (translation, scale, rotation, _, _) = self.current_transform();
self.instance_data.push(InstanceData {
translation,
scale,
rotation,
blur_radius: 0.0,
ior_override: 0.0,
glass_intensity: 1.0,
});
self.draw_calls.push(DrawCall {
target_id: None,
panel_id: self.current_panel_id,
texture_id: tid,
scissor_rect: self.clip_stack.last().copied(),
index_start: base_index_idx,
index_count: idx_count as u32,
instance_count: 1,
material,
instance_start: (self.instance_data.len() - 1) as u32,
draw_order: 0,
});
} else {
if let Some(last) = self.draw_calls.last_mut() {
last.index_count += idx_count as u32;
}
}
}
}