mirror of
https://github.com/zap-proto/rust.git
synced 2026-10-30 15:04:23 +00:00
Two pre-existing CI failures (unrelated to codegen/install-zap): - minrust 1.81: quickcheck 1.1.0 pulls rand 0.10 -> rand_core 0.10.1, whose Cargo.toml requires the edition2024 feature (unstable on Cargo 1.81). Pin quickcheck to =1.0.3 (last version on rand 0.8 / rand_core 0.6.4) — within MSRV, no major bump. Fresh-resolve verified: rand_core 0.10.1 leaves the graph. - formatting: ran 'cargo +nightly fmt --all'; the CI check (--check --unstable-features --error-on-unformatted, nightly) now passes.
150 lines
4.7 KiB
Rust
150 lines
4.7 KiB
Rust
use fill_random_values::Filler;
|
|
use zap::dynamic_value;
|
|
|
|
zap::generated_code!(pub mod shapes_zap);
|
|
zap::generated_code!(pub mod fill_zap);
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
struct Viewport {
|
|
// center
|
|
x: f64,
|
|
y: f64,
|
|
|
|
width: f64,
|
|
height: f64,
|
|
}
|
|
|
|
impl Viewport {
|
|
fn new(x: f64, y: f64, width: f64, height: f64) -> Self {
|
|
Self {
|
|
x,
|
|
y,
|
|
width,
|
|
height,
|
|
}
|
|
}
|
|
|
|
fn upper_left(&self) -> (f64, f64) {
|
|
(self.x - (self.width / 2.0), self.y - (self.height / 2.0))
|
|
}
|
|
|
|
fn denormalize(&self, x: f64, y: f64) -> (f64, f64) {
|
|
let (ulx, uly) = self.upper_left();
|
|
(ulx + (x * self.width), uly + (y * self.height))
|
|
}
|
|
|
|
fn subview(&self, x: f64, y: f64, w: f64, h: f64) -> Self {
|
|
let (ulx, uly) = self.upper_left();
|
|
Self {
|
|
x: ulx + (x * self.width),
|
|
y: uly + (y * self.width),
|
|
width: w * self.width,
|
|
height: h * self.height,
|
|
}
|
|
}
|
|
|
|
fn diag_len(&self) -> f64 {
|
|
(self.width * self.width + self.height * self.height).sqrt()
|
|
}
|
|
}
|
|
|
|
fn color_to_svg(color: shapes_zap::color::Reader) -> String {
|
|
format!(
|
|
"rgb({}, {}, {})",
|
|
color.get_red(),
|
|
color.get_green(),
|
|
color.get_blue()
|
|
)
|
|
}
|
|
|
|
struct SvgBuilder {
|
|
counter: u32,
|
|
}
|
|
|
|
impl SvgBuilder {
|
|
fn new() -> Self {
|
|
Self { counter: 0 }
|
|
}
|
|
|
|
fn canvas_to_svg(
|
|
&mut self,
|
|
view: Viewport,
|
|
canvas: shapes_zap::canvas::Reader,
|
|
) -> ::zap::Result<String> {
|
|
if !canvas.has_background_color() {
|
|
// probably recursion depth was exceeded
|
|
return Ok("".into());
|
|
}
|
|
let bc = color_to_svg(canvas.get_background_color()?);
|
|
let (vx, vy) = view.upper_left();
|
|
let mut result = format!(
|
|
"<rect x=\"{}\" y=\"{}\" width=\"{}\" height=\"{}\" fill=\"{bc}\" />\n",
|
|
vx, vy, view.width, view.height
|
|
);
|
|
let clipr = format!("clip-{}", self.counter);
|
|
self.counter += 1;
|
|
result += &format!("<defs><clipPath id=\"{clipr}\"><rect x=\"{}\" y=\"{}\" width=\"{}\" height=\"{}\"/></clipPath></defs>\n", vx, vy, view.width, view.height);
|
|
result += &format!("<g clip-path=\"url(#{clipr})\">\n");
|
|
for line in canvas.get_lines()? {
|
|
if line.has_start() {
|
|
let start = line.get_start()?;
|
|
let (x1, y1) = view.denormalize(start.get_x(), start.get_y());
|
|
let end = line.get_end()?;
|
|
let (x2, y2) = view.denormalize(end.get_x(), end.get_y());
|
|
let c = color_to_svg(line.get_color()?);
|
|
let sw = line.get_thickness() * view.diag_len() / 100.0;
|
|
result +=
|
|
&format!("<line x1=\"{x1}\" y1=\"{y1}\" x2=\"{x2}\" y2=\"{y2}\" stroke=\"{c}\" stroke-width=\"{sw}\" stroke-linecap=\"round\" clip-path=\"url(#{clipr})\"/>\n");
|
|
}
|
|
}
|
|
|
|
for circ in canvas.get_circles()? {
|
|
if circ.has_center() {
|
|
let center = circ.get_center()?;
|
|
let (cx, cy) = view.denormalize(center.get_x(), center.get_y());
|
|
let r = circ.get_radius() * view.diag_len();
|
|
let c = color_to_svg(circ.get_fill_color()?);
|
|
result += &format!("<circle cx=\"{cx}\" cy=\"{cy}\" r=\"{r}\" fill=\"{c}\" clip-path=\"url(#{clipr})\"/>\n");
|
|
}
|
|
}
|
|
|
|
for sc in canvas.get_subcanvases()? {
|
|
let center = sc.get_center()?;
|
|
let v1 = view.subview(
|
|
center.get_x(),
|
|
center.get_y(),
|
|
sc.get_width(),
|
|
sc.get_height(),
|
|
);
|
|
if sc.has_canvas() {
|
|
result += &self.canvas_to_svg(v1, sc.get_canvas()?)?;
|
|
}
|
|
}
|
|
result += "</g>\n";
|
|
Ok(result)
|
|
}
|
|
|
|
fn base_to_svg(&mut self, canvas: shapes_zap::canvas::Reader) -> ::zap::Result<String> {
|
|
let view = Viewport::new(256.0, 256.0, 512.0, 512.0);
|
|
let c = self.canvas_to_svg(view, canvas)?;
|
|
Ok(format!(
|
|
r#"<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512">
|
|
{c}
|
|
</svg>"#
|
|
))
|
|
}
|
|
}
|
|
|
|
pub fn main() {
|
|
let mut message = ::zap::message::Builder::new_default();
|
|
let mut canvas = message.init_root::<shapes_zap::canvas::Builder>();
|
|
|
|
let mut filler = Filler::new(::rand::rng(), 10);
|
|
let dynamic: dynamic_value::Builder = canvas.reborrow().into();
|
|
filler.fill(dynamic.downcast()).unwrap();
|
|
|
|
let reader = canvas.into_reader();
|
|
let mut svg_builder = SvgBuilder::new();
|
|
println!("{}", svg_builder.base_to_svg(reader).unwrap());
|
|
}
|