This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

♻️ Factor random_* into its own module, include and fixup wasm module

+385 -330
+1 -1
src/examples.rs
··· 31 31 let red_circle_in = 32 32 Region::from_topright(draw_in.topright().translated(-3, 0), (4, 3)).unwrap(); 33 33 34 - let red_circle_at = red_circle_in.random_point_within(); 34 + let red_circle_at = red_circle_in.random_point(); 35 35 36 36 let red_dot_layer = canvas.new_layer("red dot"); 37 37 let mut red_dot_friends = Layer::new("red dot friends");
-21
src/geometry/region.rs
··· 25 25 self.iter().filter(|Point(x, y)| x >= y) 26 26 } 27 27 28 - pub fn random_point_within(&self) -> Point { 29 - Point::from(self.random_coordinates_within()) 30 - } 31 - 32 - pub fn random_point_within_except(&self, except: &Region) -> Point { 33 - // XXX this is probably not a good idea lmao 34 - loop { 35 - let point = self.random_point_within(); 36 - if !except.contains(&point) { 37 - return point; 38 - } 39 - } 40 - } 41 - 42 28 pub fn ensure_nonempty(&self) -> Result<()> { 43 29 if self.width() == 0 || self.height() == 0 { 44 30 return Err(format_err!("Region {} is empty", self)); ··· 172 158 } else { 173 159 self 174 160 } 175 - } 176 - 177 - pub fn random_coordinates_within(&self) -> (i32, i32) { 178 - ( 179 - rand::thread_rng().gen_range(self.start.0..self.end.0) as i32, 180 - rand::thread_rng().gen_range(self.start.1..self.end.1) as i32, 181 - ) 182 161 } 183 162 184 163 pub fn from_origin(end: Point) -> Result<Self> {
-189
src/graphics/canvas.rs
··· 218 218 Ok(()) 219 219 } 220 220 221 - pub fn random_layer(&self, name: &str) -> Layer { 222 - self.random_layer_within(name, &self.world_region) 223 - } 224 - 225 - pub fn random_object(&self) -> Object { 226 - self.random_object_within(&self.world_region) 227 - } 228 - 229 221 pub fn add_or_replace_layer(&mut self, layer: Layer) { 230 222 if let Some(existing_layer) = self.layer_safe(&layer.name) { 231 223 existing_layer.replace(layer); ··· 234 226 } 235 227 } 236 228 237 - pub fn random_layer_within(&self, name: &str, region: &Region) -> Layer { 238 - let mut objects: HashMap<String, ColoredObject> = HashMap::new(); 239 - let number_of_objects = rand::thread_rng().gen_range(self.objects_count_range.clone()); 240 - for i in 0..number_of_objects { 241 - let object = self.random_object_within(region); 242 - let hatchable = object.hatchable(); 243 - objects.insert( 244 - format!("{}#{}", name, i), 245 - object.color(if hatchable { 246 - Fill::random_hatches(self.background) 247 - } else { 248 - Fill::random_solid(self.background) 249 - }), 250 - ); 251 - } 252 - Layer { 253 - object_sizes: self.object_sizes, 254 - name: name.to_string(), 255 - objects, 256 - _render_cache: None, 257 - hidden: false, 258 - } 259 - } 260 - 261 - pub fn random_linelikes(&self, layer_name: &str) -> Layer { 262 - self.random_linelikes_within(layer_name, &self.world_region) 263 - } 264 - 265 - pub fn n_random_linelikes_within( 266 - &self, 267 - layer_name: &str, 268 - region: &Region, 269 - count: usize, 270 - ) -> Layer { 271 - let mut objects: HashMap<String, ColoredObject> = HashMap::new(); 272 - for i in 0..count { 273 - let object = self.random_linelike_within(region); 274 - let hatchable = object.fillable(); 275 - objects.insert( 276 - format!("{}#{}", layer_name, i), 277 - ColoredObject::from(( 278 - object, 279 - if rand::thread_rng().gen_bool(0.5) { 280 - Some(Fill::random_solid(self.background)) 281 - } else { 282 - None 283 - }, 284 - )), 285 - ); 286 - } 287 - Layer { 288 - object_sizes: self.object_sizes, 289 - name: layer_name.to_owned(), 290 - objects, 291 - _render_cache: None, 292 - hidden: false, 293 - } 294 - } 295 - 296 - pub fn random_linelikes_within(&self, layer_name: &str, region: &Region) -> Layer { 297 - let number_of_objects = rand::thread_rng().gen_range(self.objects_count_range.clone()); 298 - self.n_random_linelikes_within(layer_name, region, number_of_objects) 299 - } 300 - 301 - pub fn random_object_within(&self, region: &Region) -> Object { 302 - let start = self.random_point(region); 303 - match rand::thread_rng().gen_range(1..=7) { 304 - 1 => self.random_polygon(region), 305 - 2 => Object::BigCircle(start), 306 - 3 => Object::SmallCircle(start), 307 - 4 => Object::Dot(start), 308 - 5 => Object::CurveInward( 309 - start, 310 - self.random_end_anchor(start, region), 311 - self.object_sizes.default_line_width, 312 - ), 313 - 6 => Object::CurveOutward( 314 - start, 315 - self.random_end_anchor(start, region), 316 - self.object_sizes.default_line_width, 317 - ), 318 - 7 => Object::Line( 319 - self.random_point(region), 320 - self.random_point(region), 321 - self.object_sizes.default_line_width, 322 - ), 323 - _ => unreachable!(), 324 - } 325 - } 326 - 327 - pub fn random_linelike_within(&self, region: &Region) -> Object { 328 - let start = self.random_point(region); 329 - match rand::thread_rng().gen_range(1..=3) { 330 - 1 => Object::CurveInward( 331 - start, 332 - self.random_end_anchor(start, region), 333 - self.object_sizes.default_line_width, 334 - ), 335 - 2 => Object::CurveOutward( 336 - start, 337 - self.random_end_anchor(start, region), 338 - self.object_sizes.default_line_width, 339 - ), 340 - 3 => Object::Line( 341 - self.random_point(region), 342 - self.random_point(region), 343 - self.object_sizes.default_line_width, 344 - ), 345 - _ => unreachable!(), 346 - } 347 - } 348 - 349 - pub fn random_end_anchor(&self, start: Point, region: &Region) -> Point { 350 - // End anchors are always a square diagonal from the start anchor (for now) 351 - // that means taking steps of the form n * (one of (1, 1), (1, -1), (-1, 1), (-1, -1)) 352 - // Except that the end anchor needs to stay in the bounds of the shape. 353 - 354 - // Determine all possible end anchors that are in a square diagonal from the start anchor 355 - let mut possible_end_anchors = vec![]; 356 - 357 - // shapes can end on the next cell, since that's where they end 358 - let actual_region = region.enlarged(1, 1); 359 - 360 - for x in actual_region.mirrored_width_range() { 361 - for y in actual_region.mirrored_height_range() { 362 - let end_anchor = start.translated(x, y); 363 - 364 - if end_anchor == start { 365 - continue; 366 - } 367 - 368 - // Check that the end anchor is in a square diagonal from the start anchor and that the end anchor is in bounds 369 - if x.abs() == y.abs() && actual_region.contains(&end_anchor) { 370 - possible_end_anchors.push(end_anchor); 371 - } 372 - } 373 - } 374 - 375 - // Pick a random end anchor from the possible end anchors 376 - possible_end_anchors[rand::thread_rng().gen_range(0..possible_end_anchors.len())] 377 - } 378 - 379 - pub fn random_polygon(&self, region: &Region) -> Object { 380 - let number_of_anchors = rand::thread_rng().gen_range(self.polygon_vertices_range.clone()); 381 - let start = self.random_point(region); 382 - let mut lines: Vec<LineSegment> = vec![]; 383 - for _ in 0..number_of_anchors { 384 - let next_anchor = self.random_point(region); 385 - lines.push(self.random_line(next_anchor)); 386 - } 387 - Object::Polygon(start, lines) 388 - } 389 - 390 - pub fn random_line(&self, end: Point) -> LineSegment { 391 - match rand::thread_rng().gen_range(1..=3) { 392 - 1 => LineSegment::Straight(end), 393 - 2 => LineSegment::InwardCurve(end), 394 - 3 => LineSegment::OutwardCurve(end), 395 - _ => unreachable!(), 396 - } 397 - } 398 - 399 229 pub fn region_is_whole_grid(&self, region: &Region) -> bool { 400 230 region.start == (0, 0) && region.end == self.grid_size 401 231 } 402 - 403 - pub fn random_region(&self) -> Region { 404 - let start = self.random_point(&self.world_region); 405 - let end = self.random_end_anchor(start, &self.world_region); 406 - Region::from(if start.0 > end.0 { 407 - (end, start) 408 - } else { 409 - (start, end) 410 - }) 411 - } 412 - 413 - pub fn random_point(&self, region: &Region) -> Point { 414 - region.ensure_nonempty().unwrap(); 415 - Point( 416 - rand::thread_rng().gen_range(region.x_range()), 417 - rand::thread_rng().gen_range(region.y_range()), 418 - ) 419 - } 420 - 421 232 pub fn clear(&mut self) { 422 233 self.layers.clear(); 423 234 self.remove_background()
+1
src/lib.rs
··· 9 9 pub mod rendering; 10 10 pub mod synchronization; 11 11 pub mod video; 12 + pub mod wasm; 12 13 13 14 pub use geometry::{Angle, Containable, Point, Region}; 14 15 pub use graphics::{
+102
src/random/canvas.rs
··· 1 + use crate::{Canvas, ColoredObject, Containable, Fill, Layer, LineSegment, Object, Point, Region}; 2 + use rand::{distributions::uniform::SampleRange, Rng}; 3 + use std::collections::HashMap; 4 + 5 + impl Canvas { 6 + pub fn random_layer(&self, name: &str) -> Layer { 7 + self.random_layer_within(name, &self.world_region) 8 + } 9 + 10 + pub fn random_object(&self) -> Object { 11 + Object::random( 12 + &self.world_region, 13 + self.object_sizes.default_line_width, 14 + self.polygon_vertices_range.clone(), 15 + ) 16 + } 17 + 18 + pub fn n_random_linelikes_within( 19 + &self, 20 + layer_name: &str, 21 + region: &Region, 22 + count: usize, 23 + ) -> Layer { 24 + let mut objects: HashMap<String, ColoredObject> = HashMap::new(); 25 + for i in 0..count { 26 + let object = 27 + Object::random_linelike_within(region, self.object_sizes.default_line_width); 28 + objects.insert( 29 + format!("{}#{}", layer_name, i), 30 + ColoredObject::from(( 31 + object, 32 + if rand::thread_rng().gen_bool(0.5) { 33 + Some(Fill::random_solid(self.background)) 34 + } else { 35 + None 36 + }, 37 + )), 38 + ); 39 + } 40 + Layer { 41 + object_sizes: self.object_sizes.clone(), 42 + name: layer_name.to_owned(), 43 + objects, 44 + _render_cache: None, 45 + hidden: false, 46 + } 47 + } 48 + 49 + pub fn random_linelikes_within( 50 + &self, 51 + layer_name: &str, 52 + region: &Region, 53 + object_counts: impl SampleRange<usize>, 54 + ) -> Layer { 55 + let number_of_objects = rand::thread_rng().gen_range(object_counts); 56 + self.n_random_linelikes_within(layer_name, region, number_of_objects) 57 + } 58 + 59 + pub fn random_layer_within(&self, name: &str, region: &Region) -> Layer { 60 + let mut objects: HashMap<String, ColoredObject> = HashMap::new(); 61 + let number_of_objects = rand::thread_rng().gen_range(self.objects_count_range.clone()); 62 + for i in 0..number_of_objects { 63 + let object = Object::random( 64 + region, 65 + self.object_sizes.default_line_width, 66 + self.polygon_vertices_range.clone(), 67 + ); 68 + let hatchable = object.hatchable(); 69 + objects.insert( 70 + format!("{}#{}", name, i), 71 + object.color(if hatchable { 72 + Fill::random_hatches(self.background) 73 + } else { 74 + Fill::random_solid(self.background) 75 + }), 76 + ); 77 + } 78 + Layer { 79 + object_sizes: self.object_sizes, 80 + name: name.to_string(), 81 + objects, 82 + _render_cache: None, 83 + hidden: false, 84 + } 85 + } 86 + 87 + pub fn random_linelikes(&self, layer_name: &str) -> Layer { 88 + self.random_linelikes_within( 89 + layer_name, 90 + &self.world_region, 91 + self.objects_count_range.clone(), 92 + ) 93 + } 94 + 95 + pub fn random_region(&self) -> Region { 96 + Region::random(&self.world_region) 97 + } 98 + 99 + pub(crate) fn random_point(&self, region: &Region) -> Point { 100 + Point::random(region) 101 + } 102 + }
+2
src/random/mod.rs
··· 4 4 pub mod layer; 5 5 pub mod objects; 6 6 pub mod region; 7 + pub mod point; 7 8 8 9 pub use canvas::*; 9 10 pub use color::*; ··· 11 12 pub use layer::*; 12 13 pub use objects::*; 13 14 pub use region::*; 15 + pub use point::*;
+65
src/random/objects.rs
··· 1 + use std::collections::HashMap; 2 + 3 + use rand::{distributions::uniform::SampleRange, Rng}; 4 + 5 + use crate::{ColoredObject, Layer, LineSegment, Object, ObjectSizes, Point, Region}; 6 + 7 + impl Object { 8 + pub fn random_starting_at( 9 + start: Point, 10 + region: &Region, 11 + line_width: f32, 12 + polygon_vertices_range: impl SampleRange<usize>, 13 + ) -> Self { 14 + match rand::thread_rng().gen_range(1..=7) { 15 + 1 => Self::random_polygon(region, polygon_vertices_range), 16 + 2 => Self::BigCircle(start), 17 + 3 => Self::SmallCircle(start), 18 + 4 => Self::Dot(start), 19 + 5 => Self::CurveInward(start, region.random_end(start), line_width), 20 + 6 => Self::CurveOutward(start, region.random_end(start), line_width), 21 + 7 => Self::Line(Point::random(region), Point::random(region), line_width), 22 + _ => unreachable!(), 23 + } 24 + } 25 + 26 + pub fn random_polygon(region: &Region, vertices_range: impl SampleRange<usize>) -> Object { 27 + let number_of_anchors = rand::thread_rng().gen_range(vertices_range); 28 + let start = Point::random(region); 29 + let mut lines: Vec<LineSegment> = vec![]; 30 + for _ in 0..number_of_anchors { 31 + let next_anchor = Point::random(region); 32 + lines.push(Self::random_line(next_anchor)); 33 + } 34 + Object::Polygon(start, lines) 35 + } 36 + 37 + pub fn random_line(end: Point) -> LineSegment { 38 + match rand::thread_rng().gen_range(1..=3) { 39 + 1 => LineSegment::Straight(end), 40 + 2 => LineSegment::InwardCurve(end), 41 + 3 => LineSegment::OutwardCurve(end), 42 + _ => unreachable!(), 43 + } 44 + } 45 + 46 + 47 + pub fn random( 48 + region: &Region, 49 + line_width: f32, 50 + polygon_vertices_range: impl SampleRange<usize>, 51 + ) -> Object { 52 + let start = Point::random(region); 53 + Object::random_starting_at(start, region, line_width, polygon_vertices_range) 54 + } 55 + 56 + pub fn random_linelike_within(region: &Region, line_width: f32) -> Object { 57 + let start = region.random_point(); 58 + match rand::thread_rng().gen_range(1..=3) { 59 + 1 => Object::CurveInward(start, region.random_end(start), line_width), 60 + 2 => Object::CurveOutward(start, region.random_end(start), line_width), 61 + 3 => Object::Line(Point::random(region), Point::random(region), line_width), 62 + _ => unreachable!(), 63 + } 64 + } 65 + }
+13
src/random/point.rs
··· 1 + use rand::Rng; 2 + 3 + use crate::{Point, Region}; 4 + 5 + impl Point { 6 + pub fn random(within: &Region) -> Self { 7 + within.ensure_nonempty().unwrap(); 8 + Self( 9 + rand::thread_rng().gen_range(within.x_range()), 10 + rand::thread_rng().gen_range(within.y_range()), 11 + ) 12 + } 13 + }
+58
src/random/region.rs
··· 1 + use crate::{Containable, Point, Region}; 2 + use rand::Rng; 3 + 4 + impl Region { 5 + pub fn random_end(&self, start: Point) -> Point { 6 + // End anchors are always a square diagonal from the start anchor (for now) 7 + // that means taking steps of the form n * (one of (1, 1), (1, -1), (-1, 1), (-1, -1)) 8 + // Except that the end anchor needs to stay in the bounds of the shape. 9 + 10 + // Determine all possible end anchors that are in a square diagonal from the start anchor 11 + let mut possible_end_anchors = vec![]; 12 + 13 + // shapes can end on the next cell, since that's where they end 14 + let actual_region = self.enlarged(1, 1); 15 + 16 + for x in actual_region.mirrored_width_range() { 17 + for y in actual_region.mirrored_height_range() { 18 + let end_anchor = start.translated(x, y); 19 + 20 + if end_anchor == start { 21 + continue; 22 + } 23 + 24 + // Check that the end anchor is in a square diagonal from the start anchor and that the end anchor is in bounds 25 + if x.abs() == y.abs() && actual_region.contains(&end_anchor) { 26 + possible_end_anchors.push(end_anchor); 27 + } 28 + } 29 + } 30 + 31 + // Pick a random end anchor from the possible end anchors 32 + possible_end_anchors[rand::thread_rng().gen_range(0..possible_end_anchors.len())] 33 + } 34 + 35 + pub fn random(within: &Region) -> Self { 36 + let start = Point::random(within); 37 + let end = within.random_end(start); 38 + Region::from(if start.0 > end.0 { 39 + (end, start) 40 + } else { 41 + (start, end) 42 + }) 43 + } 44 + 45 + pub fn random_point(&self) -> Point { 46 + Point::random(self) 47 + } 48 + 49 + pub fn random_point_except(&self, except: &Region) -> Point { 50 + // XXX this is probably not a good idea lmao 51 + loop { 52 + let point = self.random_point(); 53 + if !except.contains(&point) { 54 + return point; 55 + } 56 + } 57 + } 58 + }
+115
src/wasm/layer.rs
··· 1 + use super::canvas; 2 + use crate::{ 3 + wasm::{append_new_div_inside, render_canvas, replace_content_with}, 4 + Color, Fill, Filter, Layer, Object, Point, 5 + }; 6 + use wasm_bindgen::prelude::wasm_bindgen; 7 + 8 + #[wasm_bindgen(getter_with_clone)] 9 + pub struct LayerWeb { 10 + pub name: String, 11 + } 12 + 13 + #[wasm_bindgen] 14 + pub fn new_layer(name: &str) -> LayerWeb { 15 + canvas().add_or_replace_layer(Layer::new(name)); 16 + LayerWeb { 17 + name: name.to_string(), 18 + } 19 + } 20 + 21 + // #[wasm_bindgen()] 22 + 23 + #[wasm_bindgen] 24 + impl LayerWeb { 25 + pub fn render(&self) -> String { 26 + render_canvas() 27 + } 28 + 29 + pub fn render_into(&self, selector: String) { 30 + append_new_div_inside(self.render(), selector) 31 + } 32 + 33 + pub fn render_at(self, selector: String) { 34 + replace_content_with(self.render(), selector) 35 + } 36 + 37 + pub fn paint_all(&self, color: Color, opacity: Option<f32>, filter: Filter) { 38 + canvas() 39 + .layer(&self.name) 40 + .paint_all_objects(Fill::Translucent(color, opacity.unwrap_or(1.0))); 41 + canvas().layer(&self.name).filter_all_objects(filter); 42 + } 43 + 44 + pub fn random(name: &str) -> Self { 45 + let layer = canvas().random_layer(name); 46 + canvas().add_or_replace_layer(layer); 47 + LayerWeb { 48 + name: name.to_string(), 49 + } 50 + } 51 + 52 + pub fn new_line(&self, name: &str, start: Point, end: Point, thickness: f32, color: Color) { 53 + canvas().layer(name).add_object( 54 + name, 55 + ( 56 + Object::Line(start, end, thickness), 57 + Some(Fill::Solid(color)), 58 + ) 59 + .into(), 60 + ) 61 + } 62 + pub fn new_curve_outward( 63 + &self, 64 + name: &str, 65 + start: Point, 66 + end: Point, 67 + thickness: f32, 68 + color: Color, 69 + ) { 70 + canvas().layer(name).add_object( 71 + name, 72 + Object::CurveOutward(start, end, thickness).color(Fill::Solid(color)), 73 + ) 74 + } 75 + pub fn new_curve_inward( 76 + &self, 77 + name: &str, 78 + start: Point, 79 + end: Point, 80 + thickness: f32, 81 + color: Color, 82 + ) { 83 + canvas().layer(name).add_object( 84 + name, 85 + Object::CurveInward(start, end, thickness).color(Fill::Solid(color)), 86 + ) 87 + } 88 + pub fn new_small_circle(&self, name: &str, center: Point, color: Color) { 89 + canvas() 90 + .layer(name) 91 + .add_object(name, Object::SmallCircle(center).color(Fill::Solid(color))) 92 + } 93 + pub fn new_dot(&self, name: &str, center: Point, color: Color) { 94 + canvas() 95 + .layer(name) 96 + .add_object(name, Object::Dot(center).color(Fill::Solid(color))) 97 + } 98 + pub fn new_big_circle(&self, name: &str, center: Point, color: Color) { 99 + canvas() 100 + .layer(name) 101 + .add_object(name, Object::BigCircle(center).color(Fill::Solid(color))) 102 + } 103 + pub fn new_text(&self, name: &str, anchor: Point, text: String, font_size: f32, color: Color) { 104 + canvas().layer(name).add_object( 105 + name, 106 + Object::Text(anchor, text, font_size).color(Fill::Solid(color)), 107 + ) 108 + } 109 + pub fn new_rectangle(&self, name: &str, topleft: Point, bottomright: Point, color: Color) { 110 + canvas().layer(name).add_object( 111 + name, 112 + Object::Rectangle(topleft, bottomright).color(Fill::Solid(color)), 113 + ) 114 + } 115 + }
+7
src/wasm/mod.rs
··· 1 + pub mod layer; 2 + pub mod transform; 3 + pub mod web; 4 + 5 + pub use layer::*; 6 + pub use transform::*; 7 + pub use web::*;
+1
src/wasm/transform.rs
··· 1 + use crate::{graphics::TransformationType, Transformation}; 1 2 use wasm_bindgen::prelude::*; 2 3 3 4 #[wasm_bindgen(getter_with_clone)]
+20 -119
src/wasm/web.rs
··· 6 6 use wasm_bindgen::prelude::wasm_bindgen; 7 7 use wasm_bindgen::{JsValue, UnwrapThrowExt}; 8 8 9 - use crate::{examples, Canvas, Color, ColorMapping, Fill, Filter, Layer, Object, Point}; 9 + use crate::{ 10 + examples, Canvas, Color, ColorMapping, Fill, Filter, Layer, Object, Point, SVGRenderable, 11 + }; 12 + 13 + use super::LayerWeb; 10 14 11 15 static WEB_CANVAS: Lazy<Mutex<Canvas>> = Lazy::new(|| Mutex::new(Canvas::default_settings())); 12 16 13 - fn canvas() -> std::sync::MutexGuard<'static, Canvas> { 17 + pub(super) fn canvas() -> std::sync::MutexGuard<'static, Canvas> { 14 18 WEB_CANVAS.lock().unwrap() 15 19 } 16 20 ··· 59 63 60 64 #[wasm_bindgen] 61 65 pub fn render_canvas_into(selector: String) { 62 - let svgstring = canvas().render_to_svg().unwrap_throw(); 63 - append_new_div_inside(svgstring, selector) 66 + append_new_div_inside(render_canvas(), selector) 64 67 } 65 68 66 69 #[wasm_bindgen] 67 70 pub fn render_canvas_at(selector: String) { 68 - let svgstring = canvas().render_to_svg().unwrap_throw(); 69 - replace_content_with(svgstring, selector) 71 + replace_content_with(render_canvas(), selector); 70 72 } 71 73 72 74 #[wasm_bindgen] ··· 129 131 } 130 132 131 133 #[wasm_bindgen] 132 - pub fn render_canvas() { 133 - canvas().render_to_svg().unwrap_throw(); 134 + pub fn render_canvas() -> String { 135 + let can = canvas(); 136 + can.render_to_svg( 137 + can.colormap.clone(), 138 + can.cell_size, 139 + can.object_sizes, 140 + "web_root_canvas", 141 + ) 142 + .unwrap_throw() 143 + .to_string() 134 144 } 135 145 136 146 #[wasm_bindgen] 137 147 pub fn set_palette(palette: ColorMapping) { 138 148 canvas().colormap = palette; 139 - } 140 - 141 - #[wasm_bindgen] 142 - pub fn new_layer(name: &str) -> LayerWeb { 143 - canvas().add_or_replace_layer(Layer::new(name)); 144 - LayerWeb { 145 - name: name.to_string(), 146 - } 147 149 } 148 150 149 151 #[wasm_bindgen] ··· 179 181 .expect_throw("could not get the element, but is was found (shouldn't happen)") 180 182 } 181 183 182 - fn append_new_div_inside(content: String, selector: String) { 184 + pub(super) fn append_new_div_inside(content: String, selector: String) { 183 185 let output = document().create_element("div").unwrap(); 184 186 output.set_class_name("frame"); 185 187 output.set_inner_html(&content); 186 188 query_selector(selector).append_child(&output).unwrap(); 187 189 } 188 190 189 - fn replace_content_with(content: String, selector: String) { 191 + pub(super) fn replace_content_with(content: String, selector: String) { 190 192 query_selector(selector).set_inner_html(&content); 191 193 } 192 - 193 - #[wasm_bindgen(getter_with_clone)] 194 - pub struct LayerWeb { 195 - pub name: String, 196 - } 197 - 198 - // #[wasm_bindgen()] 199 - 200 - #[wasm_bindgen] 201 - impl LayerWeb { 202 - pub fn render(&self) -> String { 203 - canvas().render_to_svg().unwrap_throw() 204 - } 205 - 206 - pub fn render_into(&self, selector: String) { 207 - append_new_div_inside(self.render(), selector) 208 - } 209 - 210 - pub fn render_at(self, selector: String) { 211 - replace_content_with(self.render(), selector) 212 - } 213 - 214 - pub fn paint_all(&self, color: Color, opacity: Option<f32>, filter: Filter) { 215 - canvas() 216 - .layer(&self.name) 217 - .paint_all_objects(Fill::Translucent(color, opacity.unwrap_or(1.0))); 218 - canvas().layer(&self.name).filter_all_objects(filter); 219 - } 220 - 221 - pub fn random(name: &str) -> Self { 222 - let layer = canvas().random_layer(name); 223 - canvas().add_or_replace_layer(layer); 224 - LayerWeb { 225 - name: name.to_string(), 226 - } 227 - } 228 - 229 - pub fn new_line(&self, name: &str, start: Point, end: Point, thickness: f32, color: Color) { 230 - canvas().layer(name).add_object( 231 - name, 232 - ( 233 - Object::Line(start, end, thickness), 234 - Some(Fill::Solid(color)), 235 - ) 236 - .into(), 237 - ) 238 - } 239 - pub fn new_curve_outward( 240 - &self, 241 - name: &str, 242 - start: Point, 243 - end: Point, 244 - thickness: f32, 245 - color: Color, 246 - ) { 247 - canvas().layer(name).add_object( 248 - name, 249 - Object::CurveOutward(start, end, thickness).color(Fill::Solid(color)), 250 - ) 251 - } 252 - pub fn new_curve_inward( 253 - &self, 254 - name: &str, 255 - start: Point, 256 - end: Point, 257 - thickness: f32, 258 - color: Color, 259 - ) { 260 - canvas().layer(name).add_object( 261 - name, 262 - Object::CurveInward(start, end, thickness).color(Fill::Solid(color)), 263 - ) 264 - } 265 - pub fn new_small_circle(&self, name: &str, center: Point, color: Color) { 266 - canvas() 267 - .layer(name) 268 - .add_object(name, Object::SmallCircle(center).color(Fill::Solid(color))) 269 - } 270 - pub fn new_dot(&self, name: &str, center: Point, color: Color) { 271 - canvas() 272 - .layer(name) 273 - .add_object(name, Object::Dot(center).color(Fill::Solid(color))) 274 - } 275 - pub fn new_big_circle(&self, name: &str, center: Point, color: Color) { 276 - canvas() 277 - .layer(name) 278 - .add_object(name, Object::BigCircle(center).color(Fill::Solid(color))) 279 - } 280 - pub fn new_text(&self, name: &str, anchor: Point, text: String, font_size: f32, color: Color) { 281 - canvas().layer(name).add_object( 282 - name, 283 - Object::Text(anchor, text, font_size).color(Fill::Solid(color)), 284 - ) 285 - } 286 - pub fn new_rectangle(&self, name: &str, topleft: Point, bottomright: Point, color: Color) { 287 - canvas().layer(name).add_object( 288 - name, 289 - Object::Rectangle(topleft, bottomright).color(Fill::Solid(color)), 290 - ) 291 - } 292 - }