lib.rs
58.5 kB · rust · 1660 lines
1#![allow(non_camel_case_types, non_snake_case, clippy::too_many_arguments)]23mod hand;45use wasm_bindgen::prelude::*;67/// Flips every type to one minus itself, same as invert.8#[wasm_bindgen]9pub fn cell_anti(cell: JsValue) -> Result<JsValue, JsValue> {10 let cell = hand::cell_from_js(&cell)?;11 let value = cell.anti();12 hand::cell_to_js(&value)13}1415/// Maps every type to one at or above the threshold and zero below, dropping colors.16#[wasm_bindgen]17pub fn cell_binarize(cell: JsValue, threshold: u8) -> Result<JsValue, JsValue> {18 let cell = hand::cell_from_js(&cell)?;19 let value = cell.binarize(threshold);20 hand::cell_to_js(&value)21}2223/// Binarizes the types at Otsu's threshold, dropping colors.24#[wasm_bindgen]25pub fn cell_binarize_otsu(cell: JsValue) -> Result<JsValue, JsValue> {26 let cell = hand::cell_from_js(&cell)?;27 let value = cell.binarize_otsu();28 hand::cell_to_js(&value)29}3031/// Replaces every type with the rounded mean of its masked neighborhood, dropping colors.32#[wasm_bindgen]33pub fn cell_blur(cell: JsValue, mask: JsValue, wrap: bool) -> Result<JsValue, JsValue> {34 let cell = hand::cell_from_js(&cell)?;35 let mask = hand::tensor_from_js(&mask)?;36 let value = cell.blur(&mask, wrap).map_err(hand::throw)?;37 hand::cell_to_js(&value)38}3940/// Returns the painted color at a flat index, or transparent while unpainted or past the end.41#[wasm_bindgen]42pub fn cell_color_at(cell: JsValue, flat: usize) -> Result<Vec<u8>, JsValue> {43 let cell = hand::cell_from_js(&cell)?;44 let value = cell.color_at(flat);45 Ok(value.to_vec())46}4748/// Builds the Kronecker product of the two cells' types.49#[wasm_bindgen]50pub fn cell_combine(cell: JsValue, other: JsValue) -> Result<JsValue, JsValue> {51 let cell = hand::cell_from_js(&cell)?;52 let other = hand::cell_from_js(&other)?;53 let value = cell.combine(&other);54 hand::cell_to_js(&value)55}5657/// Grows the types to the level-fold Kronecker power of themselves, dropping colors and tags.58#[wasm_bindgen]59pub fn cell_fractal(cell: JsValue, level: usize) -> Result<JsValue, JsValue> {60 let cell = hand::cell_from_js(&cell)?;61 let value = cell.fractal(level).map_err(hand::throw)?;62 hand::cell_to_js(&value)63}6465/// Flips every type to one minus itself.66#[wasm_bindgen]67pub fn cell_invert(cell: JsValue) -> Result<JsValue, JsValue> {68 let cell = hand::cell_from_js(&cell)?;69 let value = cell.invert();70 hand::cell_to_js(&value)71}7273/// Tags every cell with its concentric shell distance from the center.74#[wasm_bindgen]75pub fn cell_layers(cell: JsValue, dtype: JsValue) -> Result<JsValue, JsValue> {76 let cell = hand::cell_from_js(&cell)?;77 let dtype = hand::from_js::<mrlyrs::core::Dtype>(&dtype)?;78 let value = cell.layers(dtype);79 hand::cell_to_js(&value)80}8182/// Folds at least two cells into one by chained Kronecker products.83#[wasm_bindgen]84pub fn cell_magic(cells: JsValue) -> Result<JsValue, JsValue> {85 let cells = hand::list_from_js(&cells, hand::cell_from_js)?;86 let value = mrlyrs::core::cell::magic(&cells).map_err(hand::throw)?;87 hand::cell_to_js(&value)88}8990/// Returns the default mapping of the first six types to white, black, alpha, red, green, and blue.91#[wasm_bindgen]92pub fn cell_mapping() -> Result<JsValue, JsValue> {93 let value = mrlyrs::core::cell::mapping();94 hand::map_to_js(&value, |x1| hand::list_to_js(x1, |x2| Ok(hand::color_to_js(*x2))))95}9697/// Stitches same-shaped cells into one grid of reps blocks per axis.98#[wasm_bindgen]99pub fn cell_merge(cells: JsValue, reps: &[usize]) -> Result<JsValue, JsValue> {100 let cells = hand::list_from_js(&cells, hand::cell_from_js)?;101 let value = mrlyrs::core::cell::merge(&cells, reps).map_err(hand::throw)?;102 hand::cell_to_js(&value)103}104105/// Builds the 3-wide Moore mask of the dimension, every site on but the center.106#[wasm_bindgen]107pub fn cell_moore(dimension: usize) -> Result<JsValue, JsValue> {108 let value = mrlyrs::core::cell::moore(dimension);109 hand::tensor_to_js(&value)110}111112/// Lays the cell each mask entry indexes into that entry's place and merges the lot.113#[wasm_bindgen]114pub fn cell_mosaic(mask: JsValue, cells: JsValue) -> Result<JsValue, JsValue> {115 let mask = hand::tensor_from_js(&mask)?;116 let cells = hand::list_from_js(&cells, hand::cell_from_js)?;117 let value = mrlyrs::core::cell::mosaic(&mask, &cells).map_err(hand::throw)?;118 hand::cell_to_js(&value)119}120121/// Tags every cell with its count of target-valued neighbors under the mask.122#[wasm_bindgen]123pub fn cell_neighbors(cell: JsValue, mask: JsValue, target: u8, wrap: bool, dtype: JsValue) -> Result<JsValue, JsValue> {124 let cell = hand::cell_from_js(&cell)?;125 let mask = hand::tensor_from_js(&mask)?;126 let dtype = hand::from_js::<mrlyrs::core::Dtype>(&dtype)?;127 let value = cell.neighbors(&mask, target, wrap, dtype).map_err(hand::throw)?;128 hand::cell_to_js(&value)129}130131/// Wraps a tensor of types in a bare cell, colorless and tagless.132#[wasm_bindgen]133pub fn cell_new(types: JsValue) -> Result<JsValue, JsValue> {134 let types = hand::tensor_from_js(&types)?;135 let value = mrlyrs::core::Cell::new(types);136 hand::cell_to_js(&value)137}138139/// Wraps the cell in count layers of value on every side, dropping colors.140#[wasm_bindgen]141pub fn cell_pad(cell: JsValue, count: usize, value: u8) -> Result<JsValue, JsValue> {142 let cell = hand::cell_from_js(&cell)?;143 let value = cell.pad(count, value);144 hand::cell_to_js(&value)145}146147/// Colors every mapped cell, picking within each type's palette by the mode.148#[wasm_bindgen]149pub fn cell_paint(cell: JsValue, mapping: JsValue, mode: JsValue, rng: JsValue) -> Result<JsValue, JsValue> {150 let cell = hand::cell_from_js(&cell)?;151 let mapping = hand::map_from_js::<u8, _>(&mapping, |x1| hand::list_from_js(x1, hand::color_from_js))?;152 let mode = hand::from_js::<mrlyrs::core::Mode>(&mode)?;153 let mut rng_stream = hand::stream_from_js(&rng)?;154 let value = cell.paint(&mapping, mode, rng_stream.as_mut()).map_err(hand::throw)?;155 if let Some(stream) = &rng_stream { hand::stream_to_js(&rng, stream)?; }156 hand::cell_to_js(&value)157}158159/// Stamps value wherever the tiled mask is on, dropping colors.160#[wasm_bindgen]161pub fn cell_perforate(cell: JsValue, mask: JsValue, value: u8) -> Result<JsValue, JsValue> {162 let cell = hand::cell_from_js(&cell)?;163 let mask = hand::tensor_from_js(&mask)?;164 let value = cell.perforate(&mask, value).map_err(hand::throw)?;165 hand::cell_to_js(&value)166}167168/// Rebuilds a cell's types, colors and tags at the new shape from one destination-to-source index map.169#[wasm_bindgen]170pub fn cell_remap(cell: JsValue, map: &[usize], shape: &[usize]) -> Result<JsValue, JsValue> {171 let cell = hand::cell_from_js(&cell)?;172 let value = mrlyrs::core::cell::remap(&cell, map, shape).map_err(hand::throw)?;173 hand::cell_to_js(&value)174}175176/// Returns the flat rgba bytes of the cells, four to a cell, the stored color where there is one and opaque black everywhere else.177#[wasm_bindgen]178pub fn cell_rgba(cell: JsValue) -> Result<Vec<u8>, JsValue> {179 let cell = hand::cell_from_js(&cell)?;180 let value = cell.rgba();181 Ok(value)182}183184/// Builds the flat source index of every destination cell after k quarter turns in the plane of the axes.185#[wasm_bindgen]186pub fn cell_rot90_map(shape: &[usize], k: usize, axes: JsValue) -> Result<Vec<usize>, JsValue> {187 let axes = hand::from_js::<(usize, usize)>(&axes)?;188 let value = mrlyrs::core::cell::rot90_map(shape, k, axes).map_err(hand::throw)?;189 Ok(value)190}191192/// Rotates the cell k quarter turns in the plane of the given axes, carrying colors and tags along.193#[wasm_bindgen]194pub fn cell_rotate(cell: JsValue, k: usize, axes: JsValue) -> Result<JsValue, JsValue> {195 let cell = hand::cell_from_js(&cell)?;196 let axes = hand::from_js::<(usize, usize)>(&axes)?;197 let value = cell.rotate(k, axes).map_err(hand::throw)?;198 hand::cell_to_js(&value)199}200201/// Returns the shape of the type tensor.202#[wasm_bindgen]203pub fn cell_shape(cell: JsValue) -> Result<Vec<usize>, JsValue> {204 let cell = hand::cell_from_js(&cell)?;205 let value = cell.shape();206 Ok(value.to_vec())207}208209/// Returns the number of cells.210#[wasm_bindgen]211pub fn cell_size(cell: JsValue) -> Result<usize, JsValue> {212 let cell = hand::cell_from_js(&cell)?;213 let value = cell.size();214 Ok(value)215}216217/// Repeats the cell reps times along each axis, carrying colors and tags along.218#[wasm_bindgen]219pub fn cell_tile(cell: JsValue, reps: &[usize]) -> Result<JsValue, JsValue> {220 let cell = hand::cell_from_js(&cell)?;221 let value = cell.tile(reps).map_err(hand::throw)?;222 hand::cell_to_js(&value)223}224225/// Builds the flat source index of every destination cell after tiling reps copies per axis.226#[wasm_bindgen]227pub fn cell_tile_map(shape: &[usize], reps: &[usize]) -> Result<Vec<usize>, JsValue> {228 let value = mrlyrs::core::cell::tile_map(shape, reps).map_err(hand::throw)?;229 Ok(value)230}231232/// Encodes indexed frames as an animated gif89a, each source pixel a scale by scale block.233#[wasm_bindgen]234pub fn codec_gif(frames: JsValue, palette: JsValue, width: usize, height: usize, scale: usize, delay: usize) -> Result<Vec<u8>, JsValue> {235 let frames = hand::from_js::<Vec<Vec<u8>>>(&frames)?;236 let frames_view: Vec<&[u8]> = frames.iter().map(Vec::as_slice).collect();237 let palette = hand::from_js::<Vec<[u8; 4]>>(&palette)?;238 let value = mrlyrs::core::codec::gif(&frames_view, &palette, width, height, scale, delay).map_err(hand::throw)?;239 Ok(value)240}241242/// Encodes rgba colors as a png, drawing each source pixel as a scale by scale block.243#[wasm_bindgen]244pub fn codec_png(colors: JsValue, width: usize, height: usize, scale: usize) -> Result<Vec<u8>, JsValue> {245 let colors = hand::from_js::<Vec<[u8; 4]>>(&colors)?;246 let value = mrlyrs::core::codec::png(&colors, width, height, scale).map_err(hand::throw)?;247 Ok(value)248}249250/// Returns the color with its alpha set to level.251#[wasm_bindgen]252pub fn colors_alpha(color: JsValue, level: u8) -> Result<JsValue, JsValue> {253 let color = hand::color_from_js(&color)?;254 let value = color.alpha(level);255 Ok(hand::color_to_js(value))256}257258/// Returns the ground rgba of the dark or the light theme.259#[wasm_bindgen]260pub fn colors_board(dark: bool) -> Result<Vec<u8>, JsValue> {261 let value = mrlyrs::core::colors::board(dark);262 Ok(value.to_vec())263}264265/// Formats the color as a css rgb or rgba call.266#[wasm_bindgen]267pub fn colors_css(color: JsValue) -> Result<String, JsValue> {268 let color = hand::color_from_js(&color)?;269 let value = color.css();270 Ok(value)271}272273/// Parses a #RRGGBB or #RRGGBBAA code, hash optional.274#[wasm_bindgen]275pub fn colors_from_hex(hex: &str) -> Result<JsValue, JsValue> {276 let value = mrlyrs::core::Color::from_hex(hex).map_err(hand::throw)?;277 Ok(hand::color_to_js(value))278}279280/// Builds a gradient of steps colors sweeping evenly through the given stops.281#[wasm_bindgen]282pub fn colors_gradient(colors: JsValue, steps: usize) -> Result<JsValue, JsValue> {283 let colors = hand::list_from_js(&colors, hand::color_from_js)?;284 let value = mrlyrs::core::colors::gradient(&colors, steps).map_err(hand::throw)?;285 hand::list_to_js(&value, |x1| Ok(hand::color_to_js(*x1)))286}287288/// Returns the foreground rgba of the dark or the light theme.289#[wasm_bindgen]290pub fn colors_ink(dark: bool) -> Result<Vec<u8>, JsValue> {291 let value = mrlyrs::core::colors::ink(dark);292 Ok(value.to_vec())293}294295/// Returns the color with every channel flipped and the alpha kept.296#[wasm_bindgen]297pub fn colors_invert(color: JsValue) -> Result<JsValue, JsValue> {298 let color = hand::color_from_js(&color)?;299 let value = color.invert();300 Ok(hand::color_to_js(value))301}302303/// Returns the color scaled toward black below level 50 and toward white above.304#[wasm_bindgen]305pub fn colors_lightness(color: JsValue, level: u8) -> Result<JsValue, JsValue> {306 let color = hand::color_from_js(&color)?;307 let value = color.lightness(level).map_err(hand::throw)?;308 Ok(hand::color_to_js(value))309}310311/// Reads rgba pixels as a type grid, one wherever the rgb mean falls below the level.312#[wasm_bindgen]313pub fn colors_luma_types(pixels: JsValue, width: usize, height: usize, level: u8) -> Result<JsValue, JsValue> {314 let pixels = hand::from_js::<Vec<[u8; 4]>>(&pixels)?;315 let value = mrlyrs::core::colors::luma_types(&pixels, width, height, level);316 hand::tensor_to_js(&value)317}318319/// Blends two colors linearly by ratio.320#[wasm_bindgen]321pub fn colors_mix(color_1: JsValue, color_2: JsValue, ratio: f64) -> Result<JsValue, JsValue> {322 let color_1 = hand::color_from_js(&color_1)?;323 let color_2 = hand::color_from_js(&color_2)?;324 let value = mrlyrs::core::colors::mix(color_1, color_2, ratio).map_err(hand::throw)?;325 Ok(hand::color_to_js(value))326}327328/// Returns the palette color a name spells.329#[wasm_bindgen]330pub fn colors_named(name: &str) -> Result<JsValue, JsValue> {331 let value = mrlyrs::core::colors::named(name).map_err(hand::throw)?;332 Ok(hand::color_to_js(value))333}334335/// Draws a color from the stream, opaque unless alpha is asked for.336#[wasm_bindgen]337pub fn colors_random(alpha: bool, rng: &mut hand::Rng) -> Result<JsValue, JsValue> {338 let value = mrlyrs::core::Color::random(alpha, rng.stream());339 Ok(hand::color_to_js(value))340}341342/// Builds an opaque color.343#[wasm_bindgen]344pub fn colors_rgb(r: u8, g: u8, b: u8) -> Result<JsValue, JsValue> {345 let value = mrlyrs::core::Color::rgb(r, g, b);346 Ok(hand::color_to_js(value))347}348349/// Builds a color with an explicit alpha.350#[wasm_bindgen]351pub fn colors_rgba(r: u8, g: u8, b: u8, a: u8) -> Result<JsValue, JsValue> {352 let value = mrlyrs::core::Color::rgba(r, g, b, a);353 Ok(hand::color_to_js(value))354}355356/// Returns a hue one shade lighter, itself, and one shade darker.357#[wasm_bindgen]358pub fn colors_shades(hue: JsValue) -> Result<JsValue, JsValue> {359 let hue = hand::color_from_js(&hue)?;360 let value = mrlyrs::core::colors::shades(hue);361 hand::list_to_js(&value, |x1| Ok(hand::color_to_js(*x1)))362}363364/// Snaps every pixel to the palette color nearest it in squared rgba distance, first on a tie.365#[wasm_bindgen]366pub fn colors_snap(pixels: JsValue, palette: JsValue) -> Result<JsValue, JsValue> {367 let pixels = hand::from_js::<Vec<[u8; 4]>>(&pixels)?;368 let palette = hand::list_from_js(&palette, hand::color_from_js)?;369 let value = mrlyrs::core::colors::snap(&pixels, &palette);370 hand::list_to_js(&value, |x1| Ok(hand::typed(&(*x1)[..])))371}372373/// Formats the color as lowercase hex, appending the alpha pair only when not opaque.374#[wasm_bindgen]375pub fn colors_to_hex(color: JsValue) -> Result<String, JsValue> {376 let color = hand::color_from_js(&color)?;377 let value = color.to_hex();378 Ok(value)379}380381/// Parses JSON text into a value.382#[wasm_bindgen]383pub fn error_parse(text: &str) -> Result<JsValue, JsValue> {384 let value = mrlyrs::core::error::parse(text).map_err(hand::throw)?;385 hand::to_js(&value)386}387388/// Squashes rgba pixels to the hex aspect, returning the new width, height and pixels.389#[wasm_bindgen]390pub fn hex_fit(pixels: JsValue, width: usize, height: usize, vertical: bool, filter: JsValue) -> Result<JsValue, JsValue> {391 let pixels = hand::from_js::<Vec<[u8; 4]>>(&pixels)?;392 let filter = hand::from_js::<mrlyrs::core::Filter>(&filter)?;393 let value = mrlyrs::core::hex_fit(&pixels, width, height, vertical, filter).map_err(hand::throw)?;394 Ok(hand::tuple_to_js(&[hand::to_js(&value.0)?, hand::to_js(&value.1)?, hand::list_to_js(&value.2, |x2| Ok(hand::typed(&(*x2)[..])))?]))395}396397/// Returns the size a hex rendering wears, the named axis squashed by the triangle ratio.398#[wasm_bindgen]399pub fn hex_size(width: usize, height: usize, vertical: bool) -> Result<JsValue, JsValue> {400 let value = mrlyrs::core::hex_size(width, height, vertical);401 hand::to_js(&value)402}403404/// Box-blurs rgba pixels by radius, each channel the mean of its edge-padded window.405#[wasm_bindgen]406pub fn image_blur(pixels: JsValue, width: usize, height: usize, radius: usize) -> Result<JsValue, JsValue> {407 let pixels = hand::from_js::<Vec<[u8; 4]>>(&pixels)?;408 let value = mrlyrs::core::image::blur(&pixels, width, height, radius);409 hand::list_to_js(&value, |x1| Ok(hand::typed(&(*x1)[..])))410}411412/// Colors the cell from the paint's inks under its edition mode, scattering the Random edition from the stream.413#[wasm_bindgen]414pub fn paint_apply(paint: &paint_Paint, cell: JsValue, rng: &mut hand::Rng) -> Result<(), JsValue> {415 let mut cell_value = hand::cell_from_js(&cell)?;416 mrlyrs::core::paint::apply(&paint.inner, &mut cell_value, rng.stream()).map_err(hand::throw)?;417 hand::cell_into_js(&cell, &cell_value)?;418 Ok(())419}420421/// Replays a stored paint onto a cell, tagging first and applying it from the stream.422#[wasm_bindgen]423pub fn paint_coat(cell: JsValue, paint: &paint_Paint, mask: JsValue, rng: &mut hand::Rng) -> Result<(), JsValue> {424 let mut cell_value = hand::cell_from_js(&cell)?;425 let mask = hand::option_from_js(&mask, hand::tensor_from_js)?;426 mrlyrs::core::paint::coat(&mut cell_value, &paint.inner, mask.as_ref(), rng.stream()).map_err(hand::throw)?;427 hand::cell_into_js(&cell, &cell_value)?;428 Ok(())429}430431/// Draws a random paint under the config, applies it to the cell, and returns the recipe.432#[wasm_bindgen]433pub fn paint_paint(cell: JsValue, config: JsValue, mask: JsValue, rng: &mut hand::Rng) -> Result<paint_Paint, JsValue> {434 let mut cell_value = hand::cell_from_js(&cell)?;435 let config = hand::from_js::<mrlyrs::core::paint::Config>(&config)?;436 let mask = hand::option_from_js(&mask, hand::tensor_from_js)?;437 let value = mrlyrs::core::paint::paint(&mut cell_value, &config, mask.as_ref(), rng.stream()).map_err(hand::throw)?;438 hand::cell_into_js(&cell, &cell_value)?;439 Ok(paint_Paint { inner: value })440}441442/// Tags the cell for Layers and Neighbors paints and sizes the palette to the tag count.443#[wasm_bindgen]444pub fn paint_prime(paint: &paint_Paint, cell: JsValue, mask: JsValue, rng: &mut hand::Rng) -> Result<paint_Paint, JsValue> {445 let mut cell_value = hand::cell_from_js(&cell)?;446 let mask = hand::option_from_js(&mask, hand::tensor_from_js)?;447 let value = mrlyrs::core::paint::prime(paint.inner.clone(), &mut cell_value, mask.as_ref(), rng.stream()).map_err(hand::throw)?;448 hand::cell_into_js(&cell, &cell_value)?;449 Ok(paint_Paint { inner: value })450}451452/// Draws a random edition from the allowed list, or from all seven.453#[wasm_bindgen]454pub fn paint_random_edition(editions: JsValue, rng: &mut hand::Rng) -> Result<JsValue, JsValue> {455 let editions = hand::from_js::<Option<Vec<mrlyrs::core::paint::Edition>>>(&editions)?;456 let value = mrlyrs::core::paint::random_edition(editions.as_deref(), rng.stream());457 hand::to_js(&value)458}459460/// Redraws the paint's secondary inks and shades under its scheme.461#[wasm_bindgen]462pub fn paint_reroll(paint: &paint_Paint, rng: &mut hand::Rng) -> Result<paint_Paint, JsValue> {463 let value = mrlyrs::core::paint::reroll(paint.inner.clone(), rng.stream());464 Ok(paint_Paint { inner: value })465}466467/// Draws the paint's scheme, target and primary under the config, then rerolls the rest.468#[wasm_bindgen]469pub fn paint_setup(paint: &paint_Paint, config: JsValue, rng: &mut hand::Rng) -> Result<paint_Paint, JsValue> {470 let config = hand::from_js::<mrlyrs::core::paint::Config>(&config)?;471 let value = mrlyrs::core::paint::setup(paint.inner.clone(), &config, rng.stream());472 Ok(paint_Paint { inner: value })473}474475/// Tags the cell for the Layers and Neighbors editions and returns the distinct tag count on the secondary side.476#[wasm_bindgen]477pub fn paint_tag(cell: JsValue, edition: JsValue, target: JsValue, mask: JsValue) -> Result<usize, JsValue> {478 let mut cell_value = hand::cell_from_js(&cell)?;479 let edition = hand::from_js::<mrlyrs::core::paint::Edition>(&edition)?;480 let target = hand::from_js::<mrlyrs::core::paint::Target>(&target)?;481 let mask = hand::option_from_js(&mask, hand::tensor_from_js)?;482 let value = mrlyrs::core::paint::tag(&mut cell_value, edition, target, mask.as_ref()).map_err(hand::throw)?;483 hand::cell_into_js(&cell, &cell_value)?;484 Ok(value)485}486487/// Returns the color for one value against the range maximum: the background at zero, the top of the ramp from the maximum up.488#[wasm_bindgen]489pub fn ramp_color(colorizer: JsValue, value: usize, max: usize) -> Result<JsValue, JsValue> {490 let colorizer = hand::from_js::<mrlyrs::core::Colorizer>(&colorizer)?;491 let value = mrlyrs::core::ramp::color(&colorizer, value, max);492 Ok(hand::color_to_js(value))493}494495/// Maps a slice of values to rgba pixels against the range maximum.496#[wasm_bindgen]497pub fn ramp_colors(colorizer: JsValue, values: &[usize], max: usize) -> Result<JsValue, JsValue> {498 let colorizer = hand::from_js::<mrlyrs::core::Colorizer>(&colorizer)?;499 let value = mrlyrs::core::ramp::colors(&colorizer, values, max);500 hand::list_to_js(&value, |x1| Ok(hand::typed(&(*x1)[..])))501}502503/// Resamples rgba pixels to a new size.504#[wasm_bindgen]505pub fn resample(pixels: JsValue, width: usize, height: usize, out_w: usize, out_h: usize, filter: JsValue) -> Result<JsValue, JsValue> {506 let pixels = hand::from_js::<Vec<[u8; 4]>>(&pixels)?;507 let filter = hand::from_js::<mrlyrs::core::Filter>(&filter)?;508 let value = mrlyrs::core::resample(&pixels, width, height, out_w, out_h, filter).map_err(hand::throw)?;509 hand::list_to_js(&value, |x1| Ok(hand::typed(&(*x1)[..])))510}511512/// Draws an integer below n, or zero when n is zero.513#[wasm_bindgen]514pub fn rng_below_(rng: &mut hand::Rng, n: usize) -> Result<usize, JsValue> {515 let value = rng.stream().below(n);516 Ok(value)517}518519/// Draws a fair coin flip.520#[wasm_bindgen]521pub fn rng_boolean_(rng: &mut hand::Rng) -> Result<bool, JsValue> {522 let value = rng.stream().boolean();523 Ok(value)524}525526/// Returns true with probability p.527#[wasm_bindgen]528pub fn rng_chance_(rng: &mut hand::Rng, p: f64) -> Result<bool, JsValue> {529 let value = rng.stream().chance(p);530 Ok(value)531}532533/// Builds the stream from a seed.534#[wasm_bindgen]535pub fn rng_new_(seed: JsValue) -> Result<hand::Rng, JsValue> {536 let seed = hand::u64_from_js(&seed)?;537 let value = mrlyrs::core::Rng::new(seed);538 Ok(hand::Rng::wrap(value))539}540541/// Draws an integer between lo and hi inclusive, or lo when hi is not above lo.542#[wasm_bindgen]543pub fn rng_range_(rng: &mut hand::Rng, lo: JsValue, hi: JsValue) -> Result<i64, JsValue> {544 let lo = hand::i64_from_js(&lo)?;545 let hi = hand::i64_from_js(&hi)?;546 let value = rng.stream().range(lo, hi);547 Ok(value)548}549550/// Draws amount distinct indices below length, or every index when amount is larger.551#[wasm_bindgen]552pub fn rng_sample_indices_(rng: &mut hand::Rng, length: usize, amount: usize) -> Result<Vec<usize>, JsValue> {553 let value = rng.stream().sample_indices(length, amount);554 Ok(value)555}556557/// Draws a float at or above zero and below one.558#[wasm_bindgen]559pub fn rng_unit_(rng: &mut hand::Rng) -> Result<f64, JsValue> {560 let value = rng.stream().unit();561 Ok(value)562}563564/// Returns the element at a flat index, which must be below the size like a slice index.565#[wasm_bindgen]566pub fn tensor_at(tensor: JsValue, flat: usize) -> Result<i64, JsValue> {567 let tensor = hand::tensor_from_js(&tensor)?;568 let value = tensor.at(flat);569 Ok(value)570}571572/// Maps every element to one at or above the threshold, zero below.573#[wasm_bindgen]574pub fn tensor_binarize(tensor: JsValue, threshold: u8) -> Result<JsValue, JsValue> {575 let tensor = hand::tensor_from_js(&tensor)?;576 let value = tensor.binarize(threshold);577 hand::tensor_to_js(&value)578}579580/// Binarizes at one above the Otsu threshold.581#[wasm_bindgen]582pub fn tensor_binarize_otsu(tensor: JsValue) -> Result<JsValue, JsValue> {583 let tensor = hand::tensor_from_js(&tensor)?;584 let value = tensor.binarize_otsu();585 hand::tensor_to_js(&value)586}587588/// Averages every position over its masked neighborhood, rounded.589#[wasm_bindgen]590pub fn tensor_blur(tensor: JsValue, mask: JsValue, wrap: bool) -> Result<JsValue, JsValue> {591 let tensor = hand::tensor_from_js(&tensor)?;592 let mask = hand::tensor_from_js(&mask)?;593 let value = tensor.blur(&mask, wrap).map_err(hand::throw)?;594 hand::tensor_to_js(&value)595}596597/// Returns the elements as bytes.598#[wasm_bindgen]599pub fn tensor_bytes(tensor: JsValue) -> Result<Vec<u8>, JsValue> {600 let tensor = hand::tensor_from_js(&tensor)?;601 let value = tensor.bytes().map_err(hand::throw)?;602 Ok(value.to_vec())603}604605/// Counts the cells holding one value.606#[wasm_bindgen]607pub fn tensor_count(tensor: JsValue, value: u8) -> Result<usize, JsValue> {608 let tensor = hand::tensor_from_js(&tensor)?;609 let value = tensor.count(value);610 Ok(value)611}612613/// Returns the element width.614#[wasm_bindgen]615pub fn tensor_dtype(tensor: JsValue) -> Result<JsValue, JsValue> {616 let tensor = hand::tensor_from_js(&tensor)?;617 let value = tensor.dtype();618 hand::to_js(&value)619}620621/// Counts the faces where filled cells meet empty cells or the boundary: perimeter in 2d, surface in 3d.622#[wasm_bindgen]623pub fn tensor_exposed(tensor: JsValue) -> Result<JsValue, JsValue> {624 let tensor = hand::tensor_from_js(&tensor)?;625 let value = tensor.exposed();626 Ok(JsValue::from_str(&value.to_string()))627}628629/// Builds a tensor of the shape and width filled with one value.630#[wasm_bindgen]631pub fn tensor_filled(shape: Vec<usize>, value: JsValue, dtype: JsValue) -> Result<JsValue, JsValue> {632 let value = hand::i64_from_js(&value)?;633 let dtype = hand::from_js::<mrlyrs::core::Dtype>(&dtype)?;634 let value = mrlyrs::core::Tensor::filled(shape, value, dtype);635 hand::tensor_to_js(&value)636}637638/// Reverses the tensor along one axis.639#[wasm_bindgen]640pub fn tensor_flip(tensor: JsValue, axis: usize) -> Result<JsValue, JsValue> {641 let tensor = hand::tensor_from_js(&tensor)?;642 let value = tensor.flip(axis).map_err(hand::throw)?;643 hand::tensor_to_js(&value)644}645646/// Folds the tensor into its level-fold Kronecker power.647#[wasm_bindgen]648pub fn tensor_fractal(tensor: JsValue, level: usize) -> Result<JsValue, JsValue> {649 let tensor = hand::tensor_from_js(&tensor)?;650 let value = tensor.fractal(level);651 hand::tensor_to_js(&value)652}653654/// Builds a u8 tensor filled with one value.655#[wasm_bindgen]656pub fn tensor_full(shape: Vec<usize>, value: u8) -> Result<JsValue, JsValue> {657 let value = mrlyrs::core::Tensor::full(shape, value);658 hand::tensor_to_js(&value)659}660661/// Returns the byte at a multi-index.662#[wasm_bindgen]663pub fn tensor_get(tensor: JsValue, multi: &[usize]) -> Result<u8, JsValue> {664 let tensor = hand::tensor_from_js(&tensor)?;665 let value = tensor.get(multi).map_err(hand::throw)?;666 Ok(value)667}668669/// Wraps an i32 vector as a tensor of the shape.670#[wasm_bindgen]671pub fn tensor_i32(data: Vec<i32>, shape: Vec<usize>) -> Result<JsValue, JsValue> {672 let value = mrlyrs::core::Tensor::i32(data, shape).map_err(hand::throw)?;673 hand::tensor_to_js(&value)674}675676/// Returns the elements as i32s.677#[wasm_bindgen]678pub fn tensor_i32s(tensor: JsValue) -> Result<Vec<i32>, JsValue> {679 let tensor = hand::tensor_from_js(&tensor)?;680 let value = tensor.i32s().map_err(hand::throw)?;681 Ok(value.to_vec())682}683684/// Folds a multi-index into its flat index.685#[wasm_bindgen]686pub fn tensor_index(tensor: JsValue, multi: &[usize]) -> Result<usize, JsValue> {687 let tensor = hand::tensor_from_js(&tensor)?;688 let value = tensor.index(multi);689 Ok(value)690}691692/// Flips every element between zero and one.693#[wasm_bindgen]694pub fn tensor_invert(tensor: JsValue) -> Result<JsValue, JsValue> {695 let tensor = hand::tensor_from_js(&tensor)?;696 let value = tensor.invert();697 hand::tensor_to_js(&value)698}699700/// Builds the Kronecker product of the two tensors.701#[wasm_bindgen]702pub fn tensor_kron(tensor: JsValue, other: JsValue) -> Result<JsValue, JsValue> {703 let tensor = hand::tensor_from_js(&tensor)?;704 let other = hand::tensor_from_js(&other)?;705 let value = tensor.kron(&other);706 hand::tensor_to_js(&value)707}708709/// Numbers every position by its concentric ring out from the center.710#[wasm_bindgen]711pub fn tensor_layers(tensor: JsValue, dtype: JsValue) -> Result<JsValue, JsValue> {712 let tensor = hand::tensor_from_js(&tensor)?;713 let dtype = hand::from_js::<mrlyrs::core::Dtype>(&dtype)?;714 let value = tensor.layers(dtype);715 hand::tensor_to_js(&value)716}717718/// Counts each position's masked neighbors holding the target bit.719#[wasm_bindgen]720pub fn tensor_neighbors(tensor: JsValue, mask: JsValue, target: u8, wrap: bool, dtype: JsValue) -> Result<JsValue, JsValue> {721 let tensor = hand::tensor_from_js(&tensor)?;722 let mask = hand::tensor_from_js(&mask)?;723 let dtype = hand::from_js::<mrlyrs::core::Dtype>(&dtype)?;724 let value = tensor.neighbors(&mask, target, wrap, dtype).map_err(hand::throw)?;725 hand::tensor_to_js(&value)726}727728/// Builds a zeroed u8 tensor of the shape.729#[wasm_bindgen]730pub fn tensor_new(shape: Vec<usize>) -> Result<JsValue, JsValue> {731 let value = mrlyrs::core::Tensor::new(shape);732 hand::tensor_to_js(&value)733}734735/// Wraps a byte vector as a tensor of the shape.736#[wasm_bindgen]737pub fn tensor_of(data: Vec<u8>, shape: Vec<usize>) -> Result<JsValue, JsValue> {738 let value = mrlyrs::core::Tensor::of(data, shape).map_err(hand::throw)?;739 hand::tensor_to_js(&value)740}741742/// Returns the Otsu threshold splitting the histogram at greatest variance.743#[wasm_bindgen]744pub fn tensor_otsu_threshold(tensor: JsValue) -> Result<u8, JsValue> {745 let tensor = hand::tensor_from_js(&tensor)?;746 let value = tensor.otsu_threshold();747 Ok(value)748}749750/// Wraps the tensor in a count-thick border of one value.751#[wasm_bindgen]752pub fn tensor_pad(tensor: JsValue, count: usize, value: u8) -> Result<JsValue, JsValue> {753 let tensor = hand::tensor_from_js(&tensor)?;754 let value = tensor.pad(count, value);755 hand::tensor_to_js(&value)756}757758/// Stamps the value wherever the tiled mask is nonzero.759#[wasm_bindgen]760pub fn tensor_perforate(tensor: JsValue, mask: JsValue, value: u8) -> Result<JsValue, JsValue> {761 let tensor = hand::tensor_from_js(&tensor)?;762 let mask = hand::tensor_from_js(&mask)?;763 let value = tensor.perforate(&mask, value).map_err(hand::throw)?;764 hand::tensor_to_js(&value)765}766767/// Writes the element at a flat index, which must be below the size like a slice index.768#[wasm_bindgen]769pub fn tensor_put(tensor: JsValue, flat: usize, value: JsValue) -> Result<(), JsValue> {770 let mut tensor_value = hand::tensor_from_js(&tensor)?;771 let value = hand::i64_from_js(&value)?;772 tensor_value.put(flat, value);773 hand::tensor_into_js(&tensor, &tensor_value)?;774 Ok(())775}776777/// Rotates the tensor k quarter turns in the plane of two axes.778#[wasm_bindgen]779pub fn tensor_rot90(tensor: JsValue, k: usize, axes: JsValue) -> Result<JsValue, JsValue> {780 let tensor = hand::tensor_from_js(&tensor)?;781 let axes = hand::from_js::<(usize, usize)>(&axes)?;782 let value = tensor.rot90(k, axes).map_err(hand::throw)?;783 hand::tensor_to_js(&value)784}785786/// Writes the byte at a multi-index.787#[wasm_bindgen]788pub fn tensor_set(tensor: JsValue, multi: &[usize], value: u8) -> Result<(), JsValue> {789 let mut tensor_value = hand::tensor_from_js(&tensor)?;790 tensor_value.set(multi, value).map_err(hand::throw)?;791 hand::tensor_into_js(&tensor, &tensor_value)?;792 Ok(())793}794795/// Returns the number of elements.796#[wasm_bindgen]797pub fn tensor_size(tensor: JsValue) -> Result<usize, JsValue> {798 let tensor = hand::tensor_from_js(&tensor)?;799 let value = tensor.size();800 Ok(value)801}802803/// Drops one axis by fixing it at an index.804#[wasm_bindgen]805pub fn tensor_slice(tensor: JsValue, axis: usize, index: usize) -> Result<JsValue, JsValue> {806 let tensor = hand::tensor_from_js(&tensor)?;807 let value = tensor.slice(axis, index).map_err(hand::throw)?;808 hand::tensor_to_js(&value)809}810811/// Returns the sum of all elements.812#[wasm_bindgen]813pub fn tensor_sum(tensor: JsValue) -> Result<u64, JsValue> {814 let tensor = hand::tensor_from_js(&tensor)?;815 let value = tensor.sum();816 Ok(value)817}818819/// Repeats the tensor the given number of times along each axis.820#[wasm_bindgen]821pub fn tensor_tile(tensor: JsValue, reps: &[usize]) -> Result<JsValue, JsValue> {822 let tensor = hand::tensor_from_js(&tensor)?;823 let value = tensor.tile(reps).map_err(hand::throw)?;824 hand::tensor_to_js(&value)825}826827/// Swaps two axes.828#[wasm_bindgen]829pub fn tensor_transpose(tensor: JsValue, a: usize, b: usize) -> Result<JsValue, JsValue> {830 let tensor = hand::tensor_from_js(&tensor)?;831 let value = tensor.transpose(a, b).map_err(hand::throw)?;832 hand::tensor_to_js(&value)833}834835/// Builds a zeroed tensor of the shape and width.836#[wasm_bindgen]837pub fn tensor_typed(shape: Vec<usize>, dtype: JsValue) -> Result<JsValue, JsValue> {838 let dtype = hand::from_js::<mrlyrs::core::Dtype>(&dtype)?;839 let value = mrlyrs::core::Tensor::typed(shape, dtype);840 hand::tensor_to_js(&value)841}842843/// Wraps a u16 vector as a tensor of the shape.844#[wasm_bindgen]845pub fn tensor_u16(data: Vec<u16>, shape: Vec<usize>) -> Result<JsValue, JsValue> {846 let value = mrlyrs::core::Tensor::u16(data, shape).map_err(hand::throw)?;847 hand::tensor_to_js(&value)848}849850/// Returns the elements as u16s.851#[wasm_bindgen]852pub fn tensor_u16s(tensor: JsValue) -> Result<Vec<u16>, JsValue> {853 let tensor = hand::tensor_from_js(&tensor)?;854 let value = tensor.u16s().map_err(hand::throw)?;855 Ok(value.to_vec())856}857858/// Wraps a u32 vector as a tensor of the shape.859#[wasm_bindgen]860pub fn tensor_u32(data: Vec<u32>, shape: Vec<usize>) -> Result<JsValue, JsValue> {861 let value = mrlyrs::core::Tensor::u32(data, shape).map_err(hand::throw)?;862 hand::tensor_to_js(&value)863}864865/// Returns the elements as u32s.866#[wasm_bindgen]867pub fn tensor_u32s(tensor: JsValue) -> Result<Vec<u32>, JsValue> {868 let tensor = hand::tensor_from_js(&tensor)?;869 let value = tensor.u32s().map_err(hand::throw)?;870 Ok(value.to_vec())871}872873/// Wraps a u8 vector as a tensor of the shape, the same door as [`Tensor::of`].874#[wasm_bindgen]875pub fn tensor_u8(data: Vec<u8>, shape: Vec<usize>) -> Result<JsValue, JsValue> {876 let value = mrlyrs::core::Tensor::u8(data, shape).map_err(hand::throw)?;877 hand::tensor_to_js(&value)878}879880/// Decodes a png to its width, height, and rgba colors.881#[wasm_bindgen]882pub fn unpng(bytes: &[u8]) -> Result<JsValue, JsValue> {883 let value = mrlyrs::core::unpng(bytes).map_err(hand::throw)?;884 Ok(hand::tuple_to_js(&[hand::to_js(&value.0)?, hand::to_js(&value.1)?, hand::list_to_js(&value.2, |x2| Ok(hand::typed(&(*x2)[..])))?]))885}886887/// The height of an equilateral triangle over its side, the squash a hex rendering wears.888#[wasm_bindgen]889pub fn HEX_RATIO() -> Result<f64, JsValue> {890 let value = mrlyrs::core::HEX_RATIO;891 Ok(value)892}893894/// The eight bytes every png file starts with.895#[wasm_bindgen]896pub fn PNG_MAGIC() -> Result<Vec<u8>, JsValue> {897 let value = mrlyrs::core::PNG_MAGIC;898 Ok(value.to_vec())899}900901/// The fully transparent color.902#[wasm_bindgen]903pub fn colors_ALPHA() -> Result<JsValue, JsValue> {904 let value = mrlyrs::core::colors::ALPHA;905 Ok(hand::color_to_js(value))906}907908/// The palette black, #000000.909#[wasm_bindgen]910pub fn colors_BLACK() -> Result<JsValue, JsValue> {911 let value = mrlyrs::core::colors::BLACK;912 Ok(hand::color_to_js(value))913}914915/// The palette blue, #008cff.916#[wasm_bindgen]917pub fn colors_BLUE() -> Result<JsValue, JsValue> {918 let value = mrlyrs::core::colors::BLUE;919 Ok(hand::color_to_js(value))920}921922/// The palette brown, #b18462.923#[wasm_bindgen]924pub fn colors_BROWN() -> Result<JsValue, JsValue> {925 let value = mrlyrs::core::colors::BROWN;926 Ok(hand::color_to_js(value))927}928929/// The palette cyan, #1ec9f3.930#[wasm_bindgen]931pub fn colors_CYAN() -> Result<JsValue, JsValue> {932 let value = mrlyrs::core::colors::CYAN;933 Ok(hand::color_to_js(value))934}935936/// The dark theme.937#[wasm_bindgen]938pub fn colors_DARK() -> Result<colors_Theme, JsValue> {939 let value = mrlyrs::core::colors::DARK;940 Ok(colors_Theme { inner: value })941}942943/// The palette gray, #8e8e93.944#[wasm_bindgen]945pub fn colors_GRAY() -> Result<JsValue, JsValue> {946 let value = mrlyrs::core::colors::GRAY;947 Ok(hand::color_to_js(value))948}949950/// The palette green, #32cc58.951#[wasm_bindgen]952pub fn colors_GREEN() -> Result<JsValue, JsValue> {953 let value = mrlyrs::core::colors::GREEN;954 Ok(hand::color_to_js(value))955}956957/// The palette indigo, #6768fa.958#[wasm_bindgen]959pub fn colors_INDIGO() -> Result<JsValue, JsValue> {960 let value = mrlyrs::core::colors::INDIGO;961 Ok(hand::color_to_js(value))962}963964/// The light theme.965#[wasm_bindgen]966pub fn colors_LIGHT() -> Result<colors_Theme, JsValue> {967 let value = mrlyrs::core::colors::LIGHT;968 Ok(colors_Theme { inner: value })969}970971/// The palette mint, #00d1bb.972#[wasm_bindgen]973pub fn colors_MINT() -> Result<JsValue, JsValue> {974 let value = mrlyrs::core::colors::MINT;975 Ok(hand::color_to_js(value))976}977978/// The fifteen names, in palette order.979#[wasm_bindgen]980pub fn colors_NAMES() -> Result<JsValue, JsValue> {981 let value = mrlyrs::core::colors::NAMES;982 hand::to_js(&value)983}984985/// The palette orange, #ff8f2c.986#[wasm_bindgen]987pub fn colors_ORANGE() -> Result<JsValue, JsValue> {988 let value = mrlyrs::core::colors::ORANGE;989 Ok(hand::color_to_js(value))990}991992/// The fifteen colors, in name order.993#[wasm_bindgen]994pub fn colors_PALETTE() -> Result<JsValue, JsValue> {995 let value = mrlyrs::core::colors::PALETTE;996 hand::list_to_js(&value, |x1| Ok(hand::color_to_js(*x1)))997}998999/// The palette pink, #ff325a.1000#[wasm_bindgen]1001pub fn colors_PINK() -> Result<JsValue, JsValue> {1002 let value = mrlyrs::core::colors::PINK;1003 Ok(hand::color_to_js(value))1004}10051006/// The palette purple, #d332e9.1007#[wasm_bindgen]1008pub fn colors_PURPLE() -> Result<JsValue, JsValue> {1009 let value = mrlyrs::core::colors::PURPLE;1010 Ok(hand::color_to_js(value))1011}10121013/// The palette red, #ff3d40.1014#[wasm_bindgen]1015pub fn colors_RED() -> Result<JsValue, JsValue> {1016 let value = mrlyrs::core::colors::RED;1017 Ok(hand::color_to_js(value))1018}10191020/// The palette teal, #00cad8.1021#[wasm_bindgen]1022pub fn colors_TEAL() -> Result<JsValue, JsValue> {1023 let value = mrlyrs::core::colors::TEAL;1024 Ok(hand::color_to_js(value))1025}10261027/// The palette white, #ffffff.1028#[wasm_bindgen]1029pub fn colors_WHITE() -> Result<JsValue, JsValue> {1030 let value = mrlyrs::core::colors::WHITE;1031 Ok(hand::color_to_js(value))1032}10331034/// The palette yellow, #ffd100.1035#[wasm_bindgen]1036pub fn colors_YELLOW() -> Result<JsValue, JsValue> {1037 let value = mrlyrs::core::colors::YELLOW;1038 Ok(hand::color_to_js(value))1039}10401041/// A paletted image: rows of palette indices and the palette they point into, hex strings in json.1042#[wasm_bindgen]1043pub struct Image {1044 inner: mrlyrs::core::Image,1045}10461047#[wasm_bindgen]1048impl Image {1049 /// Reads the Image from its plain data.1050 #[wasm_bindgen(js_name = "from")]1051 pub fn from_plain(data: JsValue) -> Result<Image, JsValue> {1052 Ok(Image { inner: hand::from_js(&data)? })1053 }1054 /// Writes the Image as plain data.1055 #[wasm_bindgen(js_name = "toJSON")]1056 pub fn to_plain(&self) -> Result<JsValue, JsValue> {1057 hand::to_js(&self.inner)1058 }1059 /// The width in pixels.1060 #[wasm_bindgen(getter)]1061 pub fn width(&self) -> Result<usize, JsValue> {1062 let value = self.inner.width;1063 Ok(value)1064 }1065 #[wasm_bindgen(setter)]1066 pub fn set_width(&mut self, value: usize) -> Result<(), JsValue> {1067 self.inner.width = value;1068 Ok(())1069 }1070 /// The height in pixels.1071 #[wasm_bindgen(getter)]1072 pub fn height(&self) -> Result<usize, JsValue> {1073 let value = self.inner.height;1074 Ok(value)1075 }1076 #[wasm_bindgen(setter)]1077 pub fn set_height(&mut self, value: usize) -> Result<(), JsValue> {1078 self.inner.height = value;1079 Ok(())1080 }1081 /// The palette index of every pixel, row by row.1082 #[wasm_bindgen(getter)]1083 pub fn rows(&self) -> Result<JsValue, JsValue> {1084 let value = self.inner.rows.clone();1085 hand::list_to_js(&value, |x1| Ok(hand::typed(&(*x1)[..])))1086 }1087 #[wasm_bindgen(setter)]1088 pub fn set_rows(&mut self, value: JsValue) -> Result<(), JsValue> {1089 let value = hand::from_js::<Vec<Vec<usize>>>(&value)?;1090 self.inner.rows = value;1091 Ok(())1092 }1093 /// The colors the rows index.1094 #[wasm_bindgen(getter)]1095 pub fn palette(&self) -> Result<JsValue, JsValue> {1096 let value = self.inner.palette.clone();1097 hand::list_to_js(&value, |x1| Ok(hand::color_to_js(*x1)))1098 }1099 #[wasm_bindgen(setter)]1100 pub fn set_palette(&mut self, value: JsValue) -> Result<(), JsValue> {1101 let value = hand::list_from_js(&value, hand::color_from_js)?;1102 self.inner.palette = value;1103 Ok(())1104 }1105 /// Returns the flat rgba pixels, transparent wherever an index misses the palette.1106 pub fn colors(&self) -> Result<JsValue, JsValue> {1107 let value = self.inner.colors();1108 hand::list_to_js(&value, |x1| Ok(hand::typed(&(*x1)[..])))1109 }1110 /// Builds a paletted image from raw rgba pixels, growing the palette as new colors appear.1111 pub fn from_pixels(width: usize, height: usize, pixels: JsValue) -> Result<Image, JsValue> {1112 let pixels = hand::from_js::<Vec<[u8; 4]>>(&pixels)?;1113 let value = mrlyrs::core::Image::from_pixels(width, height, &pixels);1114 Ok(Image { inner: value })1115 }1116 /// Builds an image from its four parts.1117 #[wasm_bindgen(constructor)]1118 pub fn new(width: usize, height: usize, rows: JsValue, palette: JsValue) -> Result<Image, JsValue> {1119 let rows = hand::from_js::<Vec<Vec<usize>>>(&rows)?;1120 let palette = hand::list_from_js(&palette, hand::color_from_js)?;1121 let value = mrlyrs::core::Image::new(width, height, rows, palette);1122 Ok(Image { inner: value })1123 }1124 /// Encodes the image as a png at the given scale.1125 pub fn png(&self, scale: usize) -> Result<Vec<u8>, JsValue> {1126 let value = self.inner.png(scale).map_err(hand::throw)?;1127 Ok(value)1128 }1129 /// Resamples the image to a new size, its palette rebuilt from the blended pixels.1130 pub fn resample(&self, width: usize, height: usize, filter: JsValue) -> Result<Image, JsValue> {1131 let filter = hand::from_js::<mrlyrs::core::Filter>(&filter)?;1132 let value = self.inner.resample(width, height, filter).map_err(hand::throw)?;1133 Ok(Image { inner: value })1134 }1135}11361137/// One theme: the surfaces of a dark or a light ground and the thirteen inks, the same on both.1138#[wasm_bindgen]1139pub struct colors_Theme {1140 inner: mrlyrs::core::colors::Theme,1141}11421143#[wasm_bindgen]1144impl colors_Theme {1145 /// Reads the Theme from its plain data.1146 #[wasm_bindgen(js_name = "from")]1147 pub fn from_plain(data: JsValue) -> Result<colors_Theme, JsValue> {1148 Ok(colors_Theme { inner: hand::from_js(&data)? })1149 }1150 /// Writes the Theme as plain data.1151 #[wasm_bindgen(js_name = "toJSON")]1152 pub fn to_plain(&self) -> Result<JsValue, JsValue> {1153 hand::to_js(&self.inner)1154 }1155 /// The ground every figure is painted on.1156 #[wasm_bindgen(getter)]1157 pub fn ground(&self) -> Result<JsValue, JsValue> {1158 let value = self.inner.ground;1159 Ok(hand::color_to_js(value))1160 }1161 #[wasm_bindgen(setter)]1162 pub fn set_ground(&mut self, value: JsValue) -> Result<(), JsValue> {1163 let value = hand::color_from_js(&value)?;1164 self.inner.ground = value;1165 Ok(())1166 }1167 /// The page background, one step off the ground.1168 #[wasm_bindgen(getter)]1169 pub fn bg(&self) -> Result<JsValue, JsValue> {1170 let value = self.inner.bg;1171 Ok(hand::color_to_js(value))1172 }1173 #[wasm_bindgen(setter)]1174 pub fn set_bg(&mut self, value: JsValue) -> Result<(), JsValue> {1175 let value = hand::color_from_js(&value)?;1176 self.inner.bg = value;1177 Ok(())1178 }1179 /// The raised panel.1180 #[wasm_bindgen(getter)]1181 pub fn panel(&self) -> Result<JsValue, JsValue> {1182 let value = self.inner.panel;1183 Ok(hand::color_to_js(value))1184 }1185 #[wasm_bindgen(setter)]1186 pub fn set_panel(&mut self, value: JsValue) -> Result<(), JsValue> {1187 let value = hand::color_from_js(&value)?;1188 self.inner.panel = value;1189 Ok(())1190 }1191 /// The sunken well.1192 #[wasm_bindgen(getter)]1193 pub fn deep(&self) -> Result<JsValue, JsValue> {1194 let value = self.inner.deep;1195 Ok(hand::color_to_js(value))1196 }1197 #[wasm_bindgen(setter)]1198 pub fn set_deep(&mut self, value: JsValue) -> Result<(), JsValue> {1199 let value = hand::color_from_js(&value)?;1200 self.inner.deep = value;1201 Ok(())1202 }1203 /// The hairline between things.1204 #[wasm_bindgen(getter)]1205 pub fn line(&self) -> Result<JsValue, JsValue> {1206 let value = self.inner.line;1207 Ok(hand::color_to_js(value))1208 }1209 #[wasm_bindgen(setter)]1210 pub fn set_line(&mut self, value: JsValue) -> Result<(), JsValue> {1211 let value = hand::color_from_js(&value)?;1212 self.inner.line = value;1213 Ok(())1214 }1215 /// The foreground, the strongest tone.1216 #[wasm_bindgen(getter)]1217 pub fn fg(&self) -> Result<JsValue, JsValue> {1218 let value = self.inner.fg;1219 Ok(hand::color_to_js(value))1220 }1221 #[wasm_bindgen(setter)]1222 pub fn set_fg(&mut self, value: JsValue) -> Result<(), JsValue> {1223 let value = hand::color_from_js(&value)?;1224 self.inner.fg = value;1225 Ok(())1226 }1227 /// The dimmed foreground, for anything secondary.1228 #[wasm_bindgen(getter)]1229 pub fn dim(&self) -> Result<JsValue, JsValue> {1230 let value = self.inner.dim;1231 Ok(hand::color_to_js(value))1232 }1233 #[wasm_bindgen(setter)]1234 pub fn set_dim(&mut self, value: JsValue) -> Result<(), JsValue> {1235 let value = hand::color_from_js(&value)?;1236 self.inner.dim = value;1237 Ok(())1238 }1239 /// The interactive accent.1240 #[wasm_bindgen(getter)]1241 pub fn accent(&self) -> Result<JsValue, JsValue> {1242 let value = self.inner.accent;1243 Ok(hand::color_to_js(value))1244 }1245 #[wasm_bindgen(setter)]1246 pub fn set_accent(&mut self, value: JsValue) -> Result<(), JsValue> {1247 let value = hand::color_from_js(&value)?;1248 self.inner.accent = value;1249 Ok(())1250 }1251 /// The tone written on the accent.1252 #[wasm_bindgen(getter)]1253 pub fn on_accent(&self) -> Result<JsValue, JsValue> {1254 let value = self.inner.on_accent;1255 Ok(hand::color_to_js(value))1256 }1257 #[wasm_bindgen(setter)]1258 pub fn set_on_accent(&mut self, value: JsValue) -> Result<(), JsValue> {1259 let value = hand::color_from_js(&value)?;1260 self.inner.on_accent = value;1261 Ok(())1262 }1263 /// The red ink.1264 #[wasm_bindgen(getter)]1265 pub fn red(&self) -> Result<JsValue, JsValue> {1266 let value = self.inner.red;1267 Ok(hand::color_to_js(value))1268 }1269 #[wasm_bindgen(setter)]1270 pub fn set_red(&mut self, value: JsValue) -> Result<(), JsValue> {1271 let value = hand::color_from_js(&value)?;1272 self.inner.red = value;1273 Ok(())1274 }1275 /// The orange ink.1276 #[wasm_bindgen(getter)]1277 pub fn orange(&self) -> Result<JsValue, JsValue> {1278 let value = self.inner.orange;1279 Ok(hand::color_to_js(value))1280 }1281 #[wasm_bindgen(setter)]1282 pub fn set_orange(&mut self, value: JsValue) -> Result<(), JsValue> {1283 let value = hand::color_from_js(&value)?;1284 self.inner.orange = value;1285 Ok(())1286 }1287 /// The yellow ink.1288 #[wasm_bindgen(getter)]1289 pub fn yellow(&self) -> Result<JsValue, JsValue> {1290 let value = self.inner.yellow;1291 Ok(hand::color_to_js(value))1292 }1293 #[wasm_bindgen(setter)]1294 pub fn set_yellow(&mut self, value: JsValue) -> Result<(), JsValue> {1295 let value = hand::color_from_js(&value)?;1296 self.inner.yellow = value;1297 Ok(())1298 }1299 /// The green ink.1300 #[wasm_bindgen(getter)]1301 pub fn green(&self) -> Result<JsValue, JsValue> {1302 let value = self.inner.green;1303 Ok(hand::color_to_js(value))1304 }1305 #[wasm_bindgen(setter)]1306 pub fn set_green(&mut self, value: JsValue) -> Result<(), JsValue> {1307 let value = hand::color_from_js(&value)?;1308 self.inner.green = value;1309 Ok(())1310 }1311 /// The mint ink.1312 #[wasm_bindgen(getter)]1313 pub fn mint(&self) -> Result<JsValue, JsValue> {1314 let value = self.inner.mint;1315 Ok(hand::color_to_js(value))1316 }1317 #[wasm_bindgen(setter)]1318 pub fn set_mint(&mut self, value: JsValue) -> Result<(), JsValue> {1319 let value = hand::color_from_js(&value)?;1320 self.inner.mint = value;1321 Ok(())1322 }1323 /// The teal ink.1324 #[wasm_bindgen(getter)]1325 pub fn teal(&self) -> Result<JsValue, JsValue> {1326 let value = self.inner.teal;1327 Ok(hand::color_to_js(value))1328 }1329 #[wasm_bindgen(setter)]1330 pub fn set_teal(&mut self, value: JsValue) -> Result<(), JsValue> {1331 let value = hand::color_from_js(&value)?;1332 self.inner.teal = value;1333 Ok(())1334 }1335 /// The cyan ink.1336 #[wasm_bindgen(getter)]1337 pub fn cyan(&self) -> Result<JsValue, JsValue> {1338 let value = self.inner.cyan;1339 Ok(hand::color_to_js(value))1340 }1341 #[wasm_bindgen(setter)]1342 pub fn set_cyan(&mut self, value: JsValue) -> Result<(), JsValue> {1343 let value = hand::color_from_js(&value)?;1344 self.inner.cyan = value;1345 Ok(())1346 }1347 /// The blue ink.1348 #[wasm_bindgen(getter)]1349 pub fn blue(&self) -> Result<JsValue, JsValue> {1350 let value = self.inner.blue;1351 Ok(hand::color_to_js(value))1352 }1353 #[wasm_bindgen(setter)]1354 pub fn set_blue(&mut self, value: JsValue) -> Result<(), JsValue> {1355 let value = hand::color_from_js(&value)?;1356 self.inner.blue = value;1357 Ok(())1358 }1359 /// The indigo ink.1360 #[wasm_bindgen(getter)]1361 pub fn indigo(&self) -> Result<JsValue, JsValue> {1362 let value = self.inner.indigo;1363 Ok(hand::color_to_js(value))1364 }1365 #[wasm_bindgen(setter)]1366 pub fn set_indigo(&mut self, value: JsValue) -> Result<(), JsValue> {1367 let value = hand::color_from_js(&value)?;1368 self.inner.indigo = value;1369 Ok(())1370 }1371 /// The purple ink.1372 #[wasm_bindgen(getter)]1373 pub fn purple(&self) -> Result<JsValue, JsValue> {1374 let value = self.inner.purple;1375 Ok(hand::color_to_js(value))1376 }1377 #[wasm_bindgen(setter)]1378 pub fn set_purple(&mut self, value: JsValue) -> Result<(), JsValue> {1379 let value = hand::color_from_js(&value)?;1380 self.inner.purple = value;1381 Ok(())1382 }1383 /// The pink ink.1384 #[wasm_bindgen(getter)]1385 pub fn pink(&self) -> Result<JsValue, JsValue> {1386 let value = self.inner.pink;1387 Ok(hand::color_to_js(value))1388 }1389 #[wasm_bindgen(setter)]1390 pub fn set_pink(&mut self, value: JsValue) -> Result<(), JsValue> {1391 let value = hand::color_from_js(&value)?;1392 self.inner.pink = value;1393 Ok(())1394 }1395 /// The brown ink.1396 #[wasm_bindgen(getter)]1397 pub fn brown(&self) -> Result<JsValue, JsValue> {1398 let value = self.inner.brown;1399 Ok(hand::color_to_js(value))1400 }1401 #[wasm_bindgen(setter)]1402 pub fn set_brown(&mut self, value: JsValue) -> Result<(), JsValue> {1403 let value = hand::color_from_js(&value)?;1404 self.inner.brown = value;1405 Ok(())1406 }1407 /// The gray ink.1408 #[wasm_bindgen(getter)]1409 pub fn gray(&self) -> Result<JsValue, JsValue> {1410 let value = self.inner.gray;1411 Ok(hand::color_to_js(value))1412 }1413 #[wasm_bindgen(setter)]1414 pub fn set_gray(&mut self, value: JsValue) -> Result<(), JsValue> {1415 let value = hand::color_from_js(&value)?;1416 self.inner.gray = value;1417 Ok(())1418 }1419 /// The thirteen inks in name order.1420 pub fn hues(&self) -> Result<JsValue, JsValue> {1421 let value = self.inner.hues();1422 hand::list_to_js(&value, |x1| Ok(hand::color_to_js(*x1)))1423 }1424 /// The six inks a figure cycles through: blue, orange, yellow, green, pink, indigo.1425 pub fn inks(&self) -> Result<JsValue, JsValue> {1426 let value = self.inner.inks();1427 hand::list_to_js(&value, |x1| Ok(hand::color_to_js(*x1)))1428 }1429}14301431/// A complete coloring recipe for one cell.1432#[wasm_bindgen]1433pub struct paint_Paint {1434 inner: mrlyrs::core::paint::Paint,1435}14361437#[wasm_bindgen]1438impl paint_Paint {1439 /// Reads the Paint from its plain data.1440 #[wasm_bindgen(js_name = "from")]1441 pub fn from_plain(data: JsValue) -> Result<paint_Paint, JsValue> {1442 Ok(paint_Paint { inner: hand::from_js(&data)? })1443 }1444 /// Writes the Paint as plain data.1445 #[wasm_bindgen(js_name = "toJSON")]1446 pub fn to_plain(&self) -> Result<JsValue, JsValue> {1447 hand::to_js(&self.inner)1448 }1449 /// The coloring edition.1450 #[wasm_bindgen(getter)]1451 pub fn edition(&self) -> Result<JsValue, JsValue> {1452 let value = self.inner.edition;1453 hand::to_js(&value)1454 }1455 #[wasm_bindgen(setter)]1456 pub fn set_edition(&mut self, value: JsValue) -> Result<(), JsValue> {1457 let value = hand::from_js::<mrlyrs::core::paint::Edition>(&value)?;1458 self.inner.edition = value;1459 Ok(())1460 }1461 /// The secondary color scheme.1462 #[wasm_bindgen(getter)]1463 pub fn scheme(&self) -> Result<JsValue, JsValue> {1464 let value = self.inner.scheme;1465 hand::to_js(&value)1466 }1467 #[wasm_bindgen(setter)]1468 pub fn set_scheme(&mut self, value: JsValue) -> Result<(), JsValue> {1469 let value = hand::from_js::<mrlyrs::core::paint::Scheme>(&value)?;1470 self.inner.scheme = value;1471 Ok(())1472 }1473 /// The side the primary ink lands on.1474 #[wasm_bindgen(getter)]1475 pub fn target(&self) -> Result<JsValue, JsValue> {1476 let value = self.inner.target;1477 hand::to_js(&value)1478 }1479 #[wasm_bindgen(setter)]1480 pub fn set_target(&mut self, value: JsValue) -> Result<(), JsValue> {1481 let value = hand::from_js::<mrlyrs::core::paint::Target>(&value)?;1482 self.inner.target = value;1483 Ok(())1484 }1485 /// The primary ink.1486 #[wasm_bindgen(getter)]1487 pub fn primary(&self) -> Result<JsValue, JsValue> {1488 let value = self.inner.primary;1489 hand::to_js(&value)1490 }1491 #[wasm_bindgen(setter)]1492 pub fn set_primary(&mut self, value: JsValue) -> Result<(), JsValue> {1493 let value = hand::from_js::<mrlyrs::core::paint::Ink>(&value)?;1494 self.inner.primary = value;1495 Ok(())1496 }1497 /// The secondary inks.1498 #[wasm_bindgen(getter)]1499 pub fn secondary(&self) -> Result<JsValue, JsValue> {1500 let value = self.inner.secondary.clone();1501 hand::to_js(&value)1502 }1503 #[wasm_bindgen(setter)]1504 pub fn set_secondary(&mut self, value: JsValue) -> Result<(), JsValue> {1505 let value = hand::from_js::<Vec<mrlyrs::core::paint::Ink>>(&value)?;1506 self.inner.secondary = value;1507 Ok(())1508 }1509 /// The shade indices of a multitone ramp.1510 #[wasm_bindgen(getter)]1511 pub fn shades(&self) -> Result<Vec<usize>, JsValue> {1512 let value = self.inner.shades.clone();1513 Ok(value)1514 }1515 #[wasm_bindgen(setter)]1516 pub fn set_shades(&mut self, value: Vec<usize>) -> Result<(), JsValue> {1517 self.inner.shades = value;1518 Ok(())1519 }1520 /// Returns true for the Simple edition.1521 pub fn is_simple(&self) -> Result<bool, JsValue> {1522 let value = self.inner.is_simple();1523 Ok(value)1524 }1525 /// Builds a black-primary, fill-target, multicolor paint for an edition.1526 #[wasm_bindgen(constructor)]1527 pub fn new(edition: JsValue) -> Result<paint_Paint, JsValue> {1528 let edition = hand::from_js::<mrlyrs::core::paint::Edition>(&edition)?;1529 let value = mrlyrs::core::paint::Paint::new(edition);1530 Ok(paint_Paint { inner: value })1531 }1532}15331534/// A rule that turns counter values into colors.1535#[wasm_bindgen]1536pub struct Colorizer {}15371538#[wasm_bindgen]1539impl Colorizer {1540 /// Returns the default Colorizer.1541 #[wasm_bindgen(js_name = "default")]1542 pub fn default_() -> Result<JsValue, JsValue> {1543 let value = mrlyrs::core::Colorizer::default();1544 hand::to_js(&value)1545 }1546 /// Builds the blue-to-red diverging ramp around a white middle.1547 pub fn diverge() -> Result<JsValue, JsValue> {1548 let value = mrlyrs::core::Colorizer::diverge();1549 hand::to_js(&value)1550 }1551 /// Builds the black-through-ember fire ramp: black, dark red, orange, light yellow.1552 pub fn fire() -> Result<JsValue, JsValue> {1553 let value = mrlyrs::core::Colorizer::fire();1554 hand::to_js(&value)1555 }1556 /// Builds a binned colorizer from a gradient through the given stops.1557 pub fn gradient_bins(background: JsValue, colors: JsValue, shades: usize) -> Result<JsValue, JsValue> {1558 let background = hand::color_from_js(&background)?;1559 let colors = hand::list_from_js(&colors, hand::color_from_js)?;1560 let value = mrlyrs::core::Colorizer::gradient_bins(background, &colors, shades).map_err(hand::throw)?;1561 hand::to_js(&value)1562 }1563 /// Builds the white-to-black heat ramp.1564 pub fn heat() -> Result<JsValue, JsValue> {1565 let value = mrlyrs::core::Colorizer::heat();1566 hand::to_js(&value)1567 }1568}15691570/// The element widths a tensor can hold.1571#[wasm_bindgen]1572pub struct Dtype {}15731574#[wasm_bindgen]1575impl Dtype {1576 /// Returns the largest value the width can hold.1577 pub fn max(dtype: JsValue) -> Result<i64, JsValue> {1578 let dtype = hand::from_js::<mrlyrs::core::Dtype>(&dtype)?;1579 let value = dtype.max();1580 Ok(value)1581 }1582}15831584/// The constraints a caller may put on a random paint.1585#[wasm_bindgen]1586pub struct paint_Config {}15871588#[wasm_bindgen]1589impl paint_Config {1590 /// Returns the default Config.1591 #[wasm_bindgen(js_name = "default")]1592 pub fn default_() -> Result<JsValue, JsValue> {1593 let value = mrlyrs::core::paint::Config::default();1594 hand::to_js(&value)1595 }1596}15971598/// The seven ways a paint distributes its colors over a cell.1599#[wasm_bindgen]1600pub struct paint_Edition {}16011602#[wasm_bindgen]1603impl paint_Edition {1604 /// Returns every Edition in canonical order.1605 pub fn all() -> Result<JsValue, JsValue> {1606 let value = mrlyrs::core::paint::Edition::all();1607 hand::to_js(&value)1608 }1609 /// Returns the cell-painting mode this edition renders with, or None for Random, which scatters.1610 pub fn mode(edition: JsValue) -> Result<JsValue, JsValue> {1611 let edition = hand::from_js::<mrlyrs::core::paint::Edition>(&edition)?;1612 let value = edition.mode();1613 hand::to_js(&value)1614 }1615}16161617/// The fifteen named inks a paint draws from.1618#[wasm_bindgen]1619pub struct paint_Ink {}16201621#[wasm_bindgen]1622impl paint_Ink {1623 /// Returns every Ink in canonical order.1624 pub fn all() -> Result<JsValue, JsValue> {1625 let value = mrlyrs::core::paint::Ink::all();1626 hand::to_js(&value)1627 }1628 /// Returns the ink's color.1629 pub fn color(ink: JsValue) -> Result<JsValue, JsValue> {1630 let ink = hand::from_js::<mrlyrs::core::paint::Ink>(&ink)?;1631 let value = ink.color();1632 Ok(hand::color_to_js(value))1633 }1634}16351636/// The two ways secondary colors are drawn.1637#[wasm_bindgen]1638pub struct paint_Scheme {}16391640#[wasm_bindgen]1641impl paint_Scheme {1642 /// Returns every Scheme in canonical order.1643 pub fn all() -> Result<JsValue, JsValue> {1644 let value = mrlyrs::core::paint::Scheme::all();1645 hand::to_js(&value)1646 }1647}16481649/// The side of the figure the primary ink lands on.1650#[wasm_bindgen]1651pub struct paint_Target {}16521653#[wasm_bindgen]1654impl paint_Target {1655 /// Returns every Target in canonical order.1656 pub fn all() -> Result<JsValue, JsValue> {1657 let value = mrlyrs::core::paint::Target::all();1658 hand::to_js(&value)1659 }1660}