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}