From c0f32ed17af470344897fbb4a7c2022eb30cf836 Mon Sep 17 00:00:00 2001 From: Universe Date: Mon, 2 Mar 2026 20:56:16 +0900 Subject: [PATCH 1/5] feat: update vector network handling and add new dependencies - Refactored vector network construction methods to utilize `VectorGeometryShape`, enhancing shape representation with corner radius preservation. - Replaced deprecated `build_*_vector_network` functions with `build_*_vector_geometry` counterparts for polygons and stars. - Introduced new dependencies: `rendiff` for rendering differences and `imgref` for image reference handling. - Updated `Cargo.toml` to include new dependencies and their versions. This update aims to improve the accuracy and flexibility of vector shape handling in the grida-canvas project. --- Cargo.lock | 131 ++++++--- crates/grida-canvas/Cargo.toml | 2 + crates/grida-canvas/src/node/schema.rs | 6 +- crates/grida-canvas/src/shape/mod.rs | 6 +- crates/grida-canvas/src/shape/polygon.rs | 12 +- .../grida-canvas/src/shape/regular_polygon.rs | 6 +- crates/grida-canvas/src/shape/regular_star.rs | 9 +- crates/grida-canvas/src/shape/rrect.rs | 263 ++++++++++-------- crates/grida-canvas/src/shape/vector.rs | 11 + crates/grida-canvas/src/vectornetwork/vn.rs | 56 +++- .../tests/shape_to_vector_network.rs | 14 +- 11 files changed, 315 insertions(+), 201 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2254c9e300..ea245d0154 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -212,7 +212,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -241,7 +241,7 @@ checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -306,6 +306,12 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.22.1" @@ -329,7 +335,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn", + "syn 2.0.101", ] [[package]] @@ -491,9 +497,11 @@ dependencies = [ "figma-api", "futures", "gl", + "imgref", "json-patch", "math2", "pulldown-cmark", + "rendiff", "reqwest", "rstar", "seahash", @@ -596,7 +604,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -832,7 +840,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -862,7 +870,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn", + "syn 2.0.101", ] [[package]] @@ -873,7 +881,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -909,7 +917,7 @@ checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -949,7 +957,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -994,6 +1002,18 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "embed-doc-image" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af36f591236d9d822425cb6896595658fa558fcebf5ee8accac1d4b92c47166e" +dependencies = [ + "base64 0.13.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "encode_unicode" version = "1.0.0" @@ -1026,7 +1046,7 @@ checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -1099,7 +1119,7 @@ checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -1231,7 +1251,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -1321,7 +1341,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -1756,7 +1776,7 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1c293b6b3d21eca78250dc7dbebd6b9210ec5530e038cbfe0661b5c47ab06e8" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "futures-channel", "futures-core", @@ -2049,7 +2069,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -2324,7 +2344,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f44db74bde26fdf427af23f1d146c211aed857c59e3be750cf2617f6b0b05c94" dependencies = [ "proc-macro2", - "syn", + "syn 2.0.101", "synstructure", ] @@ -2519,7 +2539,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -2580,7 +2600,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -2910,7 +2930,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -3025,7 +3045,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -3060,7 +3080,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -3181,7 +3201,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dee91521343f4c5c6a63edd65e54f31f5c92fe8978c40a4282f8372194c6a7d" dependencies = [ "proc-macro2", - "syn", + "syn 2.0.101", ] [[package]] @@ -3218,7 +3238,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" dependencies = [ "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -3525,13 +3545,23 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "rendiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "056710053ba8867cb47a1a3c2b67319eb47294325450ea5ad757ee799d73c924" +dependencies = [ + "embed-doc-image", + "imgref", +] + [[package]] name = "reqwest" version = "0.12.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2f8e5513d63f2e5b386eb5106dc67eaf3f84e95258e210489136b8b92ad6119" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "encoding_rs", "futures-core", @@ -3830,7 +3860,7 @@ checksum = "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699cdb33" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -3853,7 +3883,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -3892,7 +3922,7 @@ version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" dependencies = [ - "base64", + "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", @@ -3913,7 +3943,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -3984,7 +4014,7 @@ version = "0.91.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f97f791b2d9d915947b424d76f212dc2d1c47c09a18e30546ab0edf0a8af89f" dependencies = [ - "base64", + "base64 0.22.1", "bitflags 2.9.1", "percent-encoding", "skia-bindings", @@ -3999,7 +4029,7 @@ checksum = "044dd2233c9717a74f75197f3e7f0a966db2127c0ffb5e05013b480a9b75b2c7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -4207,7 +4237,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn", + "syn 2.0.101", "synstructure", ] @@ -4279,6 +4309,17 @@ dependencies = [ "siphasher", ] +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.101" @@ -4307,7 +4348,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -4429,7 +4470,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -4440,7 +4481,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -4569,7 +4610,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn", + "syn 2.0.101", "synstructure", ] @@ -4597,7 +4638,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -4882,7 +4923,7 @@ dependencies = [ name = "usvg" version = "0.0.1" dependencies = [ - "base64", + "base64 0.22.1", "data-url", "flate2", "fontdb", @@ -5013,7 +5054,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn", + "syn 2.0.101", "wasm-bindgen-shared", ] @@ -5048,7 +5089,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5248,7 +5289,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -5259,7 +5300,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -5756,7 +5797,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", "synstructure", ] @@ -5777,7 +5818,7 @@ checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -5797,7 +5838,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", "synstructure", ] @@ -5837,7 +5878,7 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] diff --git a/crates/grida-canvas/Cargo.toml b/crates/grida-canvas/Cargo.toml index 11f5decfcd..875edc8073 100644 --- a/crates/grida-canvas/Cargo.toml +++ b/crates/grida-canvas/Cargo.toml @@ -53,6 +53,8 @@ native-clock-tick = [] criterion = "0.5" clap = { version = "4.5.39", features = ["derive"] } tokio = { version = "1", features = ["macros", "rt-multi-thread"] } +rendiff = "0.2" +imgref = "1.10" [[bench]] name = "bench_rectangles" diff --git a/crates/grida-canvas/src/node/schema.rs b/crates/grida-canvas/src/node/schema.rs index d9ca7da194..1bf78bf767 100644 --- a/crates/grida-canvas/src/node/schema.rs +++ b/crates/grida-canvas/src/node/schema.rs @@ -1813,7 +1813,7 @@ impl NodeShapeMixin for PolygonNodeRec { } fn to_vector_network(&self) -> VectorNetwork { - build_simple_polygon_vector_network(&self.to_own_shape()) + (&self.to_shape()).into() } } @@ -1930,7 +1930,7 @@ impl NodeShapeMixin for RegularPolygonNodeRec { } fn to_vector_network(&self) -> VectorNetwork { - build_regular_polygon_vector_network(&self.to_own_shape()) + (&self.to_shape()).into() } } @@ -2035,7 +2035,7 @@ impl NodeShapeMixin for RegularStarPolygonNodeRec { } fn to_vector_network(&self) -> VectorNetwork { - build_star_vector_network(&self.to_own_shape()) + (&self.to_shape()).into() } } diff --git a/crates/grida-canvas/src/shape/mod.rs b/crates/grida-canvas/src/shape/mod.rs index 3251fedc88..0b5810ffe4 100644 --- a/crates/grida-canvas/src/shape/mod.rs +++ b/crates/grida-canvas/src/shape/mod.rs @@ -71,7 +71,7 @@ impl Into for &Shape { Shape::OrthogonalSmoothRRect(shape) => { build_orthogonal_smooth_rrect_vector_network(shape) } - Shape::SimplePolygon(shape) => build_simple_polygon_vector_network(shape), + Shape::SimplePolygon(shape) => build_simple_polygon_vector_geometry(shape).into(), Shape::Ellipse(shape) => build_ellipse_vector_network(shape), Shape::EllipticalRingSector(_shape) => { todo!("Arc shape to vector network requires manual implementation") @@ -80,8 +80,8 @@ impl Into for &Shape { todo!("Arc shape to vector network requires manual implementation") } Shape::EllipticalRing(shape) => build_ring_vector_network(shape), - Shape::RegularStarPolygon(shape) => build_star_vector_network(shape), - Shape::RegularPolygon(shape) => build_regular_polygon_vector_network(shape), + Shape::RegularStarPolygon(shape) => build_star_vector_geometry(shape).into(), + Shape::RegularPolygon(shape) => build_regular_polygon_vector_geometry(shape).into(), } } } diff --git a/crates/grida-canvas/src/shape/polygon.rs b/crates/grida-canvas/src/shape/polygon.rs index 6c72dd9f08..eb2e5bcc2c 100644 --- a/crates/grida-canvas/src/shape/polygon.rs +++ b/crates/grida-canvas/src/shape/polygon.rs @@ -1,4 +1,4 @@ -use super::vn::{VectorNetwork, VectorNetworkSegment}; +use super::vn::VectorNetworkSegment; use super::*; use crate::cg::CGPoint; use math2::Rectangle; @@ -38,10 +38,8 @@ pub fn build_simple_polygon_path(shape: &SimplePolygonShape) -> skia_safe::Path build_corner_radius_path(&path, r) } -/// Build a [`VectorNetwork`] from the polygon points. Corner radius is ignored -/// in this conversion; resulting network represents the sharp-corner polygon. -#[deprecated(note = "use VectorGeometryShape instead")] -pub fn build_simple_polygon_vector_network(shape: &SimplePolygonShape) -> VectorNetwork { +/// Build a [`VectorGeometryShape`] from the polygon points, preserving the corner radius. +pub fn build_simple_polygon_vector_geometry(shape: &SimplePolygonShape) -> VectorGeometryShape { let n = shape.points.len(); assert!(n >= 3); let vertices: Vec<(f32, f32)> = shape.points.iter().map(|p| (p.x, p.y)).collect(); @@ -51,10 +49,10 @@ pub fn build_simple_polygon_vector_network(shape: &SimplePolygonShape) -> Vector let b = (i + 1) % n; segments.push(VectorNetworkSegment::ab(a, b)); } - VectorNetwork { + VectorGeometryShape { vertices, segments, - regions: vec![], + corner_radius: shape.corner_radius, } } diff --git a/crates/grida-canvas/src/shape/regular_polygon.rs b/crates/grida-canvas/src/shape/regular_polygon.rs index 7255e5cb0b..7f3bfe8477 100644 --- a/crates/grida-canvas/src/shape/regular_polygon.rs +++ b/crates/grida-canvas/src/shape/regular_polygon.rs @@ -1,4 +1,3 @@ -use super::vn::VectorNetwork; use super::*; use crate::{cg::*, shape::build_simple_polygon_path}; @@ -41,8 +40,9 @@ pub fn build_regular_polygon_path(shape: &RegularPolygonShape) -> skia_safe::Pat }) } -pub fn build_regular_polygon_vector_network(shape: &RegularPolygonShape) -> VectorNetwork { - build_simple_polygon_vector_network(&SimplePolygonShape { +/// Build a [`VectorGeometryShape`] from the regular polygon points, preserving the corner radius. +pub fn build_regular_polygon_vector_geometry(shape: &RegularPolygonShape) -> VectorGeometryShape { + build_simple_polygon_vector_geometry(&SimplePolygonShape { points: build_regular_polygon_points(shape), corner_radius: shape.corner_radius, }) diff --git a/crates/grida-canvas/src/shape/regular_star.rs b/crates/grida-canvas/src/shape/regular_star.rs index a51f280835..df1685646d 100644 --- a/crates/grida-canvas/src/shape/regular_star.rs +++ b/crates/grida-canvas/src/shape/regular_star.rs @@ -1,4 +1,3 @@ -use super::vn::VectorNetwork; use super::*; use crate::cg::*; use skia_safe; @@ -68,13 +67,13 @@ pub fn build_star_path(shape: &RegularStarShape) -> skia_safe::Path { }) } -#[deprecated(note = "use VectorGeometryShape instead")] -pub fn build_star_vector_network(shape: &RegularStarShape) -> VectorNetwork { +/// Build a [`VectorGeometryShape`] from the star polygon points, preserving the corner radius. +pub fn build_star_vector_geometry(shape: &RegularStarShape) -> VectorGeometryShape { let points = build_star_points(shape); if points.is_empty() { - return VectorNetwork::default(); + return VectorGeometryShape::new(); } - build_simple_polygon_vector_network(&SimplePolygonShape { + build_simple_polygon_vector_geometry(&SimplePolygonShape { points, corner_radius: shape.corner_radius, }) diff --git a/crates/grida-canvas/src/shape/rrect.rs b/crates/grida-canvas/src/shape/rrect.rs index 0c9c8b5de6..855c2a98b8 100644 --- a/crates/grida-canvas/src/shape/rrect.rs +++ b/crates/grida-canvas/src/shape/rrect.rs @@ -1,6 +1,5 @@ -use super::vn::{VectorNetwork, VectorNetworkSegment}; +use super::vn::VectorNetwork; use crate::cg::prelude::*; -use math2::KAPPA; pub struct RRectShape { /// width of the box @@ -41,140 +40,164 @@ pub fn build_rrect_path(shape: &RRectShape) -> skia_safe::Path { /// Build a [`VectorNetwork`] representing this rounded rectangle. /// -/// The network is constructed with segments in clockwise order starting from -/// the top edge. Each corner is approximated with a single cubic Bézier curve -/// using the KAPPA constant. -#[deprecated(note = "use VectorGeometryShape instead")] +/// Derives the vector network directly from Skia's rrect path, which uses +/// conic curves internally. The `VectorNetwork::from(&Path)` conversion +/// handles conic-to-cubic promotion, guaranteeing the resulting cubic Bézier +/// segments are pixel-identical to what Skia renders. pub fn build_rrect_vector_network(shape: &RRectShape) -> VectorNetwork { - let w = shape.width; - let h = shape.height; - let tl = shape.corner_radius.tl; - let tr = shape.corner_radius.tr; - let br = shape.corner_radius.br; - let bl = shape.corner_radius.bl; - - let mut vertices: Vec<(f32, f32)> = Vec::new(); - let mut segments: Vec = Vec::new(); - - // helper to push vertex and return index - let mut push = |p: (f32, f32)| { - vertices.push(p); - vertices.len() - 1 - }; - // helper to create line segment - let line = |a: usize, b: usize| VectorNetworkSegment::ab(a, b); - - // Starting point (top-left edge start) - let start = (tl.rx, 0.0); - let start_idx = push(start); - let mut prev = start_idx; - - // Top edge - let top_right_start = (w - tr.rx, 0.0); - let tr_start_idx = push(top_right_start); - segments.push(line(prev, tr_start_idx)); - prev = tr_start_idx; - - // Top-right corner - if !tr.is_zero() { - let end = (w, tr.ry); - let end_idx = push(end); - segments.push(VectorNetworkSegment { - a: prev, - b: end_idx, - ta: (KAPPA * tr.rx, 0.0), - tb: (0.0, -KAPPA * tr.ry), - }); - prev = end_idx; - } - - // Right edge - let br_start = (w, h - br.ry); - let br_start_idx = push(br_start); - segments.push(line(prev, br_start_idx)); - prev = br_start_idx; - - // Bottom-right corner - if !br.is_zero() { - let end = (w - br.rx, h); - let end_idx = push(end); - segments.push(VectorNetworkSegment { - a: prev, - b: end_idx, - ta: (0.0, KAPPA * br.ry), - tb: (-KAPPA * br.rx, 0.0), - }); - prev = end_idx; - } - - // Bottom edge - let bl_start = (bl.rx, h); - let bl_start_idx = push(bl_start); - segments.push(line(prev, bl_start_idx)); - prev = bl_start_idx; - - // Bottom-left corner - if !bl.is_zero() { - let end = (0.0, h - bl.ry); - let end_idx = push(end); - segments.push(VectorNetworkSegment { - a: prev, - b: end_idx, - ta: (-KAPPA * bl.rx, 0.0), - tb: (0.0, KAPPA * bl.ry), - }); - prev = end_idx; - } - - // Left edge - let tl_start = (0.0, tl.ry); - let tl_start_idx = if tl_start == start { - start_idx - } else { - push(tl_start) - }; - segments.push(line(prev, tl_start_idx)); - prev = tl_start_idx; - - // Top-left corner / close - if !tl.is_zero() { - segments.push(VectorNetworkSegment { - a: prev, - b: start_idx, - ta: (0.0, -KAPPA * tl.ry), - tb: (KAPPA * tl.rx, 0.0), - }); - } - - VectorNetwork { - vertices, - segments, - regions: vec![], - } + let path = build_rrect_path(shape); + VectorNetwork::from(&path) } #[cfg(test)] mod tests { use super::*; - use crate::vectornetwork::VectorNetworkSegment; #[test] - fn rectangle_vector_network_is_minimal() { + fn rectangle_vector_network_is_straight() { let shape = RRectShape { width: 100.0, height: 50.0, corner_radius: RectangularCornerRadius::zero(), }; - #[allow(deprecated)] let vn = build_rrect_vector_network(&shape); - assert_eq!(vn.vertices.len(), 4); - assert_eq!(vn.segments.len(), 4); + // All segments should be straight lines (zero tangents) + for seg in &vn.segments { + assert_eq!(seg.ta, (0.0, 0.0), "expected straight segment, got curved"); + assert_eq!(seg.tb, (0.0, 0.0), "expected straight segment, got curved"); + } + } + + #[test] + fn rrect_vector_network_has_curved_corners() { + let shape = RRectShape { + width: 200.0, + height: 200.0, + corner_radius: RectangularCornerRadius::circular(40.0), + }; + + let vn = build_rrect_vector_network(&shape); + + // Should have curved segments (conics are split into multiple cubics per corner) + let curved_count = vn + .segments + .iter() + .filter(|s| s.ta != (0.0, 0.0) || s.tb != (0.0, 0.0)) + .count(); + // 4 corners, each split into 2^pow2 cubic segments + assert!( + curved_count >= 4, + "expected at least 4 curved segments, got {curved_count}" + ); + // Should be a multiple of 4 (uniform radius = equal subdivision per corner) + assert_eq!( + curved_count % 4, + 0, + "curved segment count {curved_count} should be a multiple of 4" + ); + } - assert_eq!(vn.segments[0], VectorNetworkSegment::ab(0, 1)); - assert_eq!(vn.segments[1], VectorNetworkSegment::ab(1, 2)); - assert_eq!(vn.segments[2], VectorNetworkSegment::ab(2, 3)); - assert_eq!(vn.segments[3], VectorNetworkSegment::ab(3, 0)); + /// Render a shape to RGBA pixels via Skia. + fn render_path_to_rgba(path: &skia_safe::Path, w: i32, h: i32) -> Vec<[u8; 4]> { + use skia_safe::{surfaces, Color4f, ColorSpace, Paint}; + let mut paint = Paint::new(Color4f::new(1.0, 0.0, 0.0, 1.0), &ColorSpace::new_srgb()); + paint.set_anti_alias(true); + let mut surface = surfaces::raster_n32_premul((w, h)).expect("surface"); + surface + .canvas() + .clear(Color4f::new(0.0, 0.0, 0.0, 0.0)); + surface.canvas().draw_path(path, &paint); + let img = surface.image_snapshot(); + let info = img.image_info(); + let row_bytes = info.min_row_bytes(); + let mut raw = vec![0u8; row_bytes * h as usize]; + img.read_pixels( + &info, + &mut raw, + row_bytes, + skia_safe::IPoint::new(0, 0), + skia_safe::image::CachingHint::Allow, + ); + // Skia N32 premul is BGRA on little-endian; convert to RGBA for rendiff. + let pixel_count = (w * h) as usize; + let mut rgba = Vec::with_capacity(pixel_count); + for i in 0..pixel_count { + let off = i * 4; + rgba.push([raw[off + 2], raw[off + 1], raw[off], raw[off + 3]]); // BGRA → RGBA + } + rgba + } + + #[test] + fn rrect_vector_network_pixel_matches_original_path() { + use rendiff::Threshold; + + let cases: Vec<(&str, RRectShape)> = vec![ + ( + "uniform_radius", + RRectShape { + width: 200.0, + height: 200.0, + corner_radius: RectangularCornerRadius::circular(40.0), + }, + ), + ( + "non_uniform_radius", + RRectShape { + width: 200.0, + height: 150.0, + corner_radius: RectangularCornerRadius { + tl: Radius::circular(10.0), + tr: Radius::circular(30.0), + br: Radius::circular(50.0), + bl: Radius::circular(20.0), + }, + }, + ), + ( + "zero_radius", + RRectShape { + width: 150.0, + height: 100.0, + corner_radius: RectangularCornerRadius::zero(), + }, + ), + ]; + + for (name, shape) in &cases { + let w = shape.width as i32; + let h = shape.height as i32; + + // Render original rrect path + let original_path = build_rrect_path(shape); + let pixels_a = render_path_to_rgba(&original_path, w, h); + let img_a = imgref::Img::new(pixels_a, w as usize, h as usize); + + // Render vector-network round-tripped path + let vn = build_rrect_vector_network(shape); + let vn_paths = vn.to_paths(); + assert!(!vn_paths.is_empty(), "{name}: no paths from vector network"); + let pixels_b = render_path_to_rgba(&vn_paths[0], w, h); + let img_b = imgref::Img::new(pixels_b, w as usize, h as usize); + + // Compare with rendiff: tolerates 1px spatial displacement and + // anti-aliasing differences from conic-to-cubic conversion. + // + // rendiff::diff already accounts for 1px spatial shift (neighborhood + // comparison). The remaining per-pixel color differences come from + // Skia rasterizing conics vs cubics differently at sub-pixel level. + // We allow: + // - any number of diffs ≤ 10 (AA rounding noise) + // - up to 300 diffs ≤ 60 (worst-case edge pixel mismatch) + let diff = rendiff::diff(img_a.as_ref(), img_b.as_ref()); + let threshold = Threshold::new([(10, usize::MAX), (60, 300)]); + assert!( + threshold.allows(diff.histogram()), + "{name}: pixel mismatch exceeds threshold.\n histogram: {:?}", + diff.histogram(), + ); + } } } diff --git a/crates/grida-canvas/src/shape/vector.rs b/crates/grida-canvas/src/shape/vector.rs index 5cdd436359..3588110404 100644 --- a/crates/grida-canvas/src/shape/vector.rs +++ b/crates/grida-canvas/src/shape/vector.rs @@ -1,4 +1,5 @@ use super::*; +use crate::vectornetwork::VectorNetwork; /// /// Portable VectorGeometry Shape definition, that can be converted to VectorNetwork @@ -83,6 +84,16 @@ impl From for VectorGeometryShape { } } +impl From for VectorNetwork { + fn from(shape: VectorGeometryShape) -> Self { + VectorNetwork { + vertices: shape.vertices, + segments: shape.segments, + regions: vec![], + } + } +} + impl From for VectorGeometryShape { fn from(shape: RRectShape) -> Self { VectorGeometryShape::from_rrect( diff --git a/crates/grida-canvas/src/vectornetwork/vn.rs b/crates/grida-canvas/src/vectornetwork/vn.rs index b595b960cf..c9cd67f2c1 100644 --- a/crates/grida-canvas/src/vectornetwork/vn.rs +++ b/crates/grida-canvas/src/vectornetwork/vn.rs @@ -545,18 +545,50 @@ impl From<&skia_safe::Path> for VectorNetwork { let c = pts[1]; let p2 = pts[2]; let w = iter.conic_weight().unwrap_or(1.0); - let (c1, c2) = conic_to_cubic(p0, c, p2, w); - let idx = vertices.len(); - vertices.push((p2.x, p2.y)); - let seg_idx = segments.len(); - segments.push(VectorNetworkSegment { - a: prev_idx.unwrap(), - b: idx, - ta: (c1.x - p0.x, c1.y - p0.y), - tb: (c2.x - p2.x, c2.y - p2.y), - }); - current_loop.push(seg_idx); - prev_idx = Some(idx); + + // Split the conic into 2^pow2 quadratic segments for accuracy, + // then convert each quad to a cubic (lossless). + // pow2=2 (4 quads per conic) balances accuracy with vertex count. + let pow2 = 2usize; + let max_pts = 1 + 2 * (1 << pow2); // 9 points for pow2=2 + let mut quad_pts = vec![skia_safe::Point::default(); max_pts]; + if let Some(_count) = + skia_safe::Path::convert_conic_to_quads(p0, c, p2, w, &mut quad_pts, pow2) + { + // quad_pts layout: [q0_start, q0_ctrl, q0_end/q1_start, q1_ctrl, q1_end, ...] + let num_quads = 1 << pow2; + for qi in 0..num_quads { + let qp0 = quad_pts[qi * 2]; + let qp1 = quad_pts[qi * 2 + 1]; + let qp2 = quad_pts[qi * 2 + 2]; + let (cc1, cc2) = quad_to_cubic(qp0, qp1, qp2); + let idx = vertices.len(); + vertices.push((qp2.x, qp2.y)); + let seg_idx = segments.len(); + segments.push(VectorNetworkSegment { + a: prev_idx.unwrap(), + b: idx, + ta: (cc1.x - qp0.x, cc1.y - qp0.y), + tb: (cc2.x - qp2.x, cc2.y - qp2.y), + }); + current_loop.push(seg_idx); + prev_idx = Some(idx); + } + } else { + // Fallback: single cubic approximation + let (c1, c2) = conic_to_cubic(p0, c, p2, w); + let idx = vertices.len(); + vertices.push((p2.x, p2.y)); + let seg_idx = segments.len(); + segments.push(VectorNetworkSegment { + a: prev_idx.unwrap(), + b: idx, + ta: (c1.x - p0.x, c1.y - p0.y), + tb: (c2.x - p2.x, c2.y - p2.y), + }); + current_loop.push(seg_idx); + prev_idx = Some(idx); + } } Verb::Cubic => { let p0 = pts[0]; diff --git a/crates/grida-canvas/tests/shape_to_vector_network.rs b/crates/grida-canvas/tests/shape_to_vector_network.rs index 4e285f52e5..12bc2ae1b3 100644 --- a/crates/grida-canvas/tests/shape_to_vector_network.rs +++ b/crates/grida-canvas/tests/shape_to_vector_network.rs @@ -15,15 +15,23 @@ fn ellipse_vector_network_has_four_segments() { } #[test] -fn rrect_vector_network_has_eight_segments() { +fn rrect_vector_network_has_curved_corners() { let shape = RRectShape { width: 100.0, height: 80.0, corner_radius: RectangularCornerRadius::circular(10.0), }; let vn = build_rrect_vector_network(&shape); - assert_eq!(vn.vertices.len(), 8); - assert_eq!(vn.segments.len(), 8); + + // Each corner's conic is subdivided into multiple cubic segments. + // With 4 corners, curved count should be a positive multiple of 4. + let curved = vn + .segments + .iter() + .filter(|s| s.ta != (0.0, 0.0) || s.tb != (0.0, 0.0)) + .count(); + assert!(curved >= 4, "expected at least 4 curved segments, got {curved}"); + assert_eq!(curved % 4, 0, "expected multiple of 4 curved segments, got {curved}"); } #[test] From 46e1d79d017c9013338a269c57e4875a9fba75ff Mon Sep 17 00:00:00 2001 From: Universe Date: Mon, 2 Mar 2026 22:17:53 +0900 Subject: [PATCH 2/5] feat: add corner radius visual comparison example and enhance flattening logic - Introduced a new example `golden_corner_radius_backends.rs` to visually compare the differences between Skia's native `rrect` and the `corner_path` PathEffect for corner radius rendering. - Added a new PNG output for the visual comparison. - Enhanced the `JSONFlattenResult` structure to include corner radius information, improving the flattening process for shapes with corner radius. - Updated various methods to utilize the new `JSONFlattenResult`, ensuring accurate representation of vector networks with corner radius effects. This update aims to improve the understanding of corner radius rendering differences and enhance the shape flattening capabilities in the grida-canvas project. --- crates/grida-canvas-wasm/lib/index.ts | 11 + .../grida-canvas-wasm/lib/modules/canvas.ts | 9 +- .../grida-canvas-wasm/src/wasm_application.rs | 4 +- .../examples/golden_corner_radius_backends.rs | 100 ++++++ .../goldens/corner_radius_backends.png | Bin 0 -> 22334 bytes crates/grida-canvas/src/io/io_grida.rs | 21 ++ crates/grida-canvas/src/shape/corner.rs | 65 ++++ crates/grida-canvas/src/shape/rrect.rs | 90 ++++++ crates/grida-canvas/src/window/application.rs | 44 ++- .../src/window/application_emscripten.rs | 4 +- crates/grida-canvas/tests/flatten_rendiff.rs | 303 ++++++++++++++++++ editor/grida-canvas/backends/wasm.ts | 2 +- editor/grida-canvas/editor.i.ts | 11 +- .../grida-canvas/reducers/methods/flatten.ts | 68 ++-- packages/grida-canvas-vn/vn.ts | 14 + 15 files changed, 695 insertions(+), 51 deletions(-) create mode 100644 crates/grida-canvas/examples/golden_corner_radius_backends.rs create mode 100644 crates/grida-canvas/goldens/corner_radius_backends.png create mode 100644 crates/grida-canvas/tests/flatten_rendiff.rs diff --git a/crates/grida-canvas-wasm/lib/index.ts b/crates/grida-canvas-wasm/lib/index.ts index 8c629378f0..c408c6dbf5 100644 --- a/crates/grida-canvas-wasm/lib/index.ts +++ b/crates/grida-canvas-wasm/lib/index.ts @@ -115,6 +115,17 @@ export namespace types { vertices: VectorNetworkVertex[]; segments: VectorNetworkSegment[]; } + + /** + * Result of flattening a shape node to a vector network. + * + * When `corner_radius` is present, the vector network contains straight + * segments and corner radius should be applied as a rendering effect. + * When absent, corner geometry is baked into the vector network as curves. + */ + export interface FlattenResult extends VectorNetwork { + corner_radius?: number; + } } // ==================================================================================================== diff --git a/crates/grida-canvas-wasm/lib/modules/canvas.ts b/crates/grida-canvas-wasm/lib/modules/canvas.ts index 303bdacbd3..f547645dae 100644 --- a/crates/grida-canvas-wasm/lib/modules/canvas.ts +++ b/crates/grida-canvas-wasm/lib/modules/canvas.ts @@ -344,8 +344,15 @@ export class Scene { /** * Convert a node into a vector network representation. * Supports primitive shapes and text nodes. + * + * Returns a flatten result containing the vector network and an optional + * corner radius. When `corner_radius` is present, it means the vector + * network has straight segments and corner radius should be applied as + * a rendering effect. When absent, curves are baked into the geometry. */ - toVectorNetwork(id: string): types.VectorNetwork | null { + toVectorNetwork( + id: string + ): types.FlattenResult | null { this._assertAlive(); const [ptr, len] = this._alloc_string(id); const outptr = this.module._to_vector_network(this.appptr, ptr, len - 1); diff --git a/crates/grida-canvas-wasm/src/wasm_application.rs b/crates/grida-canvas-wasm/src/wasm_application.rs index 89d782b966..060f3a6020 100644 --- a/crates/grida-canvas-wasm/src/wasm_application.rs +++ b/crates/grida-canvas-wasm/src/wasm_application.rs @@ -552,8 +552,8 @@ pub unsafe extern "C" fn to_vector_network( return std::ptr::null(); }; - if let Some(vn) = app.to_vector_network(&id) { - if let Ok(json) = serde_json::to_string(&vn) { + if let Some(result) = app.to_vector_network(&id) { + if let Ok(json) = serde_json::to_string(&result) { return alloc_len_prefixed(json.as_bytes()); } } diff --git a/crates/grida-canvas/examples/golden_corner_radius_backends.rs b/crates/grida-canvas/examples/golden_corner_radius_backends.rs new file mode 100644 index 0000000000..a6c8ad4a9f --- /dev/null +++ b/crates/grida-canvas/examples/golden_corner_radius_backends.rs @@ -0,0 +1,100 @@ +//! # Corner Radius Backends: Visual Comparison +//! +//! This example demonstrates that Skia's native rrect and the `corner_path` +//! PathEffect produce **different curves** for the same corner radius value. +//! +//! Output: `goldens/corner_radius_backends.png` +//! +//! The image shows three columns at two different radii: +//! - **Red** — Native `SkRRect` (conic arcs, true circular corners) +//! - **Blue** — `PathEffect::corner_path` on a sharp rect path +//! - **Overlay** — Both drawn with 50% opacity to visualize the difference +//! +//! See `shape/corner.rs` for full documentation of this limitation. + +use cg::cg::types::RectangularCornerRadius; +use cg::shape::*; +use skia_safe::{surfaces, Color, Color4f, ColorSpace, Paint}; + +fn main() { + let radii = [40.0_f32, 80.0_f32]; + let shape_w = 300.0_f32; + let shape_h = 300.0_f32; + let pad = 30.0_f32; + let col_w = shape_w + pad; + let row_h = shape_h + pad; + + let canvas_w = (col_w * 3.0 + pad) as i32; + let canvas_h = (row_h * radii.len() as f32 + pad) as i32; + + let mut surface = surfaces::raster_n32_premul((canvas_w, canvas_h)).expect("surface"); + let canvas = surface.canvas(); + canvas.clear(Color::WHITE); + + // Paints + let mut paint_rrect = Paint::new( + Color4f::new(0.84, 0.36, 0.36, 1.0), + &ColorSpace::new_srgb(), + ); + paint_rrect.set_anti_alias(true); + + let mut paint_corner = Paint::new( + Color4f::new(0.20, 0.47, 0.76, 1.0), + &ColorSpace::new_srgb(), + ); + paint_corner.set_anti_alias(true); + + let mut paint_rrect_overlay = paint_rrect.clone(); + paint_rrect_overlay.set_alpha_f(0.5); + let mut paint_corner_overlay = paint_corner.clone(); + paint_corner_overlay.set_alpha_f(0.5); + + for (row, &radius) in radii.iter().enumerate() { + let y = pad + row as f32 * row_h; + + // Build paths + let rect_shape = RectShape { + width: shape_w, + height: shape_h, + }; + let rect_path: skia_safe::Path = (&rect_shape).into(); + let corner_effect_path = build_corner_radius_path(&rect_path, radius); + + let rrect_shape = RRectShape { + width: shape_w, + height: shape_h, + corner_radius: RectangularCornerRadius::circular(radius), + }; + let rrect_path = build_rrect_path(&rrect_shape); + + // Col 1: Native rrect (red) + canvas.save(); + canvas.translate((pad, y)); + canvas.draw_path(&rrect_path, &paint_rrect); + canvas.restore(); + + // Col 2: corner_path effect (blue) + canvas.save(); + canvas.translate((pad + col_w, y)); + canvas.draw_path(&corner_effect_path, &paint_corner); + canvas.restore(); + + // Col 3: Overlay + canvas.save(); + canvas.translate((pad + col_w * 2.0, y)); + canvas.draw_path(&rrect_path, &paint_rrect_overlay); + canvas.draw_path(&corner_effect_path, &paint_corner_overlay); + canvas.restore(); + } + + let image = surface.image_snapshot(); + let data = image + .encode(None, skia_safe::EncodedImageFormat::PNG, None) + .unwrap(); + let out_path = concat!( + env!("CARGO_MANIFEST_DIR"), + "/goldens/corner_radius_backends.png" + ); + std::fs::write(out_path, data.as_bytes()).unwrap(); + println!("Written to {out_path}"); +} diff --git a/crates/grida-canvas/goldens/corner_radius_backends.png b/crates/grida-canvas/goldens/corner_radius_backends.png new file mode 100644 index 0000000000000000000000000000000000000000..d225d461ccea836b7e4597a7898298d4666b293d GIT binary patch literal 22334 zcmeFZXH-*J+Xf6W$_y3;MS5{S1*8qqYZ#>o2+})o2u(UtrA5X;dO&F^9R#FH??rkq zLg)~Rv`|A!2r1u=&-;G=zklyq-@{t0oRf3TKD*rYy04wcXFBTF>DcI~sHm<#(NNK+ zqM{*CQC+J1^$PgL@n56?`1r-^(G$a8!C%m?wh>fRcc`AI{AK8$w!8SMdI@XAjT`mK zY$~5C6Vgg{>2+@I_I&;Czc=TywP{`?{Qb!E3V%U$+KuWkw?v(S&K2*GYhjEx?|6Mr z%zvTrNaNS8ry3f+O8qwCHdtY20Un=vd2i7OyX4R?N*dyxe$U)r$)SZOWuSsvMlkPQ zuBV~q$w8-qBWl#73aaf6SS8vo}n zeS!GAW|VVwt~kT3jmy1yXf7x?Zf=d(IC@!aVw}^^%u%|&zBRQ|2o5v?>kbl^j-Pmp)(3nzo+(OT7z)TX%6})XFx#aYt!V!t9n6)IwSAT_NAWhSt0a=cS zl;4jS-zksVs*>LhN_5`yUminm|3f}}r(aT5qu+Z;q_Y1Vss0sKWuY>V$8A=TwY>4= z!=CWyLYSR?%WULqQovC86wEh|%WLrTOVWe!2T3_rBIvsJNZmow~Q<&5g&&gB-|#sNgMAs@NGay7)KG2d>tA~TblXW?vwc?CWCT# zuu68koQ^%GSxGmX-0==~LaZ8hTz8(K9YH;Z{}Hl<7+fuA^YhzXl1r1*$uBXqz_e#4 z`S1G6&ZS384QNViZsyLrp{WS_OG`cz`@{AK~9o4hD~^RD1(Q&jl9zNN_~3$dUyNTo*oBxTttLmf%@uMaehDm z3NAuNo?DCSjie9x(@9t1og7{KOrOtm_Zjy^#c3Xi-LQ@wV-hFS!ySZiRPgtg^x?R( z<~A?R3L&C?36?-U};rBKaQCAibwT2;#wJ3G5oQksXLy*ni>$M$Ao zVjO%hFr+-a-d$Xl76aa&GX|rv(`6>%hqQ-+fAH#&Hlz*IsUO-?q+rh-9(c{lQx(mh zV%RVh1tl$$aQIt;U^Wytn#yJw+b{{`F_@JlXh(oZtT7*H_1pOevm#X$l>+OyjRni< z!S%`U*D(S*+Fk7@-Y3^fM-LC?9&*4hYPVT-57LQ5MGIWYK?5J64cnrle%abI`}Y*` z?r2ZGbgP)pd#%;N1}DNGz0%F_jbR;XR0d_TAjBU}J&|YQlX@aiKmnAn%RxdWQ`q%7 zW8)l8LOu4$a@cJ;v3i*LiTfNQ14C-hl~r1|RK!zQi)SVLfFf8Fp)##M9+`adnyX^3 z)ID~ao3vudjmFmW>h_4jJ>Z7uGLFmE85P+!gdW}2ht`368{lnUKIWMdy5Ag+JNoeO z2c}>4r*R^cJOozrBD|RwT6I+>S+MMhEoc{=}!Z^cSEPoL}K!fK`F@8`lGc=3nU?^-I z*TK7EBI!53_k~-LE!|1dM<`4Ec5jc3$L0wCNqMHv*gO2}c)CDuIqKXW&7zDT;?v`LNgtQee}nQ%u4>UHgUOqB zQQIplNDN-KdtvfGPu`oqF;-1QC1|@{f2iCZ%Qia1Ogfu0=Qtlm#cU9Q(EQ3bBsMoz z`{b7x_PF3Hg45<0QS$P;FVgZr4rPtqeOIAi)e@)73v-)oPwn}XuGoryhUm3yNoA~{StA1 z%ePYY&$bUb1?=Q~-nfibdA4O6xeCiT@=h*o&ctKdFz+S?KS=ZM>vQ<Oj zgI+4B__h#l0n(sVxIwRsdtjy|qVwvGNut!|2Cy0hh+lp@YqCTDZBkL;_*CAr#Ft{A zF8A2}D!IQ6Uu;U4EYRQ<&6kk0*A-U5wazH6K;_&uITAh_d3 z=FGtiLFIfdJF3~19ZEAZuWiYrSjXK85SLu27VX6mtvgnVVl*cy^uk>WMT%dP<*Ec@ zaf9JZ`n~>t>5drZ>btAg&Bg$s$33F6yqP|N|087BKGC_<|D}|C72%^Gflui$)G;Lh zi)YTl0>zNQgwlUTU~))@TH=MgRJH*^bAGl&&Pp+P_C@1^MIow_GPhzMJbKdrrpIJk zbZA1)5plHCLK)_>R|iX9I7jxEa3G4nJbOzzqLL~DF4zXOvKy;jC3yP5qEOwzb@&HE zyh@W{lujv=m*DBpLVjXl2ZY=UPm{a!HFOwQ&O+YiEP4ljwd*tfN~D^#Lf*8M>;lLm zi3}w%_B&xfl2uf8A)jLB|9WVEE55+0pN^|jR{!fjYp~v88^k9@e5h=4tt@;4d@Hjj zdN$mvS@Th@=S7mad`4QaN`ZN-j--5`LuhOPa3X?Tc>{rP3*umd6x8M@N3c(Q{hG>PY8^9jx)kTf;(>za(-KT?Z zw_ey#EQT0W4$x%1SBKy*V{MRDCm%uO@pe=xKK*5|cXn;7-_)*BJTCF87>3BR3e;yIijGB&F))kXE9jx=B)6Cf2s|aPUc!w+@$Nv zFfL^DiY(vMvc^>%>0du|F=I`w^q-b&7cgVVwKriK7s(r?J`CE^7qB;xI=lw=dL=uR z;m>3D%j+uhz|}~{4DCQu>w<|`BCE{e?d7mt`S-qW+va0GSQM!^xC+0x@w#feq_lhY z(OjwSldEu9UU5e%2ZN<1>Fr~B(J7m}In7Vh%a+Ll!!o`P7hfWioWzT?1p71S4{Zjt z1oh0duu3V_hYoiALhZAkxpH?=v;lt&R5*d4VecjW4Gp!mMw6vZV;sb6#l5^#b^V>X zz9QGMsu9<#yK}!Ccv}nQEgoO?P(oyC`^kmWpxc%1%!5@aN&N0AuW5{97Z+#PJMpW# z)STrjzkM2%_i3G=e3r*iT$HC--^AEg?It}nuzf%N{cX}z6w&zSCH;NuB^jtdZ&85c zo{tIDChxjwQput8=B9xn+j28_R#UP#>-Dadtg!$=S#%~o40R1Mc6I2GCe31?qR7~5 z>bLk{@U(Xr{FN*+mwJTqtqVP5j7A?}vGi%6eFAa0t@F9)jopn4)#p<5Zi%>!y;=gzg4PwV!Ls8sCoIDEsM- z?ghRiPZ}1f)1=iU!jN4W@Ja`ov~qB`oaK45uQd^7)Y#GX!r=eC;VZM*oeSU~I_du7 zPwa8jBj2t;+8geruW)l|oVmO{PI_7Lu#?{725?!P;sj-S4O!#s*MZxkxKN76dqZ(n zz!P4lr@#L{-2uL2Grszeo;g90eK`o+_f}||Hb8lxV&FZv7oZF}XS=1h?Ell{*jRc# z%5!X)8h*oGl^u}!KtD?VGHt}(mNh<@UArBU#r&D0xJUXaWw@^d7;S>I8gJ+J(~;XZ zhQ(eEOBQm`ALjJ9H3~%WZnyUBFSu;bQHF|~%&*welF^}Q{;)b@s;%>xoiE`wDIy|r zy7~V48uf_4DT~iU8HS(ny&9EF!K1%}OEm2QZ2rXa4IRTpOv_X4>-hu z1}F9MH8ZnN??EmtqtM-eVZravs^;K<%8)y$QMYb+o^ND-X8q1gifJ~aQLr%X$+z$; z$W)~9|HJIV3Q9?mQ8kRaFN+izS?}WXhMBbDToy^XCX{+v#?GS`!LraG?h_LcQSa94 zs2zJ&fS~qxTR2XdsgfkR@>ulJ!fam((Ghzz@5lp4O6;N1O@rL+5!px~M$)6~-{r~U z5KT^+0FJO!gmoUA7$+^n0oTh2o1<=)xkl`?H6FzJNfKFTVEawfk+J z00yWM*3N^}24S(cM*EOo3pQbA@J5e=J-T%qAQ@B?s4fZy z^PDxr)2NE;;dpuSQD?Q23{*DwJ$GHsm22=#qX`h;rmZ}!qnuYe`^BiLbS zGk}dtro`qU-h(_Kp!2#|NG~TPt(n1b`gLvjOy?my-vZ=hEw+5&liZc|7w$ppQ!`br zcYR_e^3`Zp2e!wz*jYVabH^Kc+VFtop?m|@+Ls(+TX@)8Xhxb$<#-)i_^j_lGdJ_R zb&=AKh?cI$d~EBQIhSPCc1V`WRd^{g<4My&vkd?$MaQTa<01w5mTj9QDb=1M7&(9 z!9yc36}9ACzyBmgzEvjO26tc~;H zHeF7dnRb9;GN9gNGtX`|*$jGU>)ueyHjT*^EQ{D0TqqWaR}T&r^X|T_w{;M=XYjbf z>(~RWQegLzk)r`!R8Me#OZi-TPBU}v1!3+qu}YHb0ZL1U5p-{niejzDvd#EM1&86J z-5c)v#CSabSKhMM0ulNH|27=9bp-I9OH!}D4T{FKuB>eB2zIf%&7{eVc-dASs;g+X zkWMR3huw8JY5FQk-9x;zTlakmVa<1?p<)bexcp*D7MTSNnm}R(tY+t%$Uy+>U9FjR zi;9R?{b74;<^i3h3XMfwhP42G&RM$q#8&DI%;9VYH-i|F7jkp0Jiv$oPsA?zT4MXF@Jw7SrD7fO+;6TP+*YHas%>c)} z<^qNDHTm|ME;RB5TBwLy;jRV;R~&D`m97W_usDkXD^H6O9x(>^yKj;)Q_gGXz1*J| zgV6*p=75y41GJ-`)Dvp~JD%`+PQSmv8kX%c+(_M03WVc|-#$>{VHgdjrF>|^DQBo{ zk4as9EeeXy1G4*s^KxG(r~}lmLJ86Qh%;X^E-s-SI3bc9=6L70Q)aC5?G^m0H2f%^ zg-a+OarFL_`6`B3_f#ET@p~9BxaIXcblpoA2UL{>&xCrGCt#Z30t&uUyCrIW9Fv#f zZ@@9vAYK+c-DE>R$m^?92h8C1>UwJq0!-X)cm{Oa!N4*%faSl_8?r9k((=jict*K- z<*hISgB}Y<45do3s&Y2^2UTUUj1m{`v^9IMF6sdm2td~cW_RgN6HqHyocv?NqK@5* zo9HMMf;K2jpi;Eop(j0eAy;rm^V=Tp>MO!xK!xJZJT*`W7QfHrxmR19~LK_uBggGR5XuHn;Xm3Tkb(UB*N zTM6qjXG>VM>UjWuv6`^3M5IHoUW$HfWUW(Nq$XkYf*S#le1O2kHMuzPFP(}@_twbw z=&LtmF=@r(c4?0F%4z_hS5tX2cCD8;;J}EbeiDzjIXoKF&Fq0FEpU^Mi}PVSD!vY9 zy4(Fg;PirbD?Xg3qavq{UV>)TPIaGl??XxJEK5~iDF33%>#1BIBtQ)Ykd1$kE`AkpumvBqCJebdoz!p77jXOQ^-KiVIIq8 zFF3xZ=AAn12x>}AhG57VB{H(CZ|3XN|9*Z4_#tNz_Gl9;+1XoKxJ*%I@M`q8H)0px z=+*Z6`M`igDprci5uA`?aj~N)lh26v0^(XV{;0+9wb8Q?Rjp&%45=AtL>rb=q|`XolWb6onZam!H!f}&7LR{OjRxo*+OhrKl=Q=!Z{&SdP=_9j7d&n= zvRrk0A7lEtmNpWLJGd)aGki{Wpm7Zle6HijXu;1K&cs9oQ9Z<#_^g%7+}fvb7~ox< z*r6^85bpG};Ji~!Qeli4LYNy|J81LtbKyK#WS)u6wsh_W08a%xp97$`bH$(!nQ?Bp z@8sA#-rc@J3-bt&i%LishYEE8x7|#Q!F!;cEo81V#%1h8rr6KavlR}gS(jmz5SZJ12w*e=)Esf7J7v>xj|^`X)TgE zz8%b8%=Oza?=O&^@F+23R9}nq)Lvsm@U8Bp6PN zQw!_qfca$c>6dAA0o+x>e7r=`rgSN4Yv$4A6m2Lp=Gtj*`{DCzH_m#;4xe3%z1B0< z=W#9eM)%l^M$C=tU0`%GAVz#cJpb4YNx5$Jvr>K_)#Gp-03S2Y|G$;YEq;?;`Cl%; z|FNPw-hlSGRo!^RM#m$Gjm=z8o+?e?%e5*jAsdvcZJM>YmzU)uwCEq`=%{)Aj5Wul zrF`+&?uv>nRI}`r`~r#=0XM77d7FpF#;t~-YVh=fRblUfrXr{@d)hQ`4JO%7eoA+& zl?Mf|+}VAV<83H==_zU&I3vvVUyq5wVq?&VZ=_Zh{xWh%)(rC-U9ucdW>A2$>CMlc zQIch(L?xAl+4U|H&s;J&v^g`cf3b8{&09ifmU1Qq2o50C5{--W3MX?KjH7*XSxb%O z=Z1}|=hGdfEykVdawpI##Yi2_Os+{3G^Ul*x+Th#D>KI3Z3AVb#pkxQv2=e6Wnp1O zR8*{dSa`?)d)&>!j*hEXv7rcEkm;#*_Sl|pQ{iKmyP*D16sN?7d_$WH$^*j<4UR*j zf*4y(a{g1XKNVX@49_plSXxMUO8m}$?b>IA+6X9mueMjbRPb%S88>RYIz}+(fS5%C zWkWk2zIV;!h#8co?@gNE_1v?Ac`mNQJUd4)A2=}Y2kXkGTzYK^S+&;Hgp$}R^j*81 z@)+{gUwRiIwT_q^hFp39b))73x{xs!p-i%BC`Fn6~u2{tjh5Nl%U{2ML+8Fwt zWX!i2IkDe6X}Tvpy|h-^X5`XM1CRQ@C=fghxk6;7xB`V5hwagZhwmv7?vKVDo8666 z7$Moh23J(fgWsiFB}mLK;-*|AxiU*jQZ8=okcAQ%1CQM2yPjJ%!Gy{dD@Y8>jhryg z)3b3FekOf&-p6z4ZfPY7R=ZlmrU7^?GC&?wB6Uj7h6YBRBs&BZTD}0gGCuBLoPL8| zosmvV&d`!f^{3SD7Wc2%4C0=*GZK>8XI}g=}U2>@N0zQX)cYczipJ zjp>?s3aAsq(!Jn+p01tMX;>#{Epi?AJy#2p_eRT;V5{hJw~sQz-5@N!>0bZ0R?wzo zs*Qg;?PTm1X>{jRB>!}VnLVm-8c05+UgBHBHeUNnCdUJ&OaXFk?zpss zH$D!K6e=9%HFlSz*qWs1RpH|@=X=j^qVc{B9H3Ggi!2Woeh{Z{bG!ncc>Qy^C?&_H zcX3Yn#ok^$ z8t$ZY(6YkkZoZmpk{pzdJUCWp3(DC8 zoQdnf$as{zm%DM&%ZF)iO^y!&nH5P-`opXE8K>w| zGSXsJaX7C5xC$_p-|9U#{V9_0wj^GTFN{1tW@#GHtsC+%nT#*r>kan;%Fva6KwO%^ zKZY>UOiUE6d4%o-zr3e}iM@qMxnLUl(W(09B#N05Jp1qX?M0YCC6nZCpx&_ip43+$|Q%jG(>xUoQ&n56U73PTDpM2rZ3Q8Yc zZTeo$0gb11#A?agKF)k=;$43iC3Bb9-Hv1c)olH zoLlgSHQ9jT^xvkhQB;_PwOS6%7)DkoQ6%{b1+CuF3t0}G)XUn81;ibfV9*EPyY=>t?-HMh4S8JOd*q?E z@6=RI!`I*UUdpN}^d*5+2*5xFr^Z_!bv*_Cy|_F>AMjwjoP|YtcDYG^mxSy&7v?JO zYqy@&c+SR={ZHH%KgrQ;J}azSdjk)aP&%0w*K?KmgRRoW`zs6N6p%u6gGS3(*pD8i z>gOUOgTqbMzCF%!tQ}ognsk-Q6_c)0$^}*H?*4w3g;rur9*Kd0rn|L%Z=jz-in?~@ zz7P!JCo>Rmni7T_C`*t#@1ZVXDHQhY+lP=H3m7FmQ5nDLoJ=t)xM@W10m?@vS#ab* zXbA;4A|JZ%Mb@?KA8q+TPwyf3yAIzzwi0xHdHeXhh3(X@9dtOW~PvP z+LMJD!o+*O0fcG66KT6p9msK5uuMahGUNu{eg(uZD|+GPW!iC_8n)B5-lrVj z?im6~SvIG<_2JtuPeEQ;=QhhU4}z~(wTXj8$E69q#8!w$XN^7nJToiCf?NcUA8BFfQ9Qy7ih8=H|<#=i#BkiENlKbtYJa zcQRIW5c`LPwe3eTP)+}}rxwy(F66f&gwmuWnX?S6%6fJ7*8sUwFx(_R#Pe!L`b`Ya1If^-faRpcb+;l0Sz zk+Y|Fq@`R|%DH5ISBG!<2{rt4Z3k6(&zDFTZR$AS5df5n=mWS6my9jPzs-$n=t5j+ zW~)F?_=SP`_7e)_;-cL$&9p4@bX4BiSq~B*(O5clZ}du9W=Fg7wY|C9!MwZ<#AAw& zq+gKYd`xq$&<|g`P150G+HV%$AfM>+O3lFKPCh^SBOi_nhs~od0vUqOIU)>X8mpPe zgf_@c-4P>75>sj7!X1ku($;m^89Xk`JxN5?7zdrDdU+nX&>s6Vjayn;LOTwEZ&sE+ zGlj0U`Rtgb;M`fcW26^b6?@(u*QI+u1|`n{O%5W+L2KU7f;O#l-T|JQAZZp74R~Oa zdI3wMkNSiJtRkbJk+}X>JrJwJ_z@EIWlA{Z8DA$@CCGlJ7 zMfCY&&UiI-nB#OA|4C*8`i09E7D^f?rueZun8==gI1T70ooyI)3eyp+`TS&?oz^bN zg#6&G-+>Nip2Onl*dxM499IP1%-SY2h@EXK8ihkyvr@brn*Zb34@*f(;%mMq4t*zo z8Za5h5$SfkJB^{9rKIiIi%q%iTSG>=#O_ByLGCGL;4c zwg4;CmgDaEIu!BFx$FsN-X>w(1kvqIisJ($lACBj6~cG=R-Ta6KwkhSKB4Cp=uWvI zlzuuohjfxaQ1~;!{a)0}rWGumO@5g^P&hRE_wp7uF97;*3+B9p;s)szepg4G>x367 zBN*Sl{R#PKH{+3D-eTxc;~<6Vz_Izz=)wWb|us?K~Ph{mpa`ihIOyu1kJ08=kg3wc~k`eh`!3hf0^z z)CKgVXv}=3@mZ(?;jEzTHelz(%cb(*W5Thkmg z1tFnfd|saQo^Dsk-!sXtILJhl-^&L-j0$e?En!xeEroFIwp#=67u+uLykqa zF7o+1nu>$3&a#`vXv}%=u>&Wcg_hR1Ovu8;-5*AE>;MYMt?}M4&H#wQemFDCcYSyI z zCU3gOEm|CVDI>K&=-88v9Z@Uw+-N2A?CzRrQN`;LE$Vuf&-NS$LH=2yOGoJ`y^~uX z`7W^kEDRrt2BQrIlwAJQ$~@N=0>_0g+W~@;V#qgSV0*M_VeM*W>p}L19Sm!UyE+KM zM}xdbC3bBM^7uS}R*#%!#vvO>xw4X-+Y%YJ++)gd&+DX^8+rWh^fIoC8{4j_0(35)Y|s|o1yX{|RIr~H@c0Yx!`euZy@5{s=;&?lMoc#`+94)kxVzgih2te% z^H<+O?;go?pl*t^$pNdr2^m6!B;o~ykE_K=vqfFSeXd~$$S^)J(dY^6sM!FBW#ZDm zbQK(ojv~D&NBu`$4j6f0xHdNv>@EcW`t5#9X-;&Wnu0IS#k_i8*&*PJ+H7D$Mt>`6 zKYvjN+gLn6OquN)4!;Sgx^*y&39-17jv^0s>bakh{_ri;kv>y8FeJGZud9SC6M(Og z@f8AY&MTxD+n?lU7nIyqKnKTe3)amQpU<0Iu~gVYB0s#sHsz*vPNYBpA5K>2;SD@*3ZcdNsFCe7GmoOG34={O=dJhN%CR#rZ+ zCw-1e^hv=jz*62MI08Pk;m#g2q3!eJt*|z4RIuJ`ohX3SX&+pisREK3C=tvmogvrs z`nRA$%B=um%2*gA_l@gIn2#o2fSd|w#f$rQxaZc7yvj~os^u!+_frGU#i6))XJ^k< z8g32XdfwgQ#wmM$YH4C@o!{%>J4jWGgWp>2z*V(WjqhdO+G|>L<4_?Z6kKZ`u&EhUH zhW5FToARxeao^{}E&j5&dUbqng}z1ki~`__h-8pZ#m=SLOKFMQ9S2!T%QoBVGz29( zUv7=8l%9+?y%`@D{ho1qR49jsN3zw~P0mSLOOA9MiH*!xqJb~V*oKX3ds2s(NO;Uz z1wPjOGlKfZ3|hLCVVG}VdKQ*z1cMcM}jr|n9yjmnx{ zU4G=8qFKOKn7XF}w8#PwF@*`hzr>VRw09%7yS^7d(&f6fR=+CU$%}(aUKE@{0-v~g zz1WrwccQlRSlstIJ34@TDxFt;XogGW)9o2h#DY$^Q1Kl!3eF|D1V;w{(W^5hjzzM} zm{ML10dt?L1mW{U)*UCic?i*a^7j%_RgtkPLsRwHB{k(cWt|Z zpXQ+nV6Qg{$|2FO2&q)eY5;LqkAXV^!2_nXx%tvI5Q>))4}Ix;R8&AJvBozIt;}p` zW?I(Ys+})@NN@oN$ylC!GaT?y0rA?DPz3?DZRRx-gt)EU#-Ze2&zKb8drZx)-Y|ur zrFS^^anXRpQO{ULC{Lu9s5Q_Pjg~YR>RJLFqcxnzQq6R4yDqHyhJ+gp%3y%JQJDi61+lc>Hv( z#b}Qb?Q^ta{>6Feie@bBl&~psvR4AQdvW*@zMA2&$&AX`=SRx`KX4g-M zQsQCo^{RM zo0?st=_iXneO0znBKnHQfWa|xl0nBpNOH;n+cZll?=CkkI;Ln=SW=4jIly#Ls^rEY zfJqB(NIA`VKlU+wQ;sWEj@X+i_KuwuHC(aPw6mSlUC-8$^^ zJ)&~5-QO|hWpe471e~3Te>b$2&3lC)w!@h{`kMs?Zv0q z_H0LW&2c-uh`b<$cG*0x+{&-gOv~MXiBoi1%NlZL0&FBO++qKE=vRbv1dw`wLVL7R zd6^pD%HoKb43X{Ut(xoR-WD&)n=i?vfPv+`Z1j9+wxX-(b;U!8?YB`ju}=Dve?Sjk zG^Fj$Qf(GDe{#Dd09d~K|KS-WIc+DysVV#=qtfQ&pLZl5I<A!G8GInPL z${YVf)t&n^ul;)0qS&qd9uZhX!?-Il?trtTCb*bhO0_AtZi+0L$Nypr9jJJ)ogGYN z1_rE;3$+G3r8<}3OO>KODZX`pY(xu&h<*x~G!(j2Q{mxHGVMRE@9OMouS z&DW$9b7{8jkCYS2Mo8wk|1)e}GCUB=mb+=T^cx{yX;X2iIb62IE2Cmj2FG|aT=}NW z`?vQlzX!Wbvm}(C@oQMAUiQu23r89km--4C70o#rCFv6N^)E4A z6vlI6d^?5XeDCg0j`MH7Q8>>3z4YJN`2VYHJgaQaG%7A^WqUrMe^z9kaqq(I^|0n_ z@lll0Z;a3Z>m;E=lTX8j(Cc4c2m~7CI^AM=76cA5b`q2^dAmm2m*Azz=wfOqVY~98 zX@$N^-6@qOzfpETybp!k!i93hSDGM8DVrAT$}97@w=P?})PgTL<>8%PKh>Hob^#>N zzXq(0iZ}XO*`HVGpFMEEQCq7HSlfYJ440pn;4V{)@2*kp2~Bg9!upt!!+)AwcN3=$ zP_~}`ClocNl*KI5Nq>lbUv|hoM|<)bZLH77Fh2%X!0`9w1FwZgOGp+DH0CWx0L{{Xqr$%}j6zqzVBV_D{m&?hK2IMR;aid}M+tJXXaopD z>k{^xncMBbgbjn>&rg#3nWb4x<5cm@CjrWn4* zSArtUsj$B=R7GWRSt+YsAN!?nrS&t4{wph3fu^!RKqgRGSNEQO!Kdn~mu?+k4{tWh04&{j1S!{<4ZtHN#_X z(fh}mOnW*Lpm!gR6wGN#zu0c$ZNIl?TBiS9PesMFNcmj=qX**)ReW~8QL#JiFS46; zYy>TRc|ueUeaifNN~5Zr?NtZ65ta3mC6^xM4y$MH-s(ke(yU3V$o!SACma4#>v3bcxh>M^$KGo5zf`ql&5H=3(FFS4=$u~wmHFGeo0ioj*C^$LhP=r0D9UqvV?3im4)PW7YofV_&S#O=$e(wNF_(|44ju zWH#7vYB*9_M19ww&~nCA;`>dUXy3)fRX;bT8S^V{4fiU+4p`P5?Hi}vW&Nuz>6d3D zXQLv&si7Z=IAV=*=gZW6$KOaP(;>Z%RT}pKs`203UJGe2$Nl4$cexh9gU#~WW!15| z)P7lY_eoW*v%G5Y8B!*ll8brB5pi$rSJLh0p1sByV^UW4z#_J1CQ3|6wVkV#l=IZZ?HE1!9#Dv;#1U@ia1{~$a zowBR$s#IlfHLF-3`z!~j8LT%PT@i0s?`Bmv4g0a*WRODb@&~UU3h+4a0!5I)&`TK~FV|-9U~^m-y&UX8 zii2Q0n4x}VUGwf;#DIBo>sT~hmPaULL@~&r#vJ|dwQ$yVm$MRnyH+CbCx%G;gu*Pnf# z*4hNrvux^1f8T~SWr*_dG&u$ew(%m`M3fO6bgd? zQ-4p&zn9b5-8QiA!i_Di)%1Q^v=J)oSUMTpmLMF=kjVF(4ls+02>-nsUdt5f6 zr4_ZjY(88yqj>MoeQt&p!jjawdQE|9Aou$;bM67i!5&&ykpj35TK^XEVQptR$zbov zDYqu{V{4r5m9dhyV|8mP#BN=L3i1pdYn4$i$}T+^@+KYAapIf-R|MZqQ#eSa>39-K z8*rAfaj_)zuJM=WSJ8P(Re|_|W1UKK;UdMkgHW4d-=>snscrRGM%8Q@Q1?Gn#Hs`b z$oa4;M@|;x+u$++^;0m7Eqk9r>wR+?BHL~)$5wbXv${9s`_=a7UYE4_Oq|#;cIM@M zCmAL0^81#eS*~ZlE$N-FV*cBxX$LxPoM4T)w$hOXSk{{#31Iv4_f8YIy&2O%8z_B& zfgLRiC%iiyJ8Tjfv>ELdbTwl-ja-_|recH!+pNCN&I-)82-{5vqbD#hloBs;eLAmG z29`yfs#9~ONWEn(ty@Nfapy~dbKG+xSZ=Zq|#K5 z&G^Pvqq*?4#j8IP+1qP%am_MA({2%w&0g!5qc>)e7-fdM!X_>*_Px`=E%c-ji$Ybs z!Al+Waf*+-V)w^?$-=44)%br7hl*IYx!(E2yeJee$)?B7rDG1@QzudO$!V7#p2XVK z5t;3e?SO@SmQAmU8c7Gk40s0o7fUd}4eXk;=Yo+qoP1rL2n~M)G-R_j!*UT)u2V5Ja(&X8z{I>}#qwf$^^JR`rd5yKy!3p7Z4zW;k0W-0gYo%srIXL%o+q&O z7xwbyxKYNxMiq%u;HLoaCL#BLn9zSbpDf7vX|x4%KzGWU1Jx;Ojh8-H(%UjB9xgJj z^xqlLB6G(hoyI?)i7Bk@NQ2A_YiWc1(&=kzHTuo{1m>N7k)?+74VH$BeV|Q>&w&-m z^;z^O9IVgbYP5T3|Mo&Zg*vhC#DkZsF;8I{zMl>NAo6$G)8>gtw5p#YP4jznU*A20 zb6%b+_~Ht`#t#YSqEiW!RVH+D`(|+a8wF2W-df`(d7vMb)i=NIZi62_rAX2bh(fjC z(Ld$pElf$8On$po-1|Et$25?~d2R5$w{a;AFn8$(ieq4d&Y=Uc=$OzhSR|1ucKmVF z<>QV5{Vo@Re!)BgDRU>CenF14Ztnr=?gg;cGt$SE$a*0!@M61Hty8>}T5pK0AAN^> z17Uu4qgO~Wei`tys?3%j=D)lyF^--EB|tO`R;blbq=aov7Zd-^PCllNdSPEL3eJ!A zvzlF}J+4WJ2D=S8)oi7v$MUZ{H(7pY_+VUGzDdN{7hkM+s$ab+Z{dt;{ct|yAo1e) z)4ZGFpw?G?wx?y)Z!`@ZU4xLnXQZ_Kdu1k3C>pm%e-KFucxBS$jMQx2Y20sAGJ7E< zZP`sz`^BpXZrz%yFvzpt7$V_>TbSfEF#0E1>IZ4D?6veRs|UNTw;spNw84mQhb6aitA_PgH*0H!qCt@PWABva z{Oo`w0yxn3mDc6@KixPDt<7pK_fxAY@nb)FAzW|3?+l3WHuNsF@GeQbX#MT$t7-S0 zE||qu)M%>Tjc$!V;=3_)d;8nYhS#OJO0ulT&{NUNy|nC}z)jtiv_gERH2N-ZKXN}9 z3p7UKIUyxP;4OTGSwBVZS71Ry4q(&Wjs+Qwj9IiXzG%!m{lRvja8Zh2xh*Dx2pe}P zfwVs3WQ{bhOZ_Zzr*sbIZx}umj<@HH^J{6CPpC^tEUSux5In9e`j`M|Fa8pU3LgLI zg&7B2>L8@8glYAvE(g!h!ReAsjCy9Xl6{lKfm7o*d*S_-7d&Y8=B+QWaq2$xes5n= zr<70ax#23ytxLOFq@Q*@uac(iP7$H(^$1?QB}RG&!T_3jy8EEM)x#Yk-js6q1f<6NMG1bnLAyka#SOvd)h`x18VBk_&CB92#Qc7mT zD@1xsP5pI%>I-g~ChQV>LMGw!Hu0IU8IyP>$vbAjOBbz4x0mc34t`oCr=QrKS1GjW zr&KBG)=-Nb$!#6CSHrKSPsh5=@D=m&>Sca<*hfErUXUOGX)6iy8Z zfB+_Ktdpr@Md$JHNQbYM*yFB3)}cPD!Mnr#{v<66LNtL?&6KyeI|Q8|K2F*(e)kJ` z$-@Od>b?%KkoCGhqD1uWIyy2czv>UO0~Nwr*Jw>tPcat6UtQPd4FcAH>4M6c^?l&Y*5um%(^V%_4cBq?gTyn{cj*Zqh_HpPgBZ;>oiZC0tha z6Zfow4Eft_XJK%}8_|rXVEV&`V@|rc6#}dZjZ4bjGV6+Tp@J?nhSHawOTv95nE>ad zn^#>y_mOB{<(F85nya^WXB_RP8vg^*ILnK2=;?uvh3H|X7rF@*OBt|G+lf9}|FsE4 z4?jYQNXPxzgvLaDIp3FmkoGba7*LA-4}ApMZ&$kKbHZ_hVE^Gwr7r914ot~w(AL4A|&gzuV!>2d-;X_xy(fyiZl8auPD-jEO} zuE0@*qv6w(HV!SpV$3ODT=%Wfw3)+WBq#{V1j!`p2E3wEO{g=ckOhQLGDE0(*qtTc zy=R7k>x-(5c{K2@x#SXF_<2e#?y=sFSK5HW3p6oKm|!ygb8)9K6_xnEHJmRctHW3U;p_adLh6WglBz%QVwM$;#UPR;p7P?$Vnx%+4TWw zv2BT!=u?b0=~(@)8MGGO3w>1s_Y`BwfGZ_$Zj=SMwtotGeg~Ks_8S|~U|VG^r#pPY zW3skypD&bbr=y5bQMd>b?dr$|*-of%u9D>KgiM^uPnSeze38xf^t$9~ol^BYBdPd@ zL+M$0niA*ns1keeF`nO2*esXfw7JGo5tqyf{E-}8{{ryN&0W%bdn0NGWX&re$uoY<~ih5OittM6cKh<3OR}xkn z?{Umpo?6rLk&o6+x$=Q#LsZh1mCF`bIYm)Od$^z}n35>LamxoOdYX}&rIdzHsYvB~ zWMUeU^Ff+uJ}D55tPnH-Mc8HgEB3=Z_s9FW_uTvae(v{v?q>u_Ye?2)W^$2;MA&s6 zrYGK1@T?&&!xe}2ddG5|O==r zgwyI5*HD3cwVrlr&I}^;$#ErGuuo8u0GKIatl_km11WHwfhTNx+pcaaZn3#o804vI z$6uTFPFecc_f*xwMIK|gedDWpU6~&85&AiJ%1ro}c98zF zHmVQuP%mWa-ag{USS-IyB7{fH66I`MoQF=_LoT~Aw7m=PNjpiR@9xiwO@%q=y4Sv= z^w=Vg?@ilRnPzHrZR?5iZdke;yNs*ytVx<|EddnjPJk-E&(hh8EV$B=F?+@!^xYuB z(q_mHj0B7MAvdCyAy>bwE>ceoBi<*cIbr^|S*UV`+Xqn=2AX~{NrXZaJbf>SwYG-0 zk~2}^Ioah<|E5F@^*gcbSW)%sfbjyg2SGS7^Ytt?n|YEG|7oi2M$ztboGFOkX4F76$p%j>(#bWn4>fRL@U3Sa|?)i`7^Yu9Av;!F@!Eu z{JRkHCzijs^f4=`HKY65g7mU|`;czO!OM^%lw_i@=02)5R$KS7G zi>H&aTTN@C{L}Yh(hce~B_5lnPbfPQyCEhO$Q10Fmly2dgl+f76W=HQF!_?N*F8}= zF$6RXiZXXkP9#-yN?La;;+PHkkvp*33>cM~s}YUm#I> zY-~(EyRi{PRkBe;whKCp-Iq%tc->#U`kDl1Yiuq_0ExqPv}u`t`LWchXlVZ%!73m# z*jYgP{J>kQljBDp-@XfwSOH1tZ}n1VfNww%=9Sm=K#dHd?lKxXPpfrB5dXQ2wvD86 zdvoT^9B&67L)TQ?;0Z#nYS5S{M!TrD!wl(Fh&U#BiguP7Xikj^04p{b7&bB`xZ_TC zW>~u!td?2FL`gilKIkvTf@m`A8&KZWr>`|c_Jh;y80g4hQTFs2-dGYBErW8i+H+1u zTJX?-EiGPB6-?E{_6hKjdn-A<%_E?u#gGc(bG)QflrY>4dWCR1O!|JLTjEeJ~LiCF0K$d`6)h!nN zZD=lDVROP?wCgf15eW zjU9$N!Tfny9{*wOmk;tl*RXI-+omd2%2HoAFt`IauwU>!+A)Y|pEP`x*X0J{q=UIj`!tlru9J!(e>%0| zhqw{t5k2LY>VqEGrOO_?gUe&Q%XOhvbvSRofn0Uw;rxxz`1smQ;5uUGf}$O=i8=2o z_7vXJD`2T4z?mSzF}}6;r4MIr`H^={Az5@#)Ivo^F_;P_Do{HEHcXW}uS0WnZ7aSw z@*#IJD*TcAZn9zw8(ALRxjkv1qVGeYkwmlFP+#FQMvtg)sBVErGvFhaNl^B-{~q0j k1Iz}k|L-TbdDF`CtI1A+$5q$CTvi-8gg97p;MA}G0D1Z+pa1{> literal 0 HcmV?d00001 diff --git a/crates/grida-canvas/src/io/io_grida.rs b/crates/grida-canvas/src/io/io_grida.rs index b2035dd0ca..81e402ac23 100644 --- a/crates/grida-canvas/src/io/io_grida.rs +++ b/crates/grida-canvas/src/io/io_grida.rs @@ -1135,6 +1135,27 @@ impl From for JSONVectorNetwork { } } +/// Result of flattening a shape to a vector network. +/// +/// When `corner_radius` is `Some`, the vector network contains straight +/// segments and the corner radius should be applied as a rendering effect +/// (e.g. polygon, star). These shapes use `corner_path` PathEffect for +/// rendering, so the effect is preserved. +/// +/// When `corner_radius` is `None`, the corner geometry is already baked +/// into the vector network as Bézier curves (e.g. rectangle, ellipse). +/// Rectangles always bake because their native rrect rendering uses conic +/// arcs, which differ from the `corner_path` PathEffect. See +/// [`crate::shape::build_corner_radius_path`] for details. +#[derive(Debug, Serialize)] +pub struct JSONFlattenResult { + #[serde(flatten)] + pub vector_network: JSONVectorNetwork, + /// Uniform corner radius to apply as a rendering effect, if applicable. + #[serde(skip_serializing_if = "Option::is_none")] + pub corner_radius: Option, +} + #[derive(Debug, Deserialize)] pub struct JSONLineNode { #[serde(flatten)] diff --git a/crates/grida-canvas/src/shape/corner.rs b/crates/grida-canvas/src/shape/corner.rs index b06ff9399f..45a90d28f7 100644 --- a/crates/grida-canvas/src/shape/corner.rs +++ b/crates/grida-canvas/src/shape/corner.rs @@ -1,5 +1,70 @@ use skia_safe; +/// # Corner Radius: Two Distinct Backends +/// +/// Grida has **two different corner rounding mechanisms** that produce +/// visually different curves. This is a known limitation. +/// +/// ## Backend 1: `corner_path` PathEffect (this function) +/// +/// Used by: **polygons, stars, and vector nodes with `corner_radius`**. +/// +/// Skia's `PathEffect::corner_path(r)` walks the path and, at each sharp +/// vertex, cuts the two adjacent edges at distance `r` from the corner and +/// connects the cut points. The resulting corner is **not** a circular arc — +/// it is a simpler geometric cut that depends on the angle between the edges. +/// +/// ## Backend 2: Native `SkRRect` (conic arcs) +/// +/// Used by: **rectangles with corner radius** (the `RectangleNode` primitive). +/// +/// Skia's `RRect` internally uses **conic curves** (rational quadratic Bézier +/// with weight `w = √2/2`) to draw true circular arcs at each corner. This +/// produces a geometrically precise quarter-circle. +/// +/// ## Why they differ +/// +/// The two approaches use mathematically distinct curve types: +/// +/// - **`corner_path`** (`SkCornerPathEffect`): At each corner, cuts the two +/// adjacent edges at distance `r` from the vertex, then connects the cut +/// points with a **quadratic Bézier** (`quadTo`) whose control point is +/// the original corner vertex. This traces a **parabolic arc**. +/// +/// - **Native rrect** (`SkRRect`): Uses **conic curves** (rational quadratic +/// Bézier with weight `w = √2/2`) at each corner, which trace a **true +/// circular arc** of radius `r`. +/// +/// A parabolic arc and a circular arc through the same two endpoints with +/// the same corner vertex as control point are different curves. At large +/// radii (e.g. `r = 80` on a 400×400 rectangle), the difference is clearly +/// visible — roughly 1–2% of pixels differ, with entire pixels filled in +/// one but empty in the other. +/// +/// ## Implications for flatten (shape → vector) +/// +/// When flattening a rectangle to a vector node: +/// - **Do NOT** use "simple rect VN + `corner_radius`" for rectangles, because +/// the vector renderer applies `corner_path` (Backend 1), which would produce +/// a different shape than the original rrect (Backend 2). +/// - **Always bake** the rrect Bézier curves into the vector network geometry. +/// This guarantees pixel-identical output. +/// +/// Polygons and stars are safe to flatten as "straight VN + `corner_radius`" +/// because their original rendering already uses `corner_path` (Backend 1). +/// +/// ## Future work +/// +/// `SkCornerPathEffect` is **pure CPU path manipulation** — it walks the path +/// vertices, computes cut points, and emits `quadTo` segments. There is no +/// GPU shader involved. This means we can replace it with a custom +/// implementation that emits **conic arcs** (matching `SkRRect`) instead of +/// quadratic Béziers, without any GPU/shader work and without significant +/// performance loss. The algorithm is ~150 lines of C++ (see +/// `SkCornerPathEffect.cpp`). A Rust port that uses `conicTo` instead of +/// `quadTo` at line 92 would unify both backends. +/// +/// See also: `golden_corner_radius_backends` example for a visual comparison. pub fn build_corner_radius_path(path: &skia_safe::Path, r: f32) -> skia_safe::Path { let mut paint = skia_safe::Paint::default(); paint.set_path_effect(skia_safe::PathEffect::corner_path(r)); diff --git a/crates/grida-canvas/src/shape/rrect.rs b/crates/grida-canvas/src/shape/rrect.rs index 855c2a98b8..a22c9718d3 100644 --- a/crates/grida-canvas/src/shape/rrect.rs +++ b/crates/grida-canvas/src/shape/rrect.rs @@ -44,6 +44,13 @@ pub fn build_rrect_path(shape: &RRectShape) -> skia_safe::Path { /// conic curves internally. The `VectorNetwork::from(&Path)` conversion /// handles conic-to-cubic promotion, guaranteeing the resulting cubic Bézier /// segments are pixel-identical to what Skia renders. +/// +/// **Why baking is required for rectangles:** Skia's native rrect uses conic +/// arcs (true circular corners), while the `corner_path` PathEffect — used by +/// the vector node renderer for `corner_radius` — produces a different curve. +/// Applying `corner_radius` as a rendering effect on a simple rect VN would +/// NOT match the original rrect shape. See [`build_corner_radius_path`] for +/// full documentation of this difference. pub fn build_rrect_vector_network(shape: &RRectShape) -> VectorNetwork { let path = build_rrect_path(shape); VectorNetwork::from(&path) @@ -53,6 +60,89 @@ pub fn build_rrect_vector_network(shape: &RRectShape) -> VectorNetwork { mod tests { use super::*; + /// Regression test: native rrect and `corner_path` PathEffect produce + /// different curves. This documents the known limitation described in + /// `shape/corner.rs`. If this test ever fails (i.e. the two become + /// identical), the flatten pipeline could be simplified. + /// + /// **Root cause:** `SkCornerPathEffect` inserts a **quadratic Bézier** + /// (`quadTo`) at each corner, with the control point at the original + /// vertex. This traces a parabolic arc. Skia's native rrect uses + /// **conic curves** (weight `√2/2`), which trace a true circular arc. + /// A quadratic Bézier and a weighted conic are mathematically distinct + /// curves for the same corner. + /// + /// See also: `golden_corner_radius_backends` example. + #[test] + fn rrect_and_corner_path_effect_produce_different_curves() { + let radius = 80.0_f32; + let w = 400; + let h = 400; + + // Backend 1: Skia's native rrect (conic arcs) + let rrect_shape = RRectShape { + width: w as f32, + height: h as f32, + corner_radius: RectangularCornerRadius::circular(radius), + }; + let rrect_path = build_rrect_path(&rrect_shape); + + // Backend 2: rect + corner_path PathEffect + let rect_shape = super::super::RectShape { + width: w as f32, + height: h as f32, + }; + let rect_path: skia_safe::Path = (&rect_shape).into(); + let corner_effect_path = super::super::build_corner_radius_path(&rect_path, radius); + + // Render both and count differing pixels + use skia_safe::{surfaces, Color4f, ColorSpace, Paint}; + let mut paint = Paint::new(Color4f::new(1.0, 0.0, 0.0, 1.0), &ColorSpace::new_srgb()); + paint.set_anti_alias(true); + + let mut surf_a = surfaces::raster_n32_premul((w, h)).expect("surface"); + surf_a.canvas().clear(Color4f::new(0.0, 0.0, 0.0, 0.0)); + surf_a.canvas().draw_path(&rrect_path, &paint); + + let mut surf_b = surfaces::raster_n32_premul((w, h)).expect("surface"); + surf_b.canvas().clear(Color4f::new(0.0, 0.0, 0.0, 0.0)); + surf_b.canvas().draw_path(&corner_effect_path, &paint); + + let img_a = surf_a.image_snapshot(); + let img_b = surf_b.image_snapshot(); + let info = img_a.image_info(); + let row_bytes = info.min_row_bytes(); + let mut pixels_a = vec![0u8; row_bytes * h as usize]; + let mut pixels_b = vec![0u8; row_bytes * h as usize]; + img_a.read_pixels( + &info, &mut pixels_a, row_bytes, + skia_safe::IPoint::new(0, 0), skia_safe::image::CachingHint::Allow, + ); + img_b.read_pixels( + &info, &mut pixels_b, row_bytes, + skia_safe::IPoint::new(0, 0), skia_safe::image::CachingHint::Allow, + ); + + let pixel_count = (w * h) as usize; + let mut diff_count = 0usize; + for i in 0..pixel_count { + let off = i * 4; + let da = (pixels_a[off + 3] as i16 - pixels_b[off + 3] as i16).unsigned_abs(); + if da > 1 { + diff_count += 1; + } + } + + // The two backends MUST differ. If they ever become identical, + // the flatten pipeline could use corner_radius as a rendering + // effect for uniform-radius rectangles instead of baking curves. + assert!( + diff_count > 100, + "Expected significant pixel differences between rrect and corner_path, \ + got only {diff_count}. Has Skia unified the backends?" + ); + } + #[test] fn rectangle_vector_network_is_straight() { let shape = RRectShape { diff --git a/crates/grida-canvas/src/window/application.rs b/crates/grida-canvas/src/window/application.rs index f6d2aea0c1..737819093e 100644 --- a/crates/grida-canvas/src/window/application.rs +++ b/crates/grida-canvas/src/window/application.rs @@ -4,7 +4,7 @@ use crate::devtools::{ }; use crate::dummy; use crate::export::{export_node_as, ExportAs, Exported}; -use crate::io::io_grida::{self, JSONVectorNetwork}; +use crate::io::io_grida::{self, JSONFlattenResult}; use crate::io::io_grida_patch::{self, TransactionApplyReport}; use crate::node::schema::*; use crate::resources::{FontMessage, ImageMessage}; @@ -44,7 +44,7 @@ pub trait ApplicationApi { fn get_node_ids_from_envelope(&mut self, envelope: Rectangle) -> Vec; fn get_node_absolute_bounding_box(&mut self, id: &str) -> Option; fn export_node_as(&mut self, id: &str, format: ExportAs) -> Option; - fn to_vector_network(&mut self, id: &str) -> Option; + fn to_vector_network(&mut self, id: &str) -> Option; /// Enable or disable caching of raster tiles. fn runtime_renderer_set_cache_tile(&mut self, cache: bool); @@ -343,17 +343,34 @@ impl ApplicationApi for UnknownTargetApplication { return None; } - fn to_vector_network(&mut self, id: &str) -> Option { + fn to_vector_network(&mut self, id: &str) -> Option { let internal_id = self.user_id_to_internal(id)?; if let Some(scene) = self.renderer.scene.as_ref() { if let Ok(node) = scene.graph.get_node(&internal_id) { - let vn = match node { - Node::Rectangle(n) => Some(n.to_vector_network()), - Node::Ellipse(n) => Some(n.to_vector_network()), - Node::Polygon(n) => Some(n.to_vector_network()), - Node::RegularPolygon(n) => Some(n.to_vector_network()), - Node::RegularStarPolygon(n) => Some(n.to_vector_network()), - Node::Vector(n) => Some(n.network.clone()), + /// Convert a positive corner radius to `Some`, zero/negative to `None`. + fn nonzero_radius(r: f32) -> Option { + if r > 0.0 { Some(r) } else { None } + } + + let result: Option<(VectorNetwork, Option)> = match node { + // Rectangle: always bake corner geometry into the VN. + // Skia's native rrect uses conic arcs while corner_path + // PathEffect uses a different curve type (quadratic Bézier). + // See `shape/corner.rs` for documentation. + Node::Rectangle(n) => Some((n.to_vector_network(), None)), + Node::Ellipse(n) => Some((n.to_vector_network(), None)), + // Polygon/star shapes use corner_path for rendering, so + // corner_radius is preserved as a rendering effect. + Node::Polygon(n) => { + Some((n.to_vector_network(), nonzero_radius(n.corner_radius))) + } + Node::RegularPolygon(n) => { + Some((n.to_vector_network(), nonzero_radius(n.corner_radius))) + } + Node::RegularStarPolygon(n) => { + Some((n.to_vector_network(), nonzero_radius(n.corner_radius))) + } + Node::Vector(n) => Some((n.network.clone(), None)), // TODO: find a better way to clean this, as simple as Text::to_vector_network() Node::TextSpan(n) => { let paragraph = self.renderer.get_cache().paragraph.borrow_mut().paragraph( @@ -386,11 +403,14 @@ impl ApplicationApi for UnknownTargetApplication { if y_offset != 0.0 { path = path.make_transform(&Matrix::translate((0.0, y_offset))); } - Some(VectorNetwork::from(&path)) + Some((VectorNetwork::from(&path), None)) } _ => None, }; - return vn.map(|v| v.into()); + return result.map(|(vn, cr)| JSONFlattenResult { + vector_network: vn.into(), + corner_radius: cr, + }); } } None diff --git a/crates/grida-canvas/src/window/application_emscripten.rs b/crates/grida-canvas/src/window/application_emscripten.rs index 129cad4bc8..37748de3f7 100644 --- a/crates/grida-canvas/src/window/application_emscripten.rs +++ b/crates/grida-canvas/src/window/application_emscripten.rs @@ -1,4 +1,4 @@ -use crate::io::io_grida::JSONVectorNetwork; +use crate::io::io_grida::JSONFlattenResult; use crate::io::io_grida_patch::TransactionApplyReport; use crate::resources::{FontMessage, ImageMessage}; use crate::runtime::camera::Camera2D; @@ -214,7 +214,7 @@ impl ApplicationApi for EmscriptenApplication { self.base.export_node_as(id, format) } - fn to_vector_network(&mut self, id: &str) -> Option { + fn to_vector_network(&mut self, id: &str) -> Option { self.base.to_vector_network(id) } diff --git a/crates/grida-canvas/tests/flatten_rendiff.rs b/crates/grida-canvas/tests/flatten_rendiff.rs new file mode 100644 index 0000000000..98024f32eb --- /dev/null +++ b/crates/grida-canvas/tests/flatten_rendiff.rs @@ -0,0 +1,303 @@ +//! Pixel-comparison tests for the flatten (shape → vector network) pipeline. +//! +//! Each test renders the original shape path and then renders the vector +//! network that the flatten pipeline would produce (optionally with +//! corner_radius as a PathEffect). The two images are compared via rendiff. + +use cg::cg::types::{Radius, RectangularCornerRadius}; +use cg::shape::*; +use cg::vectornetwork::VectorNetwork; +use rendiff::Threshold; +use skia_safe::{surfaces, Color4f, ColorSpace, Paint}; + +/// Render a Skia path to RGBA pixels. +fn render_to_rgba(path: &skia_safe::Path, w: i32, h: i32) -> Vec<[u8; 4]> { + let mut paint = Paint::new(Color4f::new(1.0, 0.0, 0.0, 1.0), &ColorSpace::new_srgb()); + paint.set_anti_alias(true); + let mut surface = surfaces::raster_n32_premul((w, h)).expect("surface"); + surface.canvas().clear(Color4f::new(0.0, 0.0, 0.0, 0.0)); + surface.canvas().draw_path(path, &paint); + let img = surface.image_snapshot(); + let info = img.image_info(); + let row_bytes = info.min_row_bytes(); + let mut raw = vec![0u8; row_bytes * h as usize]; + img.read_pixels( + &info, + &mut raw, + row_bytes, + skia_safe::IPoint::new(0, 0), + skia_safe::image::CachingHint::Allow, + ); + let pixel_count = (w * h) as usize; + let mut rgba = Vec::with_capacity(pixel_count); + for i in 0..pixel_count { + let off = i * 4; + // Skia N32 premul is BGRA on little-endian → RGBA for rendiff + rgba.push([raw[off + 2], raw[off + 1], raw[off], raw[off + 3]]); + } + rgba +} + +/// Apply corner radius to a path via Skia's corner PathEffect. +fn apply_corner_radius(path: &skia_safe::Path, radius: f32) -> skia_safe::Path { + if radius <= 0.0 { + return path.clone(); + } + cg::shape::build_corner_radius_path(path, radius) +} + +/// Assert that two rendered images match within the rendiff threshold. +/// +/// Allows any number of edge anti-aliasing differences ≤10 and up to 300 +/// differences ≤60 per-channel (conic vs cubic rasterization differences). +fn assert_rendiff_match( + name: &str, + pixels_a: Vec<[u8; 4]>, + pixels_b: Vec<[u8; 4]>, + w: usize, + h: usize, +) { + let img_a = imgref::Img::new(pixels_a, w, h); + let img_b = imgref::Img::new(pixels_b, w, h); + let diff = rendiff::diff(img_a.as_ref(), img_b.as_ref()); + let threshold = Threshold::new([(10, usize::MAX), (60, 300)]); + assert!( + threshold.allows(diff.histogram()), + "{name}: pixel mismatch exceeds threshold.\n histogram: {:?}", + diff.histogram(), + ); +} + +// ── Rectangle tests ────────────────────────────────────────────────────────── + +#[test] +fn flatten_rect_no_radius() { + let w = 200; + let h = 150; + let shape = RectShape { + width: w as f32, + height: h as f32, + }; + + // Original: simple rect path + let original_path: skia_safe::Path = (&shape).into(); + let original = render_to_rgba(&original_path, w, h); + + // Flattened: rect VN → path (no corner radius) + let vn = build_rect_vector_network(&shape); + let vn_paths = vn.to_paths(); + let flattened = render_to_rgba(&vn_paths[0], w, h); + + assert_rendiff_match("rect_no_radius", original, flattened, w as usize, h as usize); +} + +#[test] +fn flatten_rect_uniform_radius() { + let w = 200; + let h = 200; + let radius = 30.0_f32; + let corner_radius = RectangularCornerRadius::circular(radius); + + // Rectangle with uniform radius: Bézier curves are baked into the VN. + // (corner_path PathEffect and native rrect use different math, so + // baking is the only way to guarantee pixel-identical output.) + let shape = RRectShape { + width: w as f32, + height: h as f32, + corner_radius, + }; + + let original_path = build_rrect_path(&shape); + let original = render_to_rgba(&original_path, w, h); + + let vn = build_rrect_vector_network(&shape); + let vn_paths = vn.to_paths(); + let flattened = render_to_rgba(&vn_paths[0], w, h); + + assert_rendiff_match( + "rect_uniform_radius", + original, + flattened, + w as usize, + h as usize, + ); +} + +#[test] +fn flatten_rect_non_uniform_radius() { + let w = 200; + let h = 150; + let corner_radius = RectangularCornerRadius { + tl: Radius::circular(10.0), + tr: Radius::circular(30.0), + br: Radius::circular(50.0), + bl: Radius::circular(20.0), + }; + + let shape = RRectShape { + width: w as f32, + height: h as f32, + corner_radius, + }; + + // Original: rrect path (non-uniform) + let original_path = build_rrect_path(&shape); + let original = render_to_rgba(&original_path, w, h); + + // Flattened: bake Bézier curves into VN (no separate corner_radius) + let vn = build_rrect_vector_network(&shape); + let vn_paths = vn.to_paths(); + let flattened = render_to_rgba(&vn_paths[0], w, h); + + assert_rendiff_match( + "rect_non_uniform_radius", + original, + flattened, + w as usize, + h as usize, + ); +} + +// ── Polygon tests ──────────────────────────────────────────────────────────── + +#[test] +fn flatten_polygon_no_radius() { + let w = 200; + let h = 200; + + let shape = RegularPolygonShape { + width: w as f32, + height: h as f32, + point_count: 6, + corner_radius: 0.0, + }; + + let original_path = build_regular_polygon_path(&shape); + let original = render_to_rgba(&original_path, w, h); + + let vg = build_regular_polygon_vector_geometry(&shape); + let vn: VectorNetwork = vg.into(); + let vn_paths = vn.to_paths(); + let flattened = render_to_rgba(&vn_paths[0], w, h); + + assert_rendiff_match( + "polygon_no_radius", + original, + flattened, + w as usize, + h as usize, + ); +} + +#[test] +fn flatten_polygon_with_radius() { + let w = 200; + let h = 200; + let radius = 15.0_f32; + + let shape = RegularPolygonShape { + width: w as f32, + height: h as f32, + point_count: 5, + corner_radius: radius, + }; + + // Original: polygon path with corner radius applied + let original_path = build_regular_polygon_path(&shape); + let original = render_to_rgba(&original_path, w, h); + + // Flattened: polygon VN (straight) + corner_radius as PathEffect + let vg = build_regular_polygon_vector_geometry(&shape); + let vn: VectorNetwork = vg.into(); + let vn_paths = vn.to_paths(); + let rounded_path = apply_corner_radius(&vn_paths[0], radius); + let flattened = render_to_rgba(&rounded_path, w, h); + + assert_rendiff_match( + "polygon_with_radius", + original, + flattened, + w as usize, + h as usize, + ); +} + +// ── Star tests ─────────────────────────────────────────────────────────────── + +#[test] +fn flatten_star_no_radius() { + let w = 200; + let h = 200; + + let shape = RegularStarShape { + width: w as f32, + height: h as f32, + inner_radius_ratio: 0.5, + point_count: 5, + corner_radius: 0.0, + }; + + let original_path = build_star_path(&shape); + let original = render_to_rgba(&original_path, w, h); + + let vg = build_star_vector_geometry(&shape); + let vn: VectorNetwork = vg.into(); + let vn_paths = vn.to_paths(); + let flattened = render_to_rgba(&vn_paths[0], w, h); + + assert_rendiff_match("star_no_radius", original, flattened, w as usize, h as usize); +} + +#[test] +fn flatten_star_with_radius() { + let w = 200; + let h = 200; + let radius = 10.0_f32; + + let shape = RegularStarShape { + width: w as f32, + height: h as f32, + inner_radius_ratio: 0.4, + point_count: 6, + corner_radius: radius, + }; + + let original_path = build_star_path(&shape); + let original = render_to_rgba(&original_path, w, h); + + let vg = build_star_vector_geometry(&shape); + let vn: VectorNetwork = vg.into(); + let vn_paths = vn.to_paths(); + let rounded_path = apply_corner_radius(&vn_paths[0], radius); + let flattened = render_to_rgba(&rounded_path, w, h); + + assert_rendiff_match( + "star_with_radius", + original, + flattened, + w as usize, + h as usize, + ); +} + +// ── Ellipse test ───────────────────────────────────────────────────────────── + +#[test] +fn flatten_ellipse() { + let w = 200; + let h = 150; + + let shape = EllipseShape { + width: w as f32, + height: h as f32, + }; + + let original_path = build_ellipse_path(&shape); + let original = render_to_rgba(&original_path, w, h); + + let vn = build_ellipse_vector_network(&shape); + let vn_paths = vn.to_paths(); + let flattened = render_to_rgba(&vn_paths[0], w, h); + + assert_rendiff_match("ellipse", original, flattened, w as usize, h as usize); +} diff --git a/editor/grida-canvas/backends/wasm.ts b/editor/grida-canvas/backends/wasm.ts index 9d375c469d..d294862ff1 100644 --- a/editor/grida-canvas/backends/wasm.ts +++ b/editor/grida-canvas/backends/wasm.ts @@ -160,7 +160,7 @@ export class CanvasWasmVectorInterfaceProvider readonly surface: Scene ) {} - toVectorNetwork(node_id: string): vn.VectorNetwork | null { + toVectorNetwork(node_id: string): vn.FlattenResult | null { return this.surface.toVectorNetwork(node_id); } } diff --git a/editor/grida-canvas/editor.i.ts b/editor/grida-canvas/editor.i.ts index a6c3234d62..4ac6e3b439 100644 --- a/editor/grida-canvas/editor.i.ts +++ b/editor/grida-canvas/editor.i.ts @@ -2732,11 +2732,16 @@ export namespace editor.api { export interface IDocumentVectorInterfaceProvider { /** - * converts the node into a vector network + * Converts the node into a flatten result (vector network + optional corner radius). + * + * When `corner_radius` is present in the result, the vector network has + * straight segments and corner radius should be preserved on the vector node. + * When absent, corner geometry is baked into the Bézier curves. + * * @param node_id - * @returns vector network or null if unsupported + * @returns flatten result or null if unsupported */ - toVectorNetwork(node_id: string): vn.VectorNetwork | null; + toVectorNetwork(node_id: string): vn.FlattenResult | null; } // diff --git a/editor/grida-canvas/reducers/methods/flatten.ts b/editor/grida-canvas/reducers/methods/flatten.ts index 1fe7207385..f9c9dfd3dd 100644 --- a/editor/grida-canvas/reducers/methods/flatten.ts +++ b/editor/grida-canvas/reducers/methods/flatten.ts @@ -6,7 +6,6 @@ import vn from "@grida/vn"; import grida from "@grida/schema"; import cmath from "@grida/cmath"; import { normalizeVectorNodeBBox } from "./vector"; -import * as modeProperties from "@/grida-canvas/utils/properties"; /** * Node types that can be flattened into vector paths. @@ -57,27 +56,37 @@ export function self_flattenNode( const rect = context.geometry.getNodeAbsoluteBoundingRect(node_id); if (!rect) return null; - // attempt to resolve vector network via wasm backend when available - let v: vn.VectorNetwork | null = null; + // attempt to resolve vector network via wasm backend when available. + // The result includes an optional corner_radius: when present, the VN has + // straight segments and corner radius is a rendering effect to preserve. + let flattenResult: vn.FlattenResult | null = null; try { - v = context.vector?.toVectorNetwork(node_id) ?? null; + flattenResult = context.vector?.toVectorNetwork(node_id) ?? null; } catch {} - if (!v) { - v = toVectorNetworkFallback(node, { + if (!flattenResult) { + const fallback = toVectorNetworkFallback(node, { width: rect.width, height: rect.height, }); + if (fallback) { + flattenResult = fallback; + } } - if (!v) return null; + if (!flattenResult) return null; + + // Extract corner_radius from rust-side result (if curves are NOT baked in). + // When corner_radius is present, the vector node should keep it as a + // rendering effect. When absent, geometry is baked — clear corner_radius. + const { corner_radius: resultCornerRadius, ...vectorNetwork } = flattenResult; const vectornode: grida.program.nodes.VectorNode = { ...(node as grida.program.nodes.UnknownNode), type: "vector", id: node.id, active: node.active, - corner_radius: modeProperties.cornerRadius(node), + corner_radius: resultCornerRadius ?? undefined, fill_rule: (node as grida.program.nodes.UnknownNode).fill_rule ?? "nonzero", - vector_network: v, + vector_network: vectorNetwork, layout_target_width: rect.width, layout_target_height: rect.height, layout_inset_left: (node as grida.program.nodes.UnknownNode) @@ -101,35 +110,34 @@ function __dangerously_delete_non_vector_properties( node: grida.program.nodes.Node ) { // Remove primitive-only properties that should not persist on vector nodes. - // star - delete (node as any).pointCount; - delete (node as any).innerRadius; + + // star / polygon + delete (node as any).point_count; + delete (node as any).inner_radius; + + // rectangle (per-corner radius & per-side stroke width) + delete (node as any).rectangular_corner_radius_top_left; + delete (node as any).rectangular_corner_radius_top_right; + delete (node as any).rectangular_corner_radius_bottom_left; + delete (node as any).rectangular_corner_radius_bottom_right; + delete (node as any).corner_smoothing; + delete (node as any).rectangular_stroke_width_top; + delete (node as any).rectangular_stroke_width_right; + delete (node as any).rectangular_stroke_width_bottom; + delete (node as any).rectangular_stroke_width_left; + + // ellipse (arc data) + delete (node as any).angle; + delete (node as any).angle_offset; // text delete (node as any).text; } -function modeCornerRadius(node: grida.program.nodes.Node): number | undefined { - if ("corner_radius" in node) { - return node.corner_radius; - } - - if ("rectangular_corner_radius_top_left" in node) { - const values: number[] = [ - node.rectangular_corner_radius_top_left, - node.rectangular_corner_radius_top_right, - node.rectangular_corner_radius_bottom_left, - node.rectangular_corner_radius_bottom_right, - ].filter((it) => it !== undefined); - - return cmath.mode(values); - } -} - function toVectorNetworkFallback( node: grida.program.nodes.Node, size: { width: number; height: number } -): vn.VectorNetwork | null { +): vn.FlattenResult | null { switch (node.type) { case "rectangle": { return vn.fromRect({ diff --git a/packages/grida-canvas-vn/vn.ts b/packages/grida-canvas-vn/vn.ts index f84cce97b7..786c8c75c4 100644 --- a/packages/grida-canvas-vn/vn.ts +++ b/packages/grida-canvas-vn/vn.ts @@ -211,6 +211,20 @@ export namespace vn { segments: VectorNetworkSegment[]; } + /** + * Result of flattening a shape node to a vector network. + * + * When `corner_radius` is present, the vector network contains straight + * segments and corner radius should be applied as a rendering effect + * (e.g. polygon, star). + * + * When `corner_radius` is absent, corner geometry is already baked into + * the vector network as Bézier curves (e.g. rectangle, ellipse). + */ + export interface FlattenResult extends VectorNetwork { + corner_radius?: number; + } + /** * tangent mirroring mode * From 9867758d2ab33c938379c32d29b9c1f2bc316002 Mon Sep 17 00:00:00 2001 From: Universe Date: Mon, 2 Mar 2026 22:51:41 +0900 Subject: [PATCH 3/5] fix: silence emscripten/wasm build warnings with cfg-gates and allow attributes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Prefix unused wasm stub param: url → _url in webfont_helper - Rename FFI param names to snake_case in os/emscripten.rs - Guard unreachable!() in application_emscripten with cfg(not(emscripten)) - cfg-gate native-only fields/methods in FrameScheduler and UnknownTargetApplication - Suppress deprecated warnings on intentional Anchored match arms --- .../src/helpers/webfont_helper.rs | 2 +- crates/grida-canvas/src/layout/into_taffy.rs | 1 + crates/grida-canvas/src/node/schema.rs | 2 ++ crates/grida-canvas/src/os/emscripten.rs | 10 ++++---- crates/grida-canvas/src/sys/scheduler.rs | 19 ++++++++++++++- crates/grida-canvas/src/window/application.rs | 23 ++++++++++++++++--- .../src/window/application_emscripten.rs | 13 ++++++++++- 7 files changed, 59 insertions(+), 11 deletions(-) diff --git a/crates/grida-canvas/src/helpers/webfont_helper.rs b/crates/grida-canvas/src/helpers/webfont_helper.rs index dd90bcb4ba..6c8acaa342 100644 --- a/crates/grida-canvas/src/helpers/webfont_helper.rs +++ b/crates/grida-canvas/src/helpers/webfont_helper.rs @@ -163,7 +163,7 @@ pub async fn fetch_webfont(url: &str) -> Result, Box Result, Box> { +pub async fn fetch_webfont(_url: &str) -> Result, Box> { // Stub for wasm Err("Webfont fetching not supported in wasm".into()) } diff --git a/crates/grida-canvas/src/layout/into_taffy.rs b/crates/grida-canvas/src/layout/into_taffy.rs index 961fe833ad..06fa41808f 100644 --- a/crates/grida-canvas/src/layout/into_taffy.rs +++ b/crates/grida-canvas/src/layout/into_taffy.rs @@ -153,6 +153,7 @@ impl From for Rect { top: LengthPercentageAuto::length(inset.top), bottom: LengthPercentageAuto::length(inset.bottom), }, + #[allow(deprecated)] LayoutPositioningBasis::Anchored => { unreachable!("Anchored positioning is not supported") } diff --git a/crates/grida-canvas/src/node/schema.rs b/crates/grida-canvas/src/node/schema.rs index 1bf78bf767..d591c1f6d1 100644 --- a/crates/grida-canvas/src/node/schema.rs +++ b/crates/grida-canvas/src/node/schema.rs @@ -780,6 +780,7 @@ impl LayoutPositioningBasis { match self { Self::Cartesian(point) => Some(point.x), Self::Inset(inset) => Some(inset.left), + #[allow(deprecated)] Self::Anchored => unreachable!("Anchored positioning is not supported"), } } @@ -788,6 +789,7 @@ impl LayoutPositioningBasis { match self { Self::Cartesian(point) => Some(point.y), Self::Inset(inset) => Some(inset.top), + #[allow(deprecated)] Self::Anchored => unreachable!("Anchored positioning is not supported"), } } diff --git a/crates/grida-canvas/src/os/emscripten.rs b/crates/grida-canvas/src/os/emscripten.rs index e93793671d..8caba22b6e 100644 --- a/crates/grida-canvas/src/os/emscripten.rs +++ b/crates/grida-canvas/src/os/emscripten.rs @@ -15,21 +15,21 @@ unsafe extern "C" { unsafe extern "C" { pub fn emscripten_request_animation_frame( cb: ::std::option::Option< - unsafe extern "C" fn(time: f64, userData: *mut ::std::os::raw::c_void) -> bool, + unsafe extern "C" fn(time: f64, user_data: *mut ::std::os::raw::c_void) -> bool, >, - userData: *mut ::std::os::raw::c_void, + user_data: *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int; } unsafe extern "C" { - pub fn emscripten_cancel_animation_frame(requestAnimationFrameId: ::std::os::raw::c_int); + pub fn emscripten_cancel_animation_frame(request_animation_frame_id: ::std::os::raw::c_int); } unsafe extern "C" { pub fn emscripten_request_animation_frame_loop( cb: ::std::option::Option< - unsafe extern "C" fn(time: f64, userData: *mut ::std::os::raw::c_void) -> bool, + unsafe extern "C" fn(time: f64, user_data: *mut ::std::os::raw::c_void) -> bool, >, - userData: *mut ::std::os::raw::c_void, + user_data: *mut ::std::os::raw::c_void, ); } diff --git a/crates/grida-canvas/src/sys/scheduler.rs b/crates/grida-canvas/src/sys/scheduler.rs index 407f08c156..54d7edae7b 100644 --- a/crates/grida-canvas/src/sys/scheduler.rs +++ b/crates/grida-canvas/src/sys/scheduler.rs @@ -1,14 +1,20 @@ +#[cfg(not(target_arch = "wasm32"))] use std::collections::VecDeque; -use std::time::{Duration, Instant}; +#[cfg(not(target_arch = "wasm32"))] +use std::time::Instant; +use std::time::Duration; /// A module that controls frame pacing using target and max FPS limits, /// while maintaining frame duration statistics for FPS estimation. /// In WASM, the pacing logic is a no-op and the browser controls timing. pub struct FrameScheduler { + #[cfg(not(target_arch = "wasm32"))] last_frame_time: Instant, target_frame_time: Duration, max_frame_time: Option, + #[cfg(not(target_arch = "wasm32"))] frame_durations: VecDeque, + #[cfg(not(target_arch = "wasm32"))] max_samples: usize, } @@ -16,10 +22,13 @@ impl FrameScheduler { /// Creates a new scheduler with a given target FPS and rolling sample size. pub fn new(target_fps: u32) -> Self { Self { + #[cfg(not(target_arch = "wasm32"))] last_frame_time: Instant::now(), target_frame_time: Duration::from_micros(1_000_000 / target_fps as u64), max_frame_time: None, + #[cfg(not(target_arch = "wasm32"))] frame_durations: VecDeque::with_capacity(60), + #[cfg(not(target_arch = "wasm32"))] max_samples: 60, } } @@ -31,6 +40,7 @@ impl FrameScheduler { } /// Records the most recent frame duration for smoothing. + #[cfg(not(target_arch = "wasm32"))] fn record_frame_duration(&mut self, duration: Duration) { if self.frame_durations.len() == self.max_samples { self.frame_durations.pop_front(); @@ -39,6 +49,7 @@ impl FrameScheduler { } /// Returns the average FPS based on the last N recorded frames. + #[cfg(not(target_arch = "wasm32"))] pub fn average_fps(&self) -> f32 { if self.frame_durations.is_empty() { return 0.0; @@ -49,6 +60,12 @@ impl FrameScheduler { 1_000_000.0 / avg.as_micros() as f32 } + /// In WASM, the browser controls frame rate; no frame duration tracking. + #[cfg(target_arch = "wasm32")] + pub fn average_fps(&self) -> f32 { + 0.0 + } + /// No-op in WASM; browser controls frame rate via rAF. #[cfg(target_arch = "wasm32")] pub fn sleep_to_maintain_fps(&mut self) { diff --git a/crates/grida-canvas/src/window/application.rs b/crates/grida-canvas/src/window/application.rs index 737819093e..cca24e1028 100644 --- a/crates/grida-canvas/src/window/application.rs +++ b/crates/grida-canvas/src/window/application.rs @@ -16,6 +16,7 @@ use crate::sys::timer::TimerMgr; use crate::text; use crate::vectornetwork::VectorNetwork; use crate::window::command::ApplicationCommand; +#[cfg(not(target_arch = "wasm32"))] use futures::channel::mpsc; use math2::{rect::Rectangle, transform::AffineTransform, vector2::Vector2}; use serde_json::Value; @@ -158,7 +159,9 @@ pub struct UnknownTargetApplication { pub(crate) hit_test_result: Option, pub(crate) hit_test_last: std::time::Instant, pub(crate) hit_test_interval: std::time::Duration, + #[cfg(not(target_arch = "wasm32"))] pub(crate) image_rx: mpsc::UnboundedReceiver, + #[cfg(not(target_arch = "wasm32"))] pub(crate) font_rx: mpsc::UnboundedReceiver, pub(crate) last_frame_time: std::time::Instant, pub(crate) last_stats: Option, @@ -567,8 +570,8 @@ impl UnknownTargetApplication { backend: Backend, camera: Camera2D, target_fps: u32, - image_rx: mpsc::UnboundedReceiver, - font_rx: mpsc::UnboundedReceiver, + #[cfg(not(target_arch = "wasm32"))] image_rx: mpsc::UnboundedReceiver, + #[cfg(not(target_arch = "wasm32"))] font_rx: mpsc::UnboundedReceiver, request_redraw: Option, options: crate::runtime::scene::RendererOptions, ) -> Self { @@ -591,7 +594,9 @@ impl UnknownTargetApplication { hit_test_result: None, hit_test_last: std::time::Instant::now(), hit_test_interval: std::time::Duration::from_millis(0), + #[cfg(not(target_arch = "wasm32"))] image_rx, + #[cfg(not(target_arch = "wasm32"))] font_rx, scheduler: scheduler::FrameScheduler::new(target_fps).with_max_fps(target_fps), last_frame_time: std::time::Instant::now(), @@ -623,7 +628,9 @@ impl UnknownTargetApplication { height: i32, options: crate::runtime::scene::RendererOptions, ) -> Box { + #[cfg(not(target_arch = "wasm32"))] let (_image_tx, image_rx) = mpsc::unbounded::(); + #[cfg(not(target_arch = "wasm32"))] let (_font_tx, font_rx) = mpsc::unbounded::(); let camera = Camera2D::new(crate::node::schema::Size { @@ -635,7 +642,16 @@ impl UnknownTargetApplication { let backend = state.backend(); Box::new(Self::new( - state, backend, camera, 120, image_rx, font_rx, None, options, + state, + backend, + camera, + 120, + #[cfg(not(target_arch = "wasm32"))] + image_rx, + #[cfg(not(target_arch = "wasm32"))] + font_rx, + None, + options, )) } @@ -789,6 +805,7 @@ impl UnknownTargetApplication { } } + #[cfg(not(target_arch = "wasm32"))] fn print_font_repository_info(&self) { let font_repo = &self.renderer.fonts; let family_count = font_repo.family_count(); diff --git a/crates/grida-canvas/src/window/application_emscripten.rs b/crates/grida-canvas/src/window/application_emscripten.rs index 37748de3f7..90bff40b63 100644 --- a/crates/grida-canvas/src/window/application_emscripten.rs +++ b/crates/grida-canvas/src/window/application_emscripten.rs @@ -1,5 +1,6 @@ use crate::io::io_grida::JSONFlattenResult; use crate::io::io_grida_patch::TransactionApplyReport; +#[cfg(not(target_arch = "wasm32"))] use crate::resources::{FontMessage, ImageMessage}; use crate::runtime::camera::Camera2D; use crate::runtime::scene::Backend; @@ -8,6 +9,7 @@ use crate::window::application::ApplicationApi; use crate::window::application::UnknownTargetApplication; use crate::window::command::ApplicationCommand; use crate::window::state::{self, GpuState, SurfaceState}; +#[cfg(not(target_arch = "wasm32"))] use futures::channel::mpsc; use math2::{rect::Rectangle, transform::AffineTransform, vector2::Vector2}; @@ -119,7 +121,9 @@ pub fn new_webgl_app( } = gpu_state; let mut state = SurfaceState::from_parts(context, framebuffer_info, surface); + #[cfg(not(target_arch = "wasm32"))] let (_image_tx, image_rx) = mpsc::unbounded::(); + #[cfg(not(target_arch = "wasm32"))] let (_font_tx, font_rx) = mpsc::unbounded::(); let camera = Camera2D::new(crate::node::schema::Size { @@ -133,7 +137,9 @@ pub fn new_webgl_app( backend, camera, 120, + #[cfg(not(target_arch = "wasm32"))] image_rx, + #[cfg(not(target_arch = "wasm32"))] font_rx, None, options, @@ -303,7 +309,9 @@ impl EmscriptenApplication { } = gpu_state; let mut state = SurfaceState::from_parts(context, framebuffer_info, surface); + #[cfg(not(target_arch = "wasm32"))] let (_image_tx, image_rx) = mpsc::unbounded::(); + #[cfg(not(target_arch = "wasm32"))] let (_font_tx, font_rx) = mpsc::unbounded::(); let camera = Camera2D::new(crate::node::schema::Size { @@ -317,7 +325,9 @@ impl EmscriptenApplication { backend, camera, 120, + #[cfg(not(target_arch = "wasm32"))] image_rx, + #[cfg(not(target_arch = "wasm32"))] font_rx, None, options, @@ -336,7 +346,8 @@ impl EmscriptenApplication { return Box::from_raw(app_ptr); } - unreachable!("emscipten cannot be initialized on native") + #[cfg(not(target_os = "emscripten"))] + unreachable!("emscripten cannot be initialized on native") } pub fn redraw(&mut self) { From f81665ed5dec27717721e0de399616b5ace554a5 Mon Sep 17 00:00:00 2001 From: Universe Date: Mon, 2 Mar 2026 23:00:32 +0900 Subject: [PATCH 4/5] wasm 0.90.0-canary.9 --- crates/grida-canvas-wasm/lib/bin/grida-canvas-wasm.js | 2 +- .../grida-canvas-wasm/lib/bin/grida_canvas_wasm.wasm | 4 ++-- crates/grida-canvas-wasm/package.json | 2 +- packages/grida-canvas-sdk-render-figma/package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/crates/grida-canvas-wasm/lib/bin/grida-canvas-wasm.js b/crates/grida-canvas-wasm/lib/bin/grida-canvas-wasm.js index 4920e6db16..d675fb791f 100644 --- a/crates/grida-canvas-wasm/lib/bin/grida-canvas-wasm.js +++ b/crates/grida-canvas-wasm/lib/bin/grida-canvas-wasm.js @@ -1,2 +1,2 @@ -var createGridaCanvas=(()=>{var _scriptName=globalThis.document?.currentScript?.src;return async function(moduleArg={}){var moduleRtn;var Module=moduleArg;var ENVIRONMENT_IS_WEB=!!globalThis.window;var ENVIRONMENT_IS_WORKER=!!globalThis.WorkerGlobalScope;var ENVIRONMENT_IS_NODE=globalThis.process?.versions?.node&&globalThis.process?.type!="renderer";var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};if(typeof __filename!="undefined"){_scriptName=__filename}else{}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("node:fs");scriptDirectory=__dirname+"/";readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");return ret};if(process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{readAsync=async url=>{var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var EXITSTATUS;var isFileURI=filename=>filename.startsWith("file://");var readyPromiseResolve,readyPromiseReject;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;var HEAP64,HEAPU64;var runtimeInitialized=false;function updateMemoryViews(){var b=wasmMemory.buffer;HEAP8=new Int8Array(b);HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);HEAPF64=new Float64Array(b);HEAP64=new BigInt64Array(b);HEAPU64=new BigUint64Array(b)}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;if(!Module["noFSInit"]&&!FS.initialized)FS.init();TTY.init();wasmExports["Lg"]();FS.ignorePermissions=false}function preMain(){}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(onPostRuns)}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject?.(e);throw e}var wasmBinaryFile;function findWasmBinary(){return locateFile("grida_canvas_wasm.wasm")}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={a:wasmImports};return imports}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;assignWasmExports(wasmExports);updateMemoryViews();return wasmExports}function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(inst,mod)=>{resolve(receiveInstance(inst,mod))})})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.push(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.push(cb);var noExitRuntime=true;var stackRestore=val=>__emscripten_stack_restore(val);var stackSave=()=>_emscripten_stack_get_current();var exceptionCaught=[];var uncaughtExceptionCount=0;var ___cxa_begin_catch=ptr=>{var info=new ExceptionInfo(ptr);if(!info.get_caught()){info.set_caught(true);uncaughtExceptionCount--}info.set_rethrown(false);exceptionCaught.push(info);return ___cxa_get_exception_ptr(ptr)};var exceptionLast=0;var ___cxa_end_catch=()=>{_setThrew(0,0);var info=exceptionCaught.pop();___cxa_decrement_exception_refcount(info.excPtr);exceptionLast=0};class ExceptionInfo{constructor(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24}set_type(type){HEAPU32[this.ptr+4>>2]=type}get_type(){return HEAPU32[this.ptr+4>>2]}set_destructor(destructor){HEAPU32[this.ptr+8>>2]=destructor}get_destructor(){return HEAPU32[this.ptr+8>>2]}set_caught(caught){caught=caught?1:0;HEAP8[this.ptr+12]=caught}get_caught(){return HEAP8[this.ptr+12]!=0}set_rethrown(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13]=rethrown}get_rethrown(){return HEAP8[this.ptr+13]!=0}init(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)}set_adjusted_ptr(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr}get_adjusted_ptr(){return HEAPU32[this.ptr+16>>2]}}var setTempRet0=val=>__emscripten_tempret_set(val);var findMatchingCatch=args=>{var thrown=exceptionLast;if(!thrown){setTempRet0(0);return 0}var info=new ExceptionInfo(thrown);info.set_adjusted_ptr(thrown);var thrownType=info.get_type();if(!thrownType){setTempRet0(0);return thrown}for(var caughtType of args){if(caughtType===0||caughtType===thrownType){break}var adjusted_ptr_addr=info.ptr+16;if(___cxa_can_catch(caughtType,thrownType,adjusted_ptr_addr)){setTempRet0(caughtType);return thrown}}setTempRet0(thrownType);return thrown};var ___cxa_find_matching_catch_2=()=>findMatchingCatch([]);var ___cxa_find_matching_catch_3=arg0=>findMatchingCatch([arg0]);var ___cxa_find_matching_catch_4=(arg0,arg1)=>findMatchingCatch([arg0,arg1]);var ___cxa_rethrow=()=>{var info=exceptionCaught.pop();if(!info){abort("no exception to throw")}var ptr=info.excPtr;if(!info.get_rethrown()){exceptionCaught.push(info);info.set_rethrown(true);info.set_caught(false);uncaughtExceptionCount++}___cxa_increment_exception_refcount(ptr);exceptionLast=ptr;throw exceptionLast};var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);___cxa_increment_exception_refcount(ptr);exceptionLast=ptr;uncaughtExceptionCount++;throw exceptionLast};var ___cxa_uncaught_exceptions=()=>uncaughtExceptionCount;var ___resumeException=ptr=>{if(!exceptionLast){exceptionLast=ptr}throw exceptionLast};var syscallGetVarargI=()=>{var ret=HEAP32[+SYSCALLS.varargs>>2];SYSCALLS.varargs+=4;return ret};var syscallGetVarargP=syscallGetVarargI;var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.slice(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(p=>!!p),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.slice(0,-1)}return root+dir},basename:path=>path&&path.match(/([^\/]+|\/)\/*$/)[1],join:(...paths)=>PATH.normalize(paths.join("/")),join2:(l,r)=>PATH.normalize(l+"/"+r)};var initRandomFill=()=>{if(ENVIRONMENT_IS_NODE){var nodeCrypto=require("node:crypto");return view=>nodeCrypto.randomFillSync(view)}return view=>crypto.getRandomValues(view)};var randomFill=view=>{(randomFill=initRandomFill())(view)};var PATH_FS={resolve:(...args)=>{var resolvedPath="",resolvedAbsolute=false;for(var i=args.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?args[i]:FS.cwd();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(p=>!!p),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).slice(1);to=PATH_FS.resolve(to).slice(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i{var maxIdx=idx+maxBytesToRead;if(ignoreNul)return maxIdx;while(heapOrArray[idx]&&!(idx>=maxIdx))++idx;return idx};var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead,ignoreNul)=>{var endPtr=findStringEnd(heapOrArray,idx,maxBytesToRead,ignoreNul);if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var FS_stdin_getChar_buffer=[];var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;i++}}heap[outIdx]=0;return outIdx-startIdx};var intArrayFromString=(stringy,dontAddNull,length)=>{var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array};var FS_stdin_getChar=()=>{if(!FS_stdin_getChar_buffer.length){var result=null;if(ENVIRONMENT_IS_NODE){var BUFSIZE=256;var buf=Buffer.alloc(BUFSIZE);var bytesRead=0;var fd=process.stdin.fd;try{bytesRead=fs.readSync(fd,buf,0,BUFSIZE)}catch(e){if(e.toString().includes("EOF"))bytesRead=0;else throw e}if(bytesRead>0){result=buf.slice(0,bytesRead).toString("utf-8")}}else if(globalThis.window?.prompt){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else{}if(!result){return null}FS_stdin_getChar_buffer=intArrayFromString(result,true)}return FS_stdin_getChar_buffer.shift()};var TTY={ttys:[],init(){},shutdown(){},register(dev,ops){TTY.ttys[dev]={input:[],output:[],ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close(stream){stream.tty.ops.fsync(stream.tty)},fsync(stream){stream.tty.ops.fsync(stream.tty)},read(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i0){out(UTF8ArrayToString(tty.output));tty.output=[]}},ioctl_tcgets(tty){return{c_iflag:25856,c_oflag:5,c_cflag:191,c_lflag:35387,c_cc:[3,28,127,21,4,0,1,0,17,19,26,0,18,15,23,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},ioctl_tcsets(tty,optional_actions,data){return 0},ioctl_tiocgwinsz(tty){return[24,80]}},default_tty1_ops:{put_char(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync(tty){if(tty.output?.length>0){err(UTF8ArrayToString(tty.output));tty.output=[]}}}};var zeroMemory=(ptr,size)=>HEAPU8.fill(0,ptr,ptr+size);var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var mmapAlloc=size=>{size=alignMemory(size,65536);var ptr=_emscripten_builtin_memalign(65536,size);if(ptr)zeroMemory(ptr,size);return ptr};var MEMFS={ops_table:null,mount(mount){return MEMFS.createNode(null,"/",16895,0)},createNode(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}MEMFS.ops_table||={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}};var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.atime=node.mtime=node.ctime=Date.now();if(parent){parent.contents[name]=node;parent.atime=parent.mtime=parent.ctime=node.atime}return node},getFileDataAsTypedArray(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.atime);attr.mtime=new Date(node.mtime);attr.ctime=new Date(node.ctime);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr(node,attr){for(const key of["mode","atime","mtime","ctime"]){if(attr[key]!=null){node[key]=attr[key]}}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup(parent,name){if(!MEMFS.doesNotExistError){MEMFS.doesNotExistError=new FS.ErrnoError(44);MEMFS.doesNotExistError.stack=""}throw MEMFS.doesNotExistError},mknod(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename(old_node,new_dir,new_name){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){if(FS.isDir(old_node.mode)){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}FS.hashRemoveNode(new_node)}delete old_node.parent.contents[old_node.name];new_dir.contents[new_name]=old_node;old_node.name=new_name;new_dir.ctime=new_dir.mtime=old_node.parent.ctime=old_node.parent.mtime=Date.now()},unlink(parent,name){delete parent.contents[name];parent.ctime=parent.mtime=Date.now()},rmdir(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.ctime=parent.mtime=Date.now()},readdir(node){return[".","..",...Object.keys(node.contents)]},symlink(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+length{var flagModes={r:0,"r+":2,w:512|64|1,"w+":512|64|2,a:1024|64|1,"a+":1024|64|2};var flags=flagModes[str];if(typeof flags=="undefined"){throw new Error(`Unknown file open mode: ${str}`)}return flags};var FS_getMode=(canRead,canWrite)=>{var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode};var asyncLoad=async url=>{var arrayBuffer=await readAsync(url);return new Uint8Array(arrayBuffer)};var FS_createDataFile=(...args)=>FS.createDataFile(...args);var getUniqueRunDependency=id=>id;var runDependencies=0;var dependenciesFulfilled=null;var removeRunDependency=id=>{runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}};var addRunDependency=id=>{runDependencies++;Module["monitorRunDependencies"]?.(runDependencies)};var preloadPlugins=[];var FS_handledByPreloadPlugin=async(byteArray,fullname)=>{if(typeof Browser!="undefined")Browser.init();for(var plugin of preloadPlugins){if(plugin["canHandle"](fullname)){return plugin["handle"](byteArray,fullname)}}return byteArray};var FS_preloadFile=async(parent,name,url,canRead,canWrite,dontCreateFile,canOwn,preFinish)=>{var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);addRunDependency(dep);try{var byteArray=url;if(typeof url=="string"){byteArray=await asyncLoad(url)}byteArray=await FS_handledByPreloadPlugin(byteArray,fullname);preFinish?.();if(!dontCreateFile){FS_createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}}finally{removeRunDependency(dep)}};var FS_createPreloadedFile=(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish)=>{FS_preloadFile(parent,name,url,canRead,canWrite,dontCreateFile,canOwn,preFinish).then(onload).catch(onerror)};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,filesystems:null,syncFSRequests:0,readFiles:{},ErrnoError:class{name="ErrnoError";constructor(errno){this.errno=errno}},FSStream:class{shared={};get object(){return this.node}set object(val){this.node=val}get isRead(){return(this.flags&2097155)!==1}get isWrite(){return(this.flags&2097155)!==0}get isAppend(){return this.flags&1024}get flags(){return this.shared.flags}set flags(val){this.shared.flags=val}get position(){return this.shared.position}set position(val){this.shared.position=val}},FSNode:class{node_ops={};stream_ops={};readMode=292|73;writeMode=146;mounted=null;constructor(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.rdev=rdev;this.atime=this.mtime=this.ctime=Date.now()}get read(){return(this.mode&this.readMode)===this.readMode}set read(val){val?this.mode|=this.readMode:this.mode&=~this.readMode}get write(){return(this.mode&this.writeMode)===this.writeMode}set write(val){val?this.mode|=this.writeMode:this.mode&=~this.writeMode}get isFolder(){return FS.isDir(this.mode)}get isDevice(){return FS.isChrdev(this.mode)}},lookupPath(path,opts={}){if(!path){throw new FS.ErrnoError(44)}opts.follow_mount??=true;if(!PATH.isAbs(path)){path=FS.cwd()+"/"+path}linkloop:for(var nlinks=0;nlinks<40;nlinks++){var parts=path.split("/").filter(p=>!!p);var current=FS.root;var current_path="/";for(var i=0;i>>0)%FS.nameTable.length},hashAddNode(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode(parent,name,mode,rdev){var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode(node){FS.hashRemoveNode(node)},isRoot(node){return node===node.parent},isMountpoint(node){return!!node.mounted},isFile(mode){return(mode&61440)===32768},isDir(mode){return(mode&61440)===16384},isLink(mode){return(mode&61440)===40960},isChrdev(mode){return(mode&61440)===8192},isBlkdev(mode){return(mode&61440)===24576},isFIFO(mode){return(mode&61440)===4096},isSocket(mode){return(mode&49152)===49152},flagsToPermissionString(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions(node,perms){if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}else if(perms.includes("w")&&!(node.mode&146)){return 2}else if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup(dir){if(!FS.isDir(dir.mode))return 54;var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate(dir,name){if(!FS.isDir(dir.mode)){return 54}try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&(512|64)){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},checkOpExists(op,err){if(!op){throw new FS.ErrnoError(err)}return op},MAX_OPEN_FDS:4096,nextfd(){for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStreamChecked(fd){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}return stream},getStream:fd=>FS.streams[fd],createStream(stream,fd=-1){stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream(fd){FS.streams[fd]=null},dupStream(origStream,fd=-1){var stream=FS.createStream(origStream,fd);stream.stream_ops?.dup?.(stream);return stream},doSetAttr(stream,node,attr){var setattr=stream?.stream_ops.setattr;var arg=setattr?stream:node;setattr??=node.node_ops.setattr;FS.checkOpExists(setattr,63);setattr(arg,attr)},chrdev_stream_ops:{open(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;stream.stream_ops.open?.(stream)},llseek(){throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push(...m.mounts)}return mounts},syncfs(populate,callback){if(typeof populate=="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}for(var mount of mounts){if(mount.type.syncfs){mount.type.syncfs(mount,populate,done)}else{done(null)}}},mount(type,opts,mountpoint){var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type,opts,mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);for(var[hash,current]of Object.entries(FS.nameTable)){while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}}node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup(parent,name){return parent.node_ops.lookup(parent,name)},mknod(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name){throw new FS.ErrnoError(28)}if(name==="."||name===".."){throw new FS.ErrnoError(20)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},statfs(path){return FS.statfsNode(FS.lookupPath(path,{follow:true}).node)},statfsStream(stream){return FS.statfsNode(stream.node)},statfsNode(node){var rtn={bsize:4096,frsize:4096,blocks:1e6,bfree:5e5,bavail:5e5,files:FS.nextInode,ffree:FS.nextInode-1,fsid:42,flags:2,namelen:255};if(node.node_ops.statfs){Object.assign(rtn,node.node_ops.statfs(node.mount.opts.root))}return rtn},create(path,mode=438){mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir(path,mode=511){mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree(path,mode){var dirs=path.split("/");var d="";for(var dir of dirs){if(!dir)continue;if(d||PATH.isAbs(path))d+="/";d+=dir;try{FS.mkdir(d,mode)}catch(e){if(e.errno!=20)throw e}}},mkdev(path,mode,dev){if(typeof dev=="undefined"){dev=mode;mode=438}mode|=8192;return FS.mknod(path,mode,dev)},symlink(oldpath,newpath){if(!PATH_FS.resolve(oldpath)){throw new FS.ErrnoError(44)}var lookup=FS.lookupPath(newpath,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var newname=PATH.basename(newpath);var errCode=FS.mayCreate(parent,newname);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.symlink){throw new FS.ErrnoError(63)}return parent.node_ops.symlink(parent,newname,oldpath)},rename(old_path,new_path){var old_dirname=PATH.dirname(old_path);var new_dirname=PATH.dirname(new_path);var old_name=PATH.basename(old_path);var new_name=PATH.basename(new_path);var lookup,old_dir,new_dir;lookup=FS.lookupPath(old_path,{parent:true});old_dir=lookup.node;lookup=FS.lookupPath(new_path,{parent:true});new_dir=lookup.node;if(!old_dir||!new_dir)throw new FS.ErrnoError(44);if(old_dir.mount!==new_dir.mount){throw new FS.ErrnoError(75)}var old_node=FS.lookupNode(old_dir,old_name);var relative=PATH_FS.relative(old_path,new_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(28)}relative=PATH_FS.relative(new_path,old_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(55)}var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(old_node===new_node){return}var isdir=FS.isDir(old_node.mode);var errCode=FS.mayDelete(old_dir,old_name,isdir);if(errCode){throw new FS.ErrnoError(errCode)}errCode=new_node?FS.mayDelete(new_dir,new_name,isdir):FS.mayCreate(new_dir,new_name);if(errCode){throw new FS.ErrnoError(errCode)}if(!old_dir.node_ops.rename){throw new FS.ErrnoError(63)}if(FS.isMountpoint(old_node)||new_node&&FS.isMountpoint(new_node)){throw new FS.ErrnoError(10)}if(new_dir!==old_dir){errCode=FS.nodePermissions(old_dir,"w");if(errCode){throw new FS.ErrnoError(errCode)}}FS.hashRemoveNode(old_node);try{old_dir.node_ops.rename(old_node,new_dir,new_name);old_node.parent=new_dir}catch(e){throw e}finally{FS.hashAddNode(old_node)}},rmdir(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,true);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.rmdir){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.rmdir(parent,name);FS.destroyNode(node)},readdir(path){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;var readdir=FS.checkOpExists(node.node_ops.readdir,54);return readdir(node)},unlink(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,false);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.unlink){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.unlink(parent,name);FS.destroyNode(node)},readlink(path){var lookup=FS.lookupPath(path);var link=lookup.node;if(!link){throw new FS.ErrnoError(44)}if(!link.node_ops.readlink){throw new FS.ErrnoError(28)}return link.node_ops.readlink(link)},stat(path,dontFollow){var lookup=FS.lookupPath(path,{follow:!dontFollow});var node=lookup.node;var getattr=FS.checkOpExists(node.node_ops.getattr,63);return getattr(node)},fstat(fd){var stream=FS.getStreamChecked(fd);var node=stream.node;var getattr=stream.stream_ops.getattr;var arg=getattr?stream:node;getattr??=node.node_ops.getattr;FS.checkOpExists(getattr,63);return getattr(arg)},lstat(path){return FS.stat(path,true)},doChmod(stream,node,mode,dontFollow){FS.doSetAttr(stream,node,{mode:mode&4095|node.mode&~4095,ctime:Date.now(),dontFollow})},chmod(path,mode,dontFollow){var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}FS.doChmod(null,node,mode,dontFollow)},lchmod(path,mode){FS.chmod(path,mode,true)},fchmod(fd,mode){var stream=FS.getStreamChecked(fd);FS.doChmod(stream,stream.node,mode,false)},doChown(stream,node,dontFollow){FS.doSetAttr(stream,node,{timestamp:Date.now(),dontFollow})},chown(path,uid,gid,dontFollow){var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}FS.doChown(null,node,dontFollow)},lchown(path,uid,gid){FS.chown(path,uid,gid,true)},fchown(fd,uid,gid){var stream=FS.getStreamChecked(fd);FS.doChown(stream,stream.node,false)},doTruncate(stream,node,len){if(FS.isDir(node.mode)){throw new FS.ErrnoError(31)}if(!FS.isFile(node.mode)){throw new FS.ErrnoError(28)}var errCode=FS.nodePermissions(node,"w");if(errCode){throw new FS.ErrnoError(errCode)}FS.doSetAttr(stream,node,{size:len,timestamp:Date.now()})},truncate(path,len){if(len<0){throw new FS.ErrnoError(28)}var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:true});node=lookup.node}else{node=path}FS.doTruncate(null,node,len)},ftruncate(fd,len){var stream=FS.getStreamChecked(fd);if(len<0||(stream.flags&2097155)===0){throw new FS.ErrnoError(28)}FS.doTruncate(stream,stream.node,len)},utime(path,atime,mtime){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;var setattr=FS.checkOpExists(node.node_ops.setattr,63);setattr(node,{atime,mtime})},open(path,flags,mode=438){if(path===""){throw new FS.ErrnoError(44)}flags=typeof flags=="string"?FS_modeStringToFlags(flags):flags;if(flags&64){mode=mode&4095|32768}else{mode=0}var node;var isDirPath;if(typeof path=="object"){node=path}else{isDirPath=path.endsWith("/");var lookup=FS.lookupPath(path,{follow:!(flags&131072),noent_okay:true});node=lookup.node;path=lookup.path}var created=false;if(flags&64){if(node){if(flags&128){throw new FS.ErrnoError(20)}}else if(isDirPath){throw new FS.ErrnoError(31)}else{node=FS.mknod(path,mode|511,0);created=true}}if(!node){throw new FS.ErrnoError(44)}if(FS.isChrdev(node.mode)){flags&=~512}if(flags&65536&&!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}if(!created){var errCode=FS.mayOpen(node,flags);if(errCode){throw new FS.ErrnoError(errCode)}}if(flags&512&&!created){FS.truncate(node,0)}flags&=~(128|512|131072);var stream=FS.createStream({node,path:FS.getPath(node),flags,seekable:true,position:0,stream_ops:node.stream_ops,ungotten:[],error:false});if(stream.stream_ops.open){stream.stream_ops.open(stream)}if(created){FS.chmod(node,mode&511)}if(Module["logReadFiles"]&&!(flags&1)){if(!(path in FS.readFiles)){FS.readFiles[path]=1}}return stream},close(stream){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(stream.getdents)stream.getdents=null;try{if(stream.stream_ops.close){stream.stream_ops.close(stream)}}catch(e){throw e}finally{FS.closeStream(stream.fd)}stream.fd=null},isClosed(stream){return stream.fd===null},llseek(stream,offset,whence){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(!stream.seekable||!stream.stream_ops.llseek){throw new FS.ErrnoError(70)}if(whence!=0&&whence!=1&&whence!=2){throw new FS.ErrnoError(28)}stream.position=stream.stream_ops.llseek(stream,offset,whence);stream.ungotten=[];return stream.position},read(stream,buffer,offset,length,position){if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.read){throw new FS.ErrnoError(28)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead},write(stream,buffer,offset,length,position,canOwn){if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.write){throw new FS.ErrnoError(28)}if(stream.seekable&&stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;return bytesWritten},mmap(stream,length,position,prot,flags){if((prot&2)!==0&&(flags&2)===0&&(stream.flags&2097155)!==2){throw new FS.ErrnoError(2)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(2)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(43)}if(!length){throw new FS.ErrnoError(28)}return stream.stream_ops.mmap(stream,length,position,prot,flags)},msync(stream,buffer,offset,length,mmapFlags){if(!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},ioctl(stream,cmd,arg){if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(59)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile(path,opts={}){opts.flags=opts.flags||0;opts.encoding=opts.encoding||"binary";if(opts.encoding!=="utf8"&&opts.encoding!=="binary"){abort(`Invalid encoding type "${opts.encoding}"`)}var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding==="utf8"){buf=UTF8ArrayToString(buf)}FS.close(stream);return buf},writeFile(path,data,opts={}){opts.flags=opts.flags||577;var stream=FS.open(path,opts.flags,opts.mode);if(typeof data=="string"){data=new Uint8Array(intArrayFromString(data,true))}if(ArrayBuffer.isView(data)){FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn)}else{abort("Unsupported data type")}FS.close(stream)},cwd:()=>FS.currentPath,chdir(path){var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,"x");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories(){FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices(){FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length,llseek:()=>0});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomFill(randomBuffer);randomLeft=randomBuffer.byteLength}return randomBuffer[--randomLeft]};FS.createDevice("/dev","random",randomByte);FS.createDevice("/dev","urandom",randomByte);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories(){FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount(){var node=FS.createNode(proc_self,"fd",16895,73);node.stream_ops={llseek:MEMFS.stream_ops.llseek};node.node_ops={lookup(parent,name){var fd=+name;var stream=FS.getStreamChecked(fd);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path},id:fd+1};ret.parent=ret;return ret},readdir(){return Array.from(FS.streams.entries()).filter(([k,v])=>v).map(([k,v])=>k.toString())}};return node}},{},"/proc/self/fd")},createStandardStreams(input,output,error){if(input){FS.createDevice("/dev","stdin",input)}else{FS.symlink("/dev/tty","/dev/stdin")}if(output){FS.createDevice("/dev","stdout",null,output)}else{FS.symlink("/dev/tty","/dev/stdout")}if(error){FS.createDevice("/dev","stderr",null,error)}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1)},staticInit(){FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={MEMFS}},init(input,output,error){FS.initialized=true;input??=Module["stdin"];output??=Module["stdout"];error??=Module["stderr"];FS.createStandardStreams(input,output,error)},quit(){FS.initialized=false;for(var stream of FS.streams){if(stream){FS.close(stream)}}},findObject(path,dontResolveLastLink){var ret=FS.analyzePath(path,dontResolveLastLink);if(!ret.exists){return null}return ret.object},analyzePath(path,dontResolveLastLink){try{var lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});path=lookup.path}catch(e){}var ret={isRoot:false,exists:false,error:0,name:null,path:null,object:null,parentExists:false,parentPath:null,parentObject:null};try{var lookup=FS.lookupPath(path,{parent:true});ret.parentExists=true;ret.parentPath=lookup.path;ret.parentObject=lookup.node;ret.name=PATH.basename(path);lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});ret.exists=true;ret.path=lookup.path;ret.object=lookup.node;ret.name=lookup.node.name;ret.isRoot=lookup.path==="/"}catch(e){ret.error=e.errno}return ret},createPath(parent,path,canRead,canWrite){parent=typeof parent=="string"?parent:FS.getPath(parent);var parts=path.split("/").reverse();while(parts.length){var part=parts.pop();if(!part)continue;var current=PATH.join2(parent,part);try{FS.mkdir(current)}catch(e){if(e.errno!=20)throw e}parent=current}return current},createFile(parent,name,properties,canRead,canWrite){var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS_getMode(canRead,canWrite);return FS.create(path,mode)},createDataFile(parent,name,data,canRead,canWrite,canOwn){var path=name;if(parent){parent=typeof parent=="string"?parent:FS.getPath(parent);path=name?PATH.join2(parent,name):parent}var mode=FS_getMode(canRead,canWrite);var node=FS.create(path,mode);if(data){if(typeof data=="string"){var arr=new Array(data.length);for(var i=0,len=data.length;ithis.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]}setDataGetter(getter){this.getter=getter}cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))abort("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)abort("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)abort("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))abort("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||"",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]=="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]=="undefined")abort("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true}get length(){if(!this.lengthKnown){this.cacheLength()}return this._length}get chunkSize(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}if(globalThis.XMLHttpRequest){if(!ENVIRONMENT_IS_WORKER)abort("Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc");var lazyArray=new LazyUint8Array;var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};for(const[key,fn]of Object.entries(node.stream_ops)){stream_ops[key]=(...args)=>{FS.forceLoadFile(node);return fn(...args)}}function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr,allocated:true}};node.stream_ops=stream_ops;return node}};var UTF8ToString=(ptr,maxBytesToRead,ignoreNul)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead,ignoreNul):"";var SYSCALLS={calculateAt(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return dir+"/"+path},writeStat(buf,stat){HEAPU32[buf>>2]=stat.dev;HEAPU32[buf+4>>2]=stat.mode;HEAPU32[buf+8>>2]=stat.nlink;HEAPU32[buf+12>>2]=stat.uid;HEAPU32[buf+16>>2]=stat.gid;HEAPU32[buf+20>>2]=stat.rdev;HEAP64[buf+24>>3]=BigInt(stat.size);HEAP32[buf+32>>2]=4096;HEAP32[buf+36>>2]=stat.blocks;var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();HEAP64[buf+40>>3]=BigInt(Math.floor(atime/1e3));HEAPU32[buf+48>>2]=atime%1e3*1e3*1e3;HEAP64[buf+56>>3]=BigInt(Math.floor(mtime/1e3));HEAPU32[buf+64>>2]=mtime%1e3*1e3*1e3;HEAP64[buf+72>>3]=BigInt(Math.floor(ctime/1e3));HEAPU32[buf+80>>2]=ctime%1e3*1e3*1e3;HEAP64[buf+88>>3]=BigInt(stat.ino);return 0},writeStatFs(buf,stats){HEAPU32[buf+4>>2]=stats.bsize;HEAPU32[buf+60>>2]=stats.bsize;HEAP64[buf+8>>3]=BigInt(stats.blocks);HEAP64[buf+16>>3]=BigInt(stats.bfree);HEAP64[buf+24>>3]=BigInt(stats.bavail);HEAP64[buf+32>>3]=BigInt(stats.files);HEAP64[buf+40>>3]=BigInt(stats.ffree);HEAPU32[buf+48>>2]=stats.fsid;HEAPU32[buf+64>>2]=stats.flags;HEAPU32[buf+56>>2]=stats.namelen},doMsync(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},getStreamFromFD(fd){var stream=FS.getStreamChecked(fd);return stream},varargs:undefined,getStr(ptr){var ret=UTF8ToString(ptr);return ret}};function ___syscall_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=syscallGetVarargI();if(arg<0){return-28}while(FS.streams[arg]){arg++}var newStream;newStream=FS.dupStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=syscallGetVarargI();stream.flags|=arg;return 0}case 12:{var arg=syscallGetVarargP();var offset=0;HEAP16[arg+offset>>1]=2;return 0}case 13:case 14:return 0}return-28}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fstat64(fd,buf){try{return SYSCALLS.writeStat(buf,FS.fstat(fd))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);function ___syscall_getcwd(buf,size){try{if(size===0)return-28;var cwd=FS.cwd();var cwdLengthInBytes=lengthBytesUTF8(cwd)+1;if(size>3]=BigInt(id);HEAP64[dirp+pos+8>>3]=BigInt((idx+1)*struct_size);HEAP16[dirp+pos+16>>1]=280;HEAP8[dirp+pos+18]=type;stringToUTF8(name,dirp+pos+19,256);pos+=struct_size}FS.llseek(stream,idx*struct_size,0);return pos}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:{if(!stream.tty)return-59;return 0}case 21505:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcgets){var termios=stream.tty.ops.ioctl_tcgets(stream);var argp=syscallGetVarargP();HEAP32[argp>>2]=termios.c_iflag||0;HEAP32[argp+4>>2]=termios.c_oflag||0;HEAP32[argp+8>>2]=termios.c_cflag||0;HEAP32[argp+12>>2]=termios.c_lflag||0;for(var i=0;i<32;i++){HEAP8[argp+i+17]=termios.c_cc[i]||0}return 0}return 0}case 21510:case 21511:case 21512:{if(!stream.tty)return-59;return 0}case 21506:case 21507:case 21508:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcsets){var argp=syscallGetVarargP();var c_iflag=HEAP32[argp>>2];var c_oflag=HEAP32[argp+4>>2];var c_cflag=HEAP32[argp+8>>2];var c_lflag=HEAP32[argp+12>>2];var c_cc=[];for(var i=0;i<32;i++){c_cc.push(HEAP8[argp+i+17])}return stream.tty.ops.ioctl_tcsets(stream.tty,op,{c_iflag,c_oflag,c_cflag,c_lflag,c_cc})}return 0}case 21519:{if(!stream.tty)return-59;var argp=syscallGetVarargP();HEAP32[argp>>2]=0;return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21537:case 21531:{var argp=syscallGetVarargP();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tiocgwinsz){var winsize=stream.tty.ops.ioctl_tiocgwinsz(stream.tty);var argp=syscallGetVarargP();HEAP16[argp>>1]=winsize[0];HEAP16[argp+2>>1]=winsize[1]}return 0}case 21524:{if(!stream.tty)return-59;return 0}case 21515:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_lstat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.writeStat(buf,FS.lstat(path))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_newfstatat(dirfd,path,buf,flags){try{path=SYSCALLS.getStr(path);var nofollow=flags&256;var allowEmpty=flags&4096;flags=flags&~6400;path=SYSCALLS.calculateAt(dirfd,path,allowEmpty);return SYSCALLS.writeStat(buf,nofollow?FS.lstat(path):FS.stat(path))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_openat(dirfd,path,flags,varargs){SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?syscallGetVarargI():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_readlinkat(dirfd,path,buf,bufsize){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(bufsize<=0)return-28;var ret=FS.readlink(path);var len=Math.min(bufsize,lengthBytesUTF8(ret));var endChar=HEAP8[buf+len];stringToUTF8(ret,buf,bufsize+1);HEAP8[buf+len]=endChar;return len}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_stat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.writeStat(buf,FS.stat(path))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __abort_js=()=>abort("");var __emscripten_throw_longjmp=()=>{throw Infinity};var INT53_MAX=9007199254740992;var INT53_MIN=-9007199254740992;var bigintToI53Checked=num=>numINT53_MAX?NaN:Number(num);function __gmtime_js(time,tmPtr){time=bigintToI53Checked(time);var date=new Date(time*1e3);HEAP32[tmPtr>>2]=date.getUTCSeconds();HEAP32[tmPtr+4>>2]=date.getUTCMinutes();HEAP32[tmPtr+8>>2]=date.getUTCHours();HEAP32[tmPtr+12>>2]=date.getUTCDate();HEAP32[tmPtr+16>>2]=date.getUTCMonth();HEAP32[tmPtr+20>>2]=date.getUTCFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getUTCDay();var start=Date.UTC(date.getUTCFullYear(),0,1,0,0,0,0);var yday=(date.getTime()-start)/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday}function __mmap_js(len,prot,flags,fd,offset,allocated,addr){offset=bigintToI53Checked(offset);try{var stream=SYSCALLS.getStreamFromFD(fd);var res=FS.mmap(stream,len,offset,prot,flags);var ptr=res.ptr;HEAP32[allocated>>2]=res.allocated;HEAPU32[addr>>2]=ptr;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function __munmap_js(addr,len,prot,flags,fd,offset){offset=bigintToI53Checked(offset);try{var stream=SYSCALLS.getStreamFromFD(fd);if(prot&2){SYSCALLS.doMsync(addr,stream,len,flags,offset)}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __tzset_js=(timezone,daylight,std_name,dst_name)=>{var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAPU32[timezone>>2]=stdTimezoneOffset*60;HEAP32[daylight>>2]=Number(winterOffset!=summerOffset);var extractZone=timezoneOffset=>{var sign=timezoneOffset>=0?"-":"+";var absOffset=Math.abs(timezoneOffset);var hours=String(Math.floor(absOffset/60)).padStart(2,"0");var minutes=String(absOffset%60).padStart(2,"0");return`UTC${sign}${hours}${minutes}`};var winterName=extractZone(winterOffset);var summerName=extractZone(summerOffset);if(summerOffsetperformance.now();var _emscripten_date_now=()=>Date.now();var nowIsMonotonic=1;var checkWasiClock=clock_id=>clock_id>=0&&clock_id<=3;function _clock_time_get(clk_id,ignored_precision,ptime){ignored_precision=bigintToI53Checked(ignored_precision);if(!checkWasiClock(clk_id)){return 28}var now;if(clk_id===0){now=_emscripten_date_now()}else if(nowIsMonotonic){now=_emscripten_get_now()}else{return 52}var nsec=Math.round(now*1e3*1e3);HEAP64[ptime>>3]=BigInt(nsec);return 0}var getHeapMax=()=>2147483648;var _emscripten_get_heap_max=()=>getHeapMax();var GLctx;var webgl_enable_ANGLE_instanced_arrays=ctx=>{var ext=ctx.getExtension("ANGLE_instanced_arrays");if(ext){ctx["vertexAttribDivisor"]=(index,divisor)=>ext["vertexAttribDivisorANGLE"](index,divisor);ctx["drawArraysInstanced"]=(mode,first,count,primcount)=>ext["drawArraysInstancedANGLE"](mode,first,count,primcount);ctx["drawElementsInstanced"]=(mode,count,type,indices,primcount)=>ext["drawElementsInstancedANGLE"](mode,count,type,indices,primcount);return 1}};var webgl_enable_OES_vertex_array_object=ctx=>{var ext=ctx.getExtension("OES_vertex_array_object");if(ext){ctx["createVertexArray"]=()=>ext["createVertexArrayOES"]();ctx["deleteVertexArray"]=vao=>ext["deleteVertexArrayOES"](vao);ctx["bindVertexArray"]=vao=>ext["bindVertexArrayOES"](vao);ctx["isVertexArray"]=vao=>ext["isVertexArrayOES"](vao);return 1}};var webgl_enable_WEBGL_draw_buffers=ctx=>{var ext=ctx.getExtension("WEBGL_draw_buffers");if(ext){ctx["drawBuffers"]=(n,bufs)=>ext["drawBuffersWEBGL"](n,bufs);return 1}};var webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance=ctx=>!!(ctx.dibvbi=ctx.getExtension("WEBGL_draw_instanced_base_vertex_base_instance"));var webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance=ctx=>!!(ctx.mdibvbi=ctx.getExtension("WEBGL_multi_draw_instanced_base_vertex_base_instance"));var webgl_enable_EXT_polygon_offset_clamp=ctx=>!!(ctx.extPolygonOffsetClamp=ctx.getExtension("EXT_polygon_offset_clamp"));var webgl_enable_EXT_clip_control=ctx=>!!(ctx.extClipControl=ctx.getExtension("EXT_clip_control"));var webgl_enable_WEBGL_polygon_mode=ctx=>!!(ctx.webglPolygonMode=ctx.getExtension("WEBGL_polygon_mode"));var webgl_enable_WEBGL_multi_draw=ctx=>!!(ctx.multiDrawWebgl=ctx.getExtension("WEBGL_multi_draw"));var getEmscriptenSupportedExtensions=ctx=>{var supportedExtensions=["ANGLE_instanced_arrays","EXT_blend_minmax","EXT_disjoint_timer_query","EXT_frag_depth","EXT_shader_texture_lod","EXT_sRGB","OES_element_index_uint","OES_fbo_render_mipmap","OES_standard_derivatives","OES_texture_float","OES_texture_half_float","OES_texture_half_float_linear","OES_vertex_array_object","WEBGL_color_buffer_float","WEBGL_depth_texture","WEBGL_draw_buffers","EXT_color_buffer_float","EXT_conservative_depth","EXT_disjoint_timer_query_webgl2","EXT_texture_norm16","NV_shader_noperspective_interpolation","WEBGL_clip_cull_distance","EXT_clip_control","EXT_color_buffer_half_float","EXT_depth_clamp","EXT_float_blend","EXT_polygon_offset_clamp","EXT_texture_compression_bptc","EXT_texture_compression_rgtc","EXT_texture_filter_anisotropic","KHR_parallel_shader_compile","OES_texture_float_linear","WEBGL_blend_func_extended","WEBGL_compressed_texture_astc","WEBGL_compressed_texture_etc","WEBGL_compressed_texture_etc1","WEBGL_compressed_texture_s3tc","WEBGL_compressed_texture_s3tc_srgb","WEBGL_debug_renderer_info","WEBGL_debug_shaders","WEBGL_lose_context","WEBGL_multi_draw","WEBGL_polygon_mode"];return(ctx.getSupportedExtensions()||[]).filter(ext=>supportedExtensions.includes(ext))};var GL={counter:1,buffers:[],programs:[],framebuffers:[],renderbuffers:[],textures:[],shaders:[],vaos:[],contexts:[],offscreenCanvases:{},queries:[],samplers:[],transformFeedbacks:[],syncs:[],stringCache:{},stringiCache:{},unpackAlignment:4,unpackRowLength:0,recordError:errorCode=>{if(!GL.lastError){GL.lastError=errorCode}},getNewId:table=>{var ret=GL.counter++;for(var i=table.length;i{for(var i=0;i>2]=id}},getSource:(shader,count,string,length)=>{var source="";for(var i=0;i>2]:undefined;source+=UTF8ToString(HEAPU32[string+i*4>>2],len)}return source},createContext:(canvas,webGLContextAttributes)=>{if(!canvas.getContextSafariWebGL2Fixed){canvas.getContextSafariWebGL2Fixed=canvas.getContext;function fixedGetContext(ver,attrs){var gl=canvas.getContextSafariWebGL2Fixed(ver,attrs);return ver=="webgl"==gl instanceof WebGLRenderingContext?gl:null}canvas.getContext=fixedGetContext}var ctx=webGLContextAttributes.majorVersion>1?canvas.getContext("webgl2",webGLContextAttributes):canvas.getContext("webgl",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:(ctx,webGLContextAttributes)=>{var handle=GL.getNewId(GL.contexts);var context={handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault=="undefined"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context)}return handle},makeContextCurrent:contextHandle=>{GL.currentContext=GL.contexts[contextHandle];Module["ctx"]=GLctx=GL.currentContext?.GLctx;return!(contextHandle&&!GLctx)},getContext:contextHandle=>GL.contexts[contextHandle],deleteContext:contextHandle=>{if(GL.currentContext===GL.contexts[contextHandle]){GL.currentContext=null}if(typeof JSEvents=="object"){JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas)}if(GL.contexts[contextHandle]?.GLctx.canvas){GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined}GL.contexts[contextHandle]=null},initExtensions:context=>{context||=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;webgl_enable_WEBGL_multi_draw(GLctx);webgl_enable_EXT_polygon_offset_clamp(GLctx);webgl_enable_EXT_clip_control(GLctx);webgl_enable_WEBGL_polygon_mode(GLctx);webgl_enable_ANGLE_instanced_arrays(GLctx);webgl_enable_OES_vertex_array_object(GLctx);webgl_enable_WEBGL_draw_buffers(GLctx);webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(GLctx);webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(GLctx);if(context.version>=2){GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query_webgl2")}if(context.version<2||!GLctx.disjointTimerQueryExt){GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query")}for(var ext of getEmscriptenSupportedExtensions(GLctx)){if(!ext.includes("lose_context")&&!ext.includes("debug")){GLctx.getExtension(ext)}}}};var _emscripten_glActiveTexture=x0=>GLctx.activeTexture(x0);var _emscripten_glAttachShader=(program,shader)=>{GLctx.attachShader(GL.programs[program],GL.shaders[shader])};var _emscripten_glBeginQuery=(target,id)=>{GLctx.beginQuery(target,GL.queries[id])};var _emscripten_glBeginQueryEXT=(target,id)=>{GLctx.disjointTimerQueryExt["beginQueryEXT"](target,GL.queries[id])};var _emscripten_glBeginTransformFeedback=x0=>GLctx.beginTransformFeedback(x0);var _emscripten_glBindAttribLocation=(program,index,name)=>{GLctx.bindAttribLocation(GL.programs[program],index,UTF8ToString(name))};var _emscripten_glBindBuffer=(target,buffer)=>{if(target==35051){GLctx.currentPixelPackBufferBinding=buffer}else if(target==35052){GLctx.currentPixelUnpackBufferBinding=buffer}GLctx.bindBuffer(target,GL.buffers[buffer])};var _emscripten_glBindBufferBase=(target,index,buffer)=>{GLctx.bindBufferBase(target,index,GL.buffers[buffer])};var _emscripten_glBindBufferRange=(target,index,buffer,offset,ptrsize)=>{GLctx.bindBufferRange(target,index,GL.buffers[buffer],offset,ptrsize)};var _emscripten_glBindFramebuffer=(target,framebuffer)=>{GLctx.bindFramebuffer(target,GL.framebuffers[framebuffer])};var _emscripten_glBindRenderbuffer=(target,renderbuffer)=>{GLctx.bindRenderbuffer(target,GL.renderbuffers[renderbuffer])};var _emscripten_glBindSampler=(unit,sampler)=>{GLctx.bindSampler(unit,GL.samplers[sampler])};var _emscripten_glBindTexture=(target,texture)=>{GLctx.bindTexture(target,GL.textures[texture])};var _emscripten_glBindTransformFeedback=(target,id)=>{GLctx.bindTransformFeedback(target,GL.transformFeedbacks[id])};var _emscripten_glBindVertexArray=vao=>{GLctx.bindVertexArray(GL.vaos[vao])};var _glBindVertexArray=_emscripten_glBindVertexArray;var _emscripten_glBindVertexArrayOES=_glBindVertexArray;var _emscripten_glBlendColor=(x0,x1,x2,x3)=>GLctx.blendColor(x0,x1,x2,x3);var _emscripten_glBlendEquation=x0=>GLctx.blendEquation(x0);var _emscripten_glBlendEquationSeparate=(x0,x1)=>GLctx.blendEquationSeparate(x0,x1);var _emscripten_glBlendFunc=(x0,x1)=>GLctx.blendFunc(x0,x1);var _emscripten_glBlendFuncSeparate=(x0,x1,x2,x3)=>GLctx.blendFuncSeparate(x0,x1,x2,x3);var _emscripten_glBlitFramebuffer=(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9)=>GLctx.blitFramebuffer(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9);var _emscripten_glBufferData=(target,size,data,usage)=>{if(GL.currentContext.version>=2){if(data&&size){GLctx.bufferData(target,HEAPU8,usage,data,size)}else{GLctx.bufferData(target,size,usage)}return}GLctx.bufferData(target,data?HEAPU8.subarray(data,data+size):size,usage)};var _emscripten_glBufferSubData=(target,offset,size,data)=>{if(GL.currentContext.version>=2){size&&GLctx.bufferSubData(target,offset,HEAPU8,data,size);return}GLctx.bufferSubData(target,offset,HEAPU8.subarray(data,data+size))};var _emscripten_glCheckFramebufferStatus=x0=>GLctx.checkFramebufferStatus(x0);var _emscripten_glClear=x0=>GLctx.clear(x0);var _emscripten_glClearBufferfi=(x0,x1,x2,x3)=>GLctx.clearBufferfi(x0,x1,x2,x3);var _emscripten_glClearBufferfv=(buffer,drawbuffer,value)=>{GLctx.clearBufferfv(buffer,drawbuffer,HEAPF32,value>>2)};var _emscripten_glClearBufferiv=(buffer,drawbuffer,value)=>{GLctx.clearBufferiv(buffer,drawbuffer,HEAP32,value>>2)};var _emscripten_glClearBufferuiv=(buffer,drawbuffer,value)=>{GLctx.clearBufferuiv(buffer,drawbuffer,HEAPU32,value>>2)};var _emscripten_glClearColor=(x0,x1,x2,x3)=>GLctx.clearColor(x0,x1,x2,x3);var _emscripten_glClearDepthf=x0=>GLctx.clearDepth(x0);var _emscripten_glClearStencil=x0=>GLctx.clearStencil(x0);var _emscripten_glClientWaitSync=(sync,flags,timeout)=>{timeout=Number(timeout);return GLctx.clientWaitSync(GL.syncs[sync],flags,timeout)};var _emscripten_glClipControlEXT=(origin,depth)=>{GLctx.extClipControl["clipControlEXT"](origin,depth)};var _emscripten_glColorMask=(red,green,blue,alpha)=>{GLctx.colorMask(!!red,!!green,!!blue,!!alpha)};var _emscripten_glCompileShader=shader=>{GLctx.compileShader(GL.shaders[shader])};var _emscripten_glCompressedTexImage2D=(target,level,internalFormat,width,height,border,imageSize,data)=>{if(GL.currentContext.version>=2){if(GLctx.currentPixelUnpackBufferBinding||!imageSize){GLctx.compressedTexImage2D(target,level,internalFormat,width,height,border,imageSize,data);return}GLctx.compressedTexImage2D(target,level,internalFormat,width,height,border,HEAPU8,data,imageSize);return}GLctx.compressedTexImage2D(target,level,internalFormat,width,height,border,HEAPU8.subarray(data,data+imageSize))};var _emscripten_glCompressedTexImage3D=(target,level,internalFormat,width,height,depth,border,imageSize,data)=>{if(GLctx.currentPixelUnpackBufferBinding){GLctx.compressedTexImage3D(target,level,internalFormat,width,height,depth,border,imageSize,data)}else{GLctx.compressedTexImage3D(target,level,internalFormat,width,height,depth,border,HEAPU8,data,imageSize)}};var _emscripten_glCompressedTexSubImage2D=(target,level,xoffset,yoffset,width,height,format,imageSize,data)=>{if(GL.currentContext.version>=2){if(GLctx.currentPixelUnpackBufferBinding||!imageSize){GLctx.compressedTexSubImage2D(target,level,xoffset,yoffset,width,height,format,imageSize,data);return}GLctx.compressedTexSubImage2D(target,level,xoffset,yoffset,width,height,format,HEAPU8,data,imageSize);return}GLctx.compressedTexSubImage2D(target,level,xoffset,yoffset,width,height,format,HEAPU8.subarray(data,data+imageSize))};var _emscripten_glCompressedTexSubImage3D=(target,level,xoffset,yoffset,zoffset,width,height,depth,format,imageSize,data)=>{if(GLctx.currentPixelUnpackBufferBinding){GLctx.compressedTexSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,imageSize,data)}else{GLctx.compressedTexSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,HEAPU8,data,imageSize)}};var _emscripten_glCopyBufferSubData=(x0,x1,x2,x3,x4)=>GLctx.copyBufferSubData(x0,x1,x2,x3,x4);var _emscripten_glCopyTexImage2D=(x0,x1,x2,x3,x4,x5,x6,x7)=>GLctx.copyTexImage2D(x0,x1,x2,x3,x4,x5,x6,x7);var _emscripten_glCopyTexSubImage2D=(x0,x1,x2,x3,x4,x5,x6,x7)=>GLctx.copyTexSubImage2D(x0,x1,x2,x3,x4,x5,x6,x7);var _emscripten_glCopyTexSubImage3D=(x0,x1,x2,x3,x4,x5,x6,x7,x8)=>GLctx.copyTexSubImage3D(x0,x1,x2,x3,x4,x5,x6,x7,x8);var _emscripten_glCreateProgram=()=>{var id=GL.getNewId(GL.programs);var program=GLctx.createProgram();program.name=id;program.maxUniformLength=program.maxAttributeLength=program.maxUniformBlockNameLength=0;program.uniformIdCounter=1;GL.programs[id]=program;return id};var _emscripten_glCreateShader=shaderType=>{var id=GL.getNewId(GL.shaders);GL.shaders[id]=GLctx.createShader(shaderType);return id};var _emscripten_glCullFace=x0=>GLctx.cullFace(x0);var _emscripten_glDeleteBuffers=(n,buffers)=>{for(var i=0;i>2];var buffer=GL.buffers[id];if(!buffer)continue;GLctx.deleteBuffer(buffer);buffer.name=0;GL.buffers[id]=null;if(id==GLctx.currentPixelPackBufferBinding)GLctx.currentPixelPackBufferBinding=0;if(id==GLctx.currentPixelUnpackBufferBinding)GLctx.currentPixelUnpackBufferBinding=0}};var _emscripten_glDeleteFramebuffers=(n,framebuffers)=>{for(var i=0;i>2];var framebuffer=GL.framebuffers[id];if(!framebuffer)continue;GLctx.deleteFramebuffer(framebuffer);framebuffer.name=0;GL.framebuffers[id]=null}};var _emscripten_glDeleteProgram=id=>{if(!id)return;var program=GL.programs[id];if(!program){GL.recordError(1281);return}GLctx.deleteProgram(program);program.name=0;GL.programs[id]=null};var _emscripten_glDeleteQueries=(n,ids)=>{for(var i=0;i>2];var query=GL.queries[id];if(!query)continue;GLctx.deleteQuery(query);GL.queries[id]=null}};var _emscripten_glDeleteQueriesEXT=(n,ids)=>{for(var i=0;i>2];var query=GL.queries[id];if(!query)continue;GLctx.disjointTimerQueryExt["deleteQueryEXT"](query);GL.queries[id]=null}};var _emscripten_glDeleteRenderbuffers=(n,renderbuffers)=>{for(var i=0;i>2];var renderbuffer=GL.renderbuffers[id];if(!renderbuffer)continue;GLctx.deleteRenderbuffer(renderbuffer);renderbuffer.name=0;GL.renderbuffers[id]=null}};var _emscripten_glDeleteSamplers=(n,samplers)=>{for(var i=0;i>2];var sampler=GL.samplers[id];if(!sampler)continue;GLctx.deleteSampler(sampler);sampler.name=0;GL.samplers[id]=null}};var _emscripten_glDeleteShader=id=>{if(!id)return;var shader=GL.shaders[id];if(!shader){GL.recordError(1281);return}GLctx.deleteShader(shader);GL.shaders[id]=null};var _emscripten_glDeleteSync=id=>{if(!id)return;var sync=GL.syncs[id];if(!sync){GL.recordError(1281);return}GLctx.deleteSync(sync);sync.name=0;GL.syncs[id]=null};var _emscripten_glDeleteTextures=(n,textures)=>{for(var i=0;i>2];var texture=GL.textures[id];if(!texture)continue;GLctx.deleteTexture(texture);texture.name=0;GL.textures[id]=null}};var _emscripten_glDeleteTransformFeedbacks=(n,ids)=>{for(var i=0;i>2];var transformFeedback=GL.transformFeedbacks[id];if(!transformFeedback)continue;GLctx.deleteTransformFeedback(transformFeedback);transformFeedback.name=0;GL.transformFeedbacks[id]=null}};var _emscripten_glDeleteVertexArrays=(n,vaos)=>{for(var i=0;i>2];GLctx.deleteVertexArray(GL.vaos[id]);GL.vaos[id]=null}};var _glDeleteVertexArrays=_emscripten_glDeleteVertexArrays;var _emscripten_glDeleteVertexArraysOES=_glDeleteVertexArrays;var _emscripten_glDepthFunc=x0=>GLctx.depthFunc(x0);var _emscripten_glDepthMask=flag=>{GLctx.depthMask(!!flag)};var _emscripten_glDepthRangef=(x0,x1)=>GLctx.depthRange(x0,x1);var _emscripten_glDetachShader=(program,shader)=>{GLctx.detachShader(GL.programs[program],GL.shaders[shader])};var _emscripten_glDisable=x0=>GLctx.disable(x0);var _emscripten_glDisableVertexAttribArray=index=>{GLctx.disableVertexAttribArray(index)};var _emscripten_glDrawArrays=(mode,first,count)=>{GLctx.drawArrays(mode,first,count)};var _emscripten_glDrawArraysInstanced=(mode,first,count,primcount)=>{GLctx.drawArraysInstanced(mode,first,count,primcount)};var _glDrawArraysInstanced=_emscripten_glDrawArraysInstanced;var _emscripten_glDrawArraysInstancedANGLE=_glDrawArraysInstanced;var _emscripten_glDrawArraysInstancedARB=_glDrawArraysInstanced;var _emscripten_glDrawArraysInstancedBaseInstanceWEBGL=(mode,first,count,instanceCount,baseInstance)=>{GLctx.dibvbi["drawArraysInstancedBaseInstanceWEBGL"](mode,first,count,instanceCount,baseInstance)};var _emscripten_glDrawArraysInstancedEXT=_glDrawArraysInstanced;var _emscripten_glDrawArraysInstancedNV=_glDrawArraysInstanced;var tempFixedLengthArray=[];var _emscripten_glDrawBuffers=(n,bufs)=>{var bufArray=tempFixedLengthArray[n];for(var i=0;i>2]}GLctx.drawBuffers(bufArray)};var _glDrawBuffers=_emscripten_glDrawBuffers;var _emscripten_glDrawBuffersEXT=_glDrawBuffers;var _emscripten_glDrawBuffersWEBGL=_glDrawBuffers;var _emscripten_glDrawElements=(mode,count,type,indices)=>{GLctx.drawElements(mode,count,type,indices)};var _emscripten_glDrawElementsInstanced=(mode,count,type,indices,primcount)=>{GLctx.drawElementsInstanced(mode,count,type,indices,primcount)};var _glDrawElementsInstanced=_emscripten_glDrawElementsInstanced;var _emscripten_glDrawElementsInstancedANGLE=_glDrawElementsInstanced;var _emscripten_glDrawElementsInstancedARB=_glDrawElementsInstanced;var _emscripten_glDrawElementsInstancedBaseVertexBaseInstanceWEBGL=(mode,count,type,offset,instanceCount,baseVertex,baseinstance)=>{GLctx.dibvbi["drawElementsInstancedBaseVertexBaseInstanceWEBGL"](mode,count,type,offset,instanceCount,baseVertex,baseinstance)};var _emscripten_glDrawElementsInstancedEXT=_glDrawElementsInstanced;var _emscripten_glDrawElementsInstancedNV=_glDrawElementsInstanced;var _glDrawElements=_emscripten_glDrawElements;var _emscripten_glDrawRangeElements=(mode,start,end,count,type,indices)=>{_glDrawElements(mode,count,type,indices)};var _emscripten_glEnable=x0=>GLctx.enable(x0);var _emscripten_glEnableVertexAttribArray=index=>{GLctx.enableVertexAttribArray(index)};var _emscripten_glEndQuery=x0=>GLctx.endQuery(x0);var _emscripten_glEndQueryEXT=target=>{GLctx.disjointTimerQueryExt["endQueryEXT"](target)};var _emscripten_glEndTransformFeedback=()=>GLctx.endTransformFeedback();var _emscripten_glFenceSync=(condition,flags)=>{var sync=GLctx.fenceSync(condition,flags);if(sync){var id=GL.getNewId(GL.syncs);sync.name=id;GL.syncs[id]=sync;return id}return 0};var _emscripten_glFinish=()=>GLctx.finish();var _emscripten_glFlush=()=>GLctx.flush();var _emscripten_glFramebufferRenderbuffer=(target,attachment,renderbuffertarget,renderbuffer)=>{GLctx.framebufferRenderbuffer(target,attachment,renderbuffertarget,GL.renderbuffers[renderbuffer])};var _emscripten_glFramebufferTexture2D=(target,attachment,textarget,texture,level)=>{GLctx.framebufferTexture2D(target,attachment,textarget,GL.textures[texture],level)};var _emscripten_glFramebufferTextureLayer=(target,attachment,texture,level,layer)=>{GLctx.framebufferTextureLayer(target,attachment,GL.textures[texture],level,layer)};var _emscripten_glFrontFace=x0=>GLctx.frontFace(x0);var _emscripten_glGenBuffers=(n,buffers)=>{GL.genObject(n,buffers,"createBuffer",GL.buffers)};var _emscripten_glGenFramebuffers=(n,ids)=>{GL.genObject(n,ids,"createFramebuffer",GL.framebuffers)};var _emscripten_glGenQueries=(n,ids)=>{GL.genObject(n,ids,"createQuery",GL.queries)};var _emscripten_glGenQueriesEXT=(n,ids)=>{for(var i=0;i>2]=0;return}var id=GL.getNewId(GL.queries);query.name=id;GL.queries[id]=query;HEAP32[ids+i*4>>2]=id}};var _emscripten_glGenRenderbuffers=(n,renderbuffers)=>{GL.genObject(n,renderbuffers,"createRenderbuffer",GL.renderbuffers)};var _emscripten_glGenSamplers=(n,samplers)=>{GL.genObject(n,samplers,"createSampler",GL.samplers)};var _emscripten_glGenTextures=(n,textures)=>{GL.genObject(n,textures,"createTexture",GL.textures)};var _emscripten_glGenTransformFeedbacks=(n,ids)=>{GL.genObject(n,ids,"createTransformFeedback",GL.transformFeedbacks)};var _emscripten_glGenVertexArrays=(n,arrays)=>{GL.genObject(n,arrays,"createVertexArray",GL.vaos)};var _glGenVertexArrays=_emscripten_glGenVertexArrays;var _emscripten_glGenVertexArraysOES=_glGenVertexArrays;var _emscripten_glGenerateMipmap=x0=>GLctx.generateMipmap(x0);var __glGetActiveAttribOrUniform=(funcName,program,index,bufSize,length,size,type,name)=>{program=GL.programs[program];var info=GLctx[funcName](program,index);if(info){var numBytesWrittenExclNull=name&&stringToUTF8(info.name,name,bufSize);if(length)HEAP32[length>>2]=numBytesWrittenExclNull;if(size)HEAP32[size>>2]=info.size;if(type)HEAP32[type>>2]=info.type}};var _emscripten_glGetActiveAttrib=(program,index,bufSize,length,size,type,name)=>__glGetActiveAttribOrUniform("getActiveAttrib",program,index,bufSize,length,size,type,name);var _emscripten_glGetActiveUniform=(program,index,bufSize,length,size,type,name)=>__glGetActiveAttribOrUniform("getActiveUniform",program,index,bufSize,length,size,type,name);var _emscripten_glGetActiveUniformBlockName=(program,uniformBlockIndex,bufSize,length,uniformBlockName)=>{program=GL.programs[program];var result=GLctx.getActiveUniformBlockName(program,uniformBlockIndex);if(!result)return;if(uniformBlockName&&bufSize>0){var numBytesWrittenExclNull=stringToUTF8(result,uniformBlockName,bufSize);if(length)HEAP32[length>>2]=numBytesWrittenExclNull}else{if(length)HEAP32[length>>2]=0}};var _emscripten_glGetActiveUniformBlockiv=(program,uniformBlockIndex,pname,params)=>{if(!params){GL.recordError(1281);return}program=GL.programs[program];if(pname==35393){var name=GLctx.getActiveUniformBlockName(program,uniformBlockIndex);HEAP32[params>>2]=name.length+1;return}var result=GLctx.getActiveUniformBlockParameter(program,uniformBlockIndex,pname);if(result===null)return;if(pname==35395){for(var i=0;i>2]=result[i]}}else{HEAP32[params>>2]=result}};var _emscripten_glGetActiveUniformsiv=(program,uniformCount,uniformIndices,pname,params)=>{if(!params){GL.recordError(1281);return}if(uniformCount>0&&uniformIndices==0){GL.recordError(1281);return}program=GL.programs[program];var ids=[];for(var i=0;i>2])}var result=GLctx.getActiveUniforms(program,ids,pname);if(!result)return;var len=result.length;for(var i=0;i>2]=result[i]}};var _emscripten_glGetAttachedShaders=(program,maxCount,count,shaders)=>{var result=GLctx.getAttachedShaders(GL.programs[program]);var len=result.length;if(len>maxCount){len=maxCount}HEAP32[count>>2]=len;for(var i=0;i>2]=id}};var _emscripten_glGetAttribLocation=(program,name)=>GLctx.getAttribLocation(GL.programs[program],UTF8ToString(name));var writeI53ToI64=(ptr,num)=>{HEAPU32[ptr>>2]=num;var lower=HEAPU32[ptr>>2];HEAPU32[ptr+4>>2]=(num-lower)/4294967296};var webglGetExtensions=()=>{var exts=getEmscriptenSupportedExtensions(GLctx);exts=exts.concat(exts.map(e=>"GL_"+e));return exts};var emscriptenWebGLGet=(name_,p,type)=>{if(!p){GL.recordError(1281);return}var ret=undefined;switch(name_){case 36346:ret=1;break;case 36344:if(type!=0&&type!=1){GL.recordError(1280)}return;case 34814:case 36345:ret=0;break;case 34466:var formats=GLctx.getParameter(34467);ret=formats?formats.length:0;break;case 33309:if(GL.currentContext.version<2){GL.recordError(1282);return}ret=webglGetExtensions().length;break;case 33307:case 33308:if(GL.currentContext.version<2){GL.recordError(1280);return}ret=name_==33307?3:0;break}if(ret===undefined){var result=GLctx.getParameter(name_);switch(typeof result){case"number":ret=result;break;case"boolean":ret=result?1:0;break;case"string":GL.recordError(1280);return;case"object":if(result===null){switch(name_){case 34964:case 35725:case 34965:case 36006:case 36007:case 32873:case 34229:case 36662:case 36663:case 35053:case 35055:case 36010:case 35097:case 35869:case 32874:case 36389:case 35983:case 35368:case 34068:{ret=0;break}default:{GL.recordError(1280);return}}}else if(result instanceof Float32Array||result instanceof Uint32Array||result instanceof Int32Array||result instanceof Array){for(var i=0;i>2]=result[i];break;case 2:HEAPF32[p+i*4>>2]=result[i];break;case 4:HEAP8[p+i]=result[i]?1:0;break}}return}else{try{ret=result.name|0}catch(e){GL.recordError(1280);err(`GL_INVALID_ENUM in glGet${type}v: Unknown object returned from WebGL getParameter(${name_})! (error: ${e})`);return}}break;default:GL.recordError(1280);err(`GL_INVALID_ENUM in glGet${type}v: Native code calling glGet${type}v(${name_}) and it returns ${result} of type ${typeof result}!`);return}}switch(type){case 1:writeI53ToI64(p,ret);break;case 0:HEAP32[p>>2]=ret;break;case 2:HEAPF32[p>>2]=ret;break;case 4:HEAP8[p]=ret?1:0;break}};var _emscripten_glGetBooleanv=(name_,p)=>emscriptenWebGLGet(name_,p,4);var _emscripten_glGetBufferParameteri64v=(target,value,data)=>{if(!data){GL.recordError(1281);return}writeI53ToI64(data,GLctx.getBufferParameter(target,value))};var _emscripten_glGetBufferParameteriv=(target,value,data)=>{if(!data){GL.recordError(1281);return}HEAP32[data>>2]=GLctx.getBufferParameter(target,value)};var _emscripten_glGetError=()=>{var error=GLctx.getError()||GL.lastError;GL.lastError=0;return error};var _emscripten_glGetFloatv=(name_,p)=>emscriptenWebGLGet(name_,p,2);var _emscripten_glGetFragDataLocation=(program,name)=>GLctx.getFragDataLocation(GL.programs[program],UTF8ToString(name));var _emscripten_glGetFramebufferAttachmentParameteriv=(target,attachment,pname,params)=>{var result=GLctx.getFramebufferAttachmentParameter(target,attachment,pname);if(result instanceof WebGLRenderbuffer||result instanceof WebGLTexture){result=result.name|0}HEAP32[params>>2]=result};var emscriptenWebGLGetIndexed=(target,index,data,type)=>{if(!data){GL.recordError(1281);return}var result=GLctx.getIndexedParameter(target,index);var ret;switch(typeof result){case"boolean":ret=result?1:0;break;case"number":ret=result;break;case"object":if(result===null){switch(target){case 35983:case 35368:ret=0;break;default:{GL.recordError(1280);return}}}else if(result instanceof WebGLBuffer){ret=result.name|0}else{GL.recordError(1280);return}break;default:GL.recordError(1280);return}switch(type){case 1:writeI53ToI64(data,ret);break;case 0:HEAP32[data>>2]=ret;break;case 2:HEAPF32[data>>2]=ret;break;case 4:HEAP8[data]=ret?1:0;break;default:abort("internal emscriptenWebGLGetIndexed() error, bad type: "+type)}};var _emscripten_glGetInteger64i_v=(target,index,data)=>emscriptenWebGLGetIndexed(target,index,data,1);var _emscripten_glGetInteger64v=(name_,p)=>{emscriptenWebGLGet(name_,p,1)};var _emscripten_glGetIntegeri_v=(target,index,data)=>emscriptenWebGLGetIndexed(target,index,data,0);var _emscripten_glGetIntegerv=(name_,p)=>emscriptenWebGLGet(name_,p,0);var _emscripten_glGetInternalformativ=(target,internalformat,pname,bufSize,params)=>{if(bufSize<0){GL.recordError(1281);return}if(!params){GL.recordError(1281);return}var ret=GLctx.getInternalformatParameter(target,internalformat,pname);if(ret===null)return;for(var i=0;i>2]=ret[i]}};var _emscripten_glGetProgramBinary=(program,bufSize,length,binaryFormat,binary)=>{GL.recordError(1282)};var _emscripten_glGetProgramInfoLog=(program,maxLength,length,infoLog)=>{var log=GLctx.getProgramInfoLog(GL.programs[program]);if(log===null)log="(unknown error)";var numBytesWrittenExclNull=maxLength>0&&infoLog?stringToUTF8(log,infoLog,maxLength):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull};var _emscripten_glGetProgramiv=(program,pname,p)=>{if(!p){GL.recordError(1281);return}if(program>=GL.counter){GL.recordError(1281);return}program=GL.programs[program];if(pname==35716){var log=GLctx.getProgramInfoLog(program);if(log===null)log="(unknown error)";HEAP32[p>>2]=log.length+1}else if(pname==35719){if(!program.maxUniformLength){var numActiveUniforms=GLctx.getProgramParameter(program,35718);for(var i=0;i>2]=program.maxUniformLength}else if(pname==35722){if(!program.maxAttributeLength){var numActiveAttributes=GLctx.getProgramParameter(program,35721);for(var i=0;i>2]=program.maxAttributeLength}else if(pname==35381){if(!program.maxUniformBlockNameLength){var numActiveUniformBlocks=GLctx.getProgramParameter(program,35382);for(var i=0;i>2]=program.maxUniformBlockNameLength}else{HEAP32[p>>2]=GLctx.getProgramParameter(program,pname)}};var _emscripten_glGetQueryObjecti64vEXT=(id,pname,params)=>{if(!params){GL.recordError(1281);return}var query=GL.queries[id];var param;if(GL.currentContext.version<2){param=GLctx.disjointTimerQueryExt["getQueryObjectEXT"](query,pname)}else{param=GLctx.getQueryParameter(query,pname)}var ret;if(typeof param=="boolean"){ret=param?1:0}else{ret=param}writeI53ToI64(params,ret)};var _emscripten_glGetQueryObjectivEXT=(id,pname,params)=>{if(!params){GL.recordError(1281);return}var query=GL.queries[id];var param=GLctx.disjointTimerQueryExt["getQueryObjectEXT"](query,pname);var ret;if(typeof param=="boolean"){ret=param?1:0}else{ret=param}HEAP32[params>>2]=ret};var _glGetQueryObjecti64vEXT=_emscripten_glGetQueryObjecti64vEXT;var _emscripten_glGetQueryObjectui64vEXT=_glGetQueryObjecti64vEXT;var _emscripten_glGetQueryObjectuiv=(id,pname,params)=>{if(!params){GL.recordError(1281);return}var query=GL.queries[id];var param=GLctx.getQueryParameter(query,pname);var ret;if(typeof param=="boolean"){ret=param?1:0}else{ret=param}HEAP32[params>>2]=ret};var _glGetQueryObjectivEXT=_emscripten_glGetQueryObjectivEXT;var _emscripten_glGetQueryObjectuivEXT=_glGetQueryObjectivEXT;var _emscripten_glGetQueryiv=(target,pname,params)=>{if(!params){GL.recordError(1281);return}HEAP32[params>>2]=GLctx.getQuery(target,pname)};var _emscripten_glGetQueryivEXT=(target,pname,params)=>{if(!params){GL.recordError(1281);return}HEAP32[params>>2]=GLctx.disjointTimerQueryExt["getQueryEXT"](target,pname)};var _emscripten_glGetRenderbufferParameteriv=(target,pname,params)=>{if(!params){GL.recordError(1281);return}HEAP32[params>>2]=GLctx.getRenderbufferParameter(target,pname)};var _emscripten_glGetSamplerParameterfv=(sampler,pname,params)=>{if(!params){GL.recordError(1281);return}HEAPF32[params>>2]=GLctx.getSamplerParameter(GL.samplers[sampler],pname)};var _emscripten_glGetSamplerParameteriv=(sampler,pname,params)=>{if(!params){GL.recordError(1281);return}HEAP32[params>>2]=GLctx.getSamplerParameter(GL.samplers[sampler],pname)};var _emscripten_glGetShaderInfoLog=(shader,maxLength,length,infoLog)=>{var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log="(unknown error)";var numBytesWrittenExclNull=maxLength>0&&infoLog?stringToUTF8(log,infoLog,maxLength):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull};var _emscripten_glGetShaderPrecisionFormat=(shaderType,precisionType,range,precision)=>{var result=GLctx.getShaderPrecisionFormat(shaderType,precisionType);HEAP32[range>>2]=result.rangeMin;HEAP32[range+4>>2]=result.rangeMax;HEAP32[precision>>2]=result.precision};var _emscripten_glGetShaderSource=(shader,bufSize,length,source)=>{var result=GLctx.getShaderSource(GL.shaders[shader]);if(!result)return;var numBytesWrittenExclNull=bufSize>0&&source?stringToUTF8(result,source,bufSize):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull};var _emscripten_glGetShaderiv=(shader,pname,p)=>{if(!p){GL.recordError(1281);return}if(pname==35716){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log="(unknown error)";var logLength=log?log.length+1:0;HEAP32[p>>2]=logLength}else if(pname==35720){var source=GLctx.getShaderSource(GL.shaders[shader]);var sourceLength=source?source.length+1:0;HEAP32[p>>2]=sourceLength}else{HEAP32[p>>2]=GLctx.getShaderParameter(GL.shaders[shader],pname)}};var stringToNewUTF8=str=>{var size=lengthBytesUTF8(str)+1;var ret=_malloc(size);if(ret)stringToUTF8(str,ret,size);return ret};var _emscripten_glGetString=name_=>{var ret=GL.stringCache[name_];if(!ret){switch(name_){case 7939:ret=stringToNewUTF8(webglGetExtensions().join(" "));break;case 7936:case 7937:case 37445:case 37446:var s=GLctx.getParameter(name_);if(!s){GL.recordError(1280)}ret=s?stringToNewUTF8(s):0;break;case 7938:var webGLVersion=GLctx.getParameter(7938);var glVersion=`OpenGL ES 2.0 (${webGLVersion})`;if(GL.currentContext.version>=2)glVersion=`OpenGL ES 3.0 (${webGLVersion})`;ret=stringToNewUTF8(glVersion);break;case 35724:var glslVersion=GLctx.getParameter(35724);var ver_re=/^WebGL GLSL ES ([0-9]\.[0-9][0-9]?)(?:$| .*)/;var ver_num=glslVersion.match(ver_re);if(ver_num!==null){if(ver_num[1].length==3)ver_num[1]=ver_num[1]+"0";glslVersion=`OpenGL ES GLSL ES ${ver_num[1]} (${glslVersion})`}ret=stringToNewUTF8(glslVersion);break;default:GL.recordError(1280)}GL.stringCache[name_]=ret}return ret};var _emscripten_glGetStringi=(name,index)=>{if(GL.currentContext.version<2){GL.recordError(1282);return 0}var stringiCache=GL.stringiCache[name];if(stringiCache){if(index<0||index>=stringiCache.length){GL.recordError(1281);return 0}return stringiCache[index]}switch(name){case 7939:var exts=webglGetExtensions().map(stringToNewUTF8);stringiCache=GL.stringiCache[name]=exts;if(index<0||index>=stringiCache.length){GL.recordError(1281);return 0}return stringiCache[index];default:GL.recordError(1280);return 0}};var _emscripten_glGetSynciv=(sync,pname,bufSize,length,values)=>{if(bufSize<0){GL.recordError(1281);return}if(!values){GL.recordError(1281);return}var ret=GLctx.getSyncParameter(GL.syncs[sync],pname);if(ret!==null){HEAP32[values>>2]=ret;if(length)HEAP32[length>>2]=1}};var _emscripten_glGetTexParameterfv=(target,pname,params)=>{if(!params){GL.recordError(1281);return}HEAPF32[params>>2]=GLctx.getTexParameter(target,pname)};var _emscripten_glGetTexParameteriv=(target,pname,params)=>{if(!params){GL.recordError(1281);return}HEAP32[params>>2]=GLctx.getTexParameter(target,pname)};var _emscripten_glGetTransformFeedbackVarying=(program,index,bufSize,length,size,type,name)=>{program=GL.programs[program];var info=GLctx.getTransformFeedbackVarying(program,index);if(!info)return;if(name&&bufSize>0){var numBytesWrittenExclNull=stringToUTF8(info.name,name,bufSize);if(length)HEAP32[length>>2]=numBytesWrittenExclNull}else{if(length)HEAP32[length>>2]=0}if(size)HEAP32[size>>2]=info.size;if(type)HEAP32[type>>2]=info.type};var _emscripten_glGetUniformBlockIndex=(program,uniformBlockName)=>GLctx.getUniformBlockIndex(GL.programs[program],UTF8ToString(uniformBlockName));var _emscripten_glGetUniformIndices=(program,uniformCount,uniformNames,uniformIndices)=>{if(!uniformIndices){GL.recordError(1281);return}if(uniformCount>0&&(uniformNames==0||uniformIndices==0)){GL.recordError(1281);return}program=GL.programs[program];var names=[];for(var i=0;i>2]));var result=GLctx.getUniformIndices(program,names);if(!result)return;var len=result.length;for(var i=0;i>2]=result[i]}};var jstoi_q=str=>parseInt(str);var webglGetLeftBracePos=name=>name.slice(-1)=="]"&&name.lastIndexOf("[");var webglPrepareUniformLocationsBeforeFirstUse=program=>{var uniformLocsById=program.uniformLocsById,uniformSizeAndIdsByName=program.uniformSizeAndIdsByName,i,j;if(!uniformLocsById){program.uniformLocsById=uniformLocsById={};program.uniformArrayNamesById={};var numActiveUniforms=GLctx.getProgramParameter(program,35718);for(i=0;i0?nm.slice(0,lb):nm;var id=program.uniformIdCounter;program.uniformIdCounter+=sz;uniformSizeAndIdsByName[arrayName]=[sz,id];for(j=0;j{name=UTF8ToString(name);if(program=GL.programs[program]){webglPrepareUniformLocationsBeforeFirstUse(program);var uniformLocsById=program.uniformLocsById;var arrayIndex=0;var uniformBaseName=name;var leftBrace=webglGetLeftBracePos(name);if(leftBrace>0){arrayIndex=jstoi_q(name.slice(leftBrace+1))>>>0;uniformBaseName=name.slice(0,leftBrace)}var sizeAndId=program.uniformSizeAndIdsByName[uniformBaseName];if(sizeAndId&&arrayIndex{var p=GLctx.currentProgram;if(p){var webglLoc=p.uniformLocsById[location];if(typeof webglLoc=="number"){p.uniformLocsById[location]=webglLoc=GLctx.getUniformLocation(p,p.uniformArrayNamesById[location]+(webglLoc>0?`[${webglLoc}]`:""))}return webglLoc}else{GL.recordError(1282)}};var emscriptenWebGLGetUniform=(program,location,params,type)=>{if(!params){GL.recordError(1281);return}program=GL.programs[program];webglPrepareUniformLocationsBeforeFirstUse(program);var data=GLctx.getUniform(program,webglGetUniformLocation(location));if(typeof data=="number"||typeof data=="boolean"){switch(type){case 0:HEAP32[params>>2]=data;break;case 2:HEAPF32[params>>2]=data;break}}else{for(var i=0;i>2]=data[i];break;case 2:HEAPF32[params+i*4>>2]=data[i];break}}}};var _emscripten_glGetUniformfv=(program,location,params)=>{emscriptenWebGLGetUniform(program,location,params,2)};var _emscripten_glGetUniformiv=(program,location,params)=>{emscriptenWebGLGetUniform(program,location,params,0)};var _emscripten_glGetUniformuiv=(program,location,params)=>emscriptenWebGLGetUniform(program,location,params,0);var emscriptenWebGLGetVertexAttrib=(index,pname,params,type)=>{if(!params){GL.recordError(1281);return}var data=GLctx.getVertexAttrib(index,pname);if(pname==34975){HEAP32[params>>2]=data&&data["name"]}else if(typeof data=="number"||typeof data=="boolean"){switch(type){case 0:HEAP32[params>>2]=data;break;case 2:HEAPF32[params>>2]=data;break;case 5:HEAP32[params>>2]=Math.fround(data);break}}else{for(var i=0;i>2]=data[i];break;case 2:HEAPF32[params+i*4>>2]=data[i];break;case 5:HEAP32[params+i*4>>2]=Math.fround(data[i]);break}}}};var _emscripten_glGetVertexAttribIiv=(index,pname,params)=>{emscriptenWebGLGetVertexAttrib(index,pname,params,0)};var _glGetVertexAttribIiv=_emscripten_glGetVertexAttribIiv;var _emscripten_glGetVertexAttribIuiv=_glGetVertexAttribIiv;var _emscripten_glGetVertexAttribPointerv=(index,pname,pointer)=>{if(!pointer){GL.recordError(1281);return}HEAP32[pointer>>2]=GLctx.getVertexAttribOffset(index,pname)};var _emscripten_glGetVertexAttribfv=(index,pname,params)=>{emscriptenWebGLGetVertexAttrib(index,pname,params,2)};var _emscripten_glGetVertexAttribiv=(index,pname,params)=>{emscriptenWebGLGetVertexAttrib(index,pname,params,5)};var _emscripten_glHint=(x0,x1)=>GLctx.hint(x0,x1);var _emscripten_glInvalidateFramebuffer=(target,numAttachments,attachments)=>{var list=tempFixedLengthArray[numAttachments];for(var i=0;i>2]}GLctx.invalidateFramebuffer(target,list)};var _emscripten_glInvalidateSubFramebuffer=(target,numAttachments,attachments,x,y,width,height)=>{var list=tempFixedLengthArray[numAttachments];for(var i=0;i>2]}GLctx.invalidateSubFramebuffer(target,list,x,y,width,height)};var _emscripten_glIsBuffer=buffer=>{var b=GL.buffers[buffer];if(!b)return 0;return GLctx.isBuffer(b)};var _emscripten_glIsEnabled=x0=>GLctx.isEnabled(x0);var _emscripten_glIsFramebuffer=framebuffer=>{var fb=GL.framebuffers[framebuffer];if(!fb)return 0;return GLctx.isFramebuffer(fb)};var _emscripten_glIsProgram=program=>{program=GL.programs[program];if(!program)return 0;return GLctx.isProgram(program)};var _emscripten_glIsQuery=id=>{var query=GL.queries[id];if(!query)return 0;return GLctx.isQuery(query)};var _emscripten_glIsQueryEXT=id=>{var query=GL.queries[id];if(!query)return 0;return GLctx.disjointTimerQueryExt["isQueryEXT"](query)};var _emscripten_glIsRenderbuffer=renderbuffer=>{var rb=GL.renderbuffers[renderbuffer];if(!rb)return 0;return GLctx.isRenderbuffer(rb)};var _emscripten_glIsSampler=id=>{var sampler=GL.samplers[id];if(!sampler)return 0;return GLctx.isSampler(sampler)};var _emscripten_glIsShader=shader=>{var s=GL.shaders[shader];if(!s)return 0;return GLctx.isShader(s)};var _emscripten_glIsSync=sync=>GLctx.isSync(GL.syncs[sync]);var _emscripten_glIsTexture=id=>{var texture=GL.textures[id];if(!texture)return 0;return GLctx.isTexture(texture)};var _emscripten_glIsTransformFeedback=id=>GLctx.isTransformFeedback(GL.transformFeedbacks[id]);var _emscripten_glIsVertexArray=array=>{var vao=GL.vaos[array];if(!vao)return 0;return GLctx.isVertexArray(vao)};var _glIsVertexArray=_emscripten_glIsVertexArray;var _emscripten_glIsVertexArrayOES=_glIsVertexArray;var _emscripten_glLineWidth=x0=>GLctx.lineWidth(x0);var _emscripten_glLinkProgram=program=>{program=GL.programs[program];GLctx.linkProgram(program);program.uniformLocsById=0;program.uniformSizeAndIdsByName={}};var _emscripten_glMultiDrawArraysInstancedBaseInstanceWEBGL=(mode,firsts,counts,instanceCounts,baseInstances,drawCount)=>{GLctx.mdibvbi["multiDrawArraysInstancedBaseInstanceWEBGL"](mode,HEAP32,firsts>>2,HEAP32,counts>>2,HEAP32,instanceCounts>>2,HEAPU32,baseInstances>>2,drawCount)};var _emscripten_glMultiDrawElementsInstancedBaseVertexBaseInstanceWEBGL=(mode,counts,type,offsets,instanceCounts,baseVertices,baseInstances,drawCount)=>{GLctx.mdibvbi["multiDrawElementsInstancedBaseVertexBaseInstanceWEBGL"](mode,HEAP32,counts>>2,type,HEAP32,offsets>>2,HEAP32,instanceCounts>>2,HEAP32,baseVertices>>2,HEAPU32,baseInstances>>2,drawCount)};var _emscripten_glPauseTransformFeedback=()=>GLctx.pauseTransformFeedback();var _emscripten_glPixelStorei=(pname,param)=>{if(pname==3317){GL.unpackAlignment=param}else if(pname==3314){GL.unpackRowLength=param}GLctx.pixelStorei(pname,param)};var _emscripten_glPolygonModeWEBGL=(face,mode)=>{GLctx.webglPolygonMode["polygonModeWEBGL"](face,mode)};var _emscripten_glPolygonOffset=(x0,x1)=>GLctx.polygonOffset(x0,x1);var _emscripten_glPolygonOffsetClampEXT=(factor,units,clamp)=>{GLctx.extPolygonOffsetClamp["polygonOffsetClampEXT"](factor,units,clamp)};var _emscripten_glProgramBinary=(program,binaryFormat,binary,length)=>{GL.recordError(1280)};var _emscripten_glProgramParameteri=(program,pname,value)=>{GL.recordError(1280)};var _emscripten_glQueryCounterEXT=(id,target)=>{GLctx.disjointTimerQueryExt["queryCounterEXT"](GL.queries[id],target)};var _emscripten_glReadBuffer=x0=>GLctx.readBuffer(x0);var computeUnpackAlignedImageSize=(width,height,sizePerPixel)=>{function roundedToNextMultipleOf(x,y){return x+y-1&-y}var plainRowSize=(GL.unpackRowLength||width)*sizePerPixel;var alignedRowSize=roundedToNextMultipleOf(plainRowSize,GL.unpackAlignment);return height*alignedRowSize};var colorChannelsInGlTextureFormat=format=>{var colorChannels={5:3,6:4,8:2,29502:3,29504:4,26917:2,26918:2,29846:3,29847:4};return colorChannels[format-6402]||1};var heapObjectForWebGLType=type=>{type-=5120;if(type==0)return HEAP8;if(type==1)return HEAPU8;if(type==2)return HEAP16;if(type==4)return HEAP32;if(type==6)return HEAPF32;if(type==5||type==28922||type==28520||type==30779||type==30782)return HEAPU32;return HEAPU16};var toTypedArrayIndex=(pointer,heap)=>pointer>>>31-Math.clz32(heap.BYTES_PER_ELEMENT);var emscriptenWebGLGetTexPixelData=(type,format,width,height,pixels,internalFormat)=>{var heap=heapObjectForWebGLType(type);var sizePerPixel=colorChannelsInGlTextureFormat(format)*heap.BYTES_PER_ELEMENT;var bytes=computeUnpackAlignedImageSize(width,height,sizePerPixel);return heap.subarray(toTypedArrayIndex(pixels,heap),toTypedArrayIndex(pixels+bytes,heap))};var _emscripten_glReadPixels=(x,y,width,height,format,type,pixels)=>{if(GL.currentContext.version>=2){if(GLctx.currentPixelPackBufferBinding){GLctx.readPixels(x,y,width,height,format,type,pixels);return}var heap=heapObjectForWebGLType(type);var target=toTypedArrayIndex(pixels,heap);GLctx.readPixels(x,y,width,height,format,type,heap,target);return}var pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,format);if(!pixelData){GL.recordError(1280);return}GLctx.readPixels(x,y,width,height,format,type,pixelData)};var _emscripten_glReleaseShaderCompiler=()=>{};var _emscripten_glRenderbufferStorage=(x0,x1,x2,x3)=>GLctx.renderbufferStorage(x0,x1,x2,x3);var _emscripten_glRenderbufferStorageMultisample=(x0,x1,x2,x3,x4)=>GLctx.renderbufferStorageMultisample(x0,x1,x2,x3,x4);var _emscripten_glResumeTransformFeedback=()=>GLctx.resumeTransformFeedback();var _emscripten_glSampleCoverage=(value,invert)=>{GLctx.sampleCoverage(value,!!invert)};var _emscripten_glSamplerParameterf=(sampler,pname,param)=>{GLctx.samplerParameterf(GL.samplers[sampler],pname,param)};var _emscripten_glSamplerParameterfv=(sampler,pname,params)=>{var param=HEAPF32[params>>2];GLctx.samplerParameterf(GL.samplers[sampler],pname,param)};var _emscripten_glSamplerParameteri=(sampler,pname,param)=>{GLctx.samplerParameteri(GL.samplers[sampler],pname,param)};var _emscripten_glSamplerParameteriv=(sampler,pname,params)=>{var param=HEAP32[params>>2];GLctx.samplerParameteri(GL.samplers[sampler],pname,param)};var _emscripten_glScissor=(x0,x1,x2,x3)=>GLctx.scissor(x0,x1,x2,x3);var _emscripten_glShaderBinary=(count,shaders,binaryformat,binary,length)=>{GL.recordError(1280)};var _emscripten_glShaderSource=(shader,count,string,length)=>{var source=GL.getSource(shader,count,string,length);GLctx.shaderSource(GL.shaders[shader],source)};var _emscripten_glStencilFunc=(x0,x1,x2)=>GLctx.stencilFunc(x0,x1,x2);var _emscripten_glStencilFuncSeparate=(x0,x1,x2,x3)=>GLctx.stencilFuncSeparate(x0,x1,x2,x3);var _emscripten_glStencilMask=x0=>GLctx.stencilMask(x0);var _emscripten_glStencilMaskSeparate=(x0,x1)=>GLctx.stencilMaskSeparate(x0,x1);var _emscripten_glStencilOp=(x0,x1,x2)=>GLctx.stencilOp(x0,x1,x2);var _emscripten_glStencilOpSeparate=(x0,x1,x2,x3)=>GLctx.stencilOpSeparate(x0,x1,x2,x3);var _emscripten_glTexImage2D=(target,level,internalFormat,width,height,border,format,type,pixels)=>{if(GL.currentContext.version>=2){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixels);return}if(pixels){var heap=heapObjectForWebGLType(type);var index=toTypedArrayIndex(pixels,heap);GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,heap,index);return}}var pixelData=pixels?emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat):null;GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixelData)};var _emscripten_glTexImage3D=(target,level,internalFormat,width,height,depth,border,format,type,pixels)=>{if(GLctx.currentPixelUnpackBufferBinding){GLctx.texImage3D(target,level,internalFormat,width,height,depth,border,format,type,pixels)}else if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texImage3D(target,level,internalFormat,width,height,depth,border,format,type,heap,toTypedArrayIndex(pixels,heap))}else{GLctx.texImage3D(target,level,internalFormat,width,height,depth,border,format,type,null)}};var _emscripten_glTexParameterf=(x0,x1,x2)=>GLctx.texParameterf(x0,x1,x2);var _emscripten_glTexParameterfv=(target,pname,params)=>{var param=HEAPF32[params>>2];GLctx.texParameterf(target,pname,param)};var _emscripten_glTexParameteri=(x0,x1,x2)=>GLctx.texParameteri(x0,x1,x2);var _emscripten_glTexParameteriv=(target,pname,params)=>{var param=HEAP32[params>>2];GLctx.texParameteri(target,pname,param)};var _emscripten_glTexStorage2D=(x0,x1,x2,x3,x4)=>GLctx.texStorage2D(x0,x1,x2,x3,x4);var _emscripten_glTexStorage3D=(x0,x1,x2,x3,x4,x5)=>GLctx.texStorage3D(x0,x1,x2,x3,x4,x5);var _emscripten_glTexSubImage2D=(target,level,xoffset,yoffset,width,height,format,type,pixels)=>{if(GL.currentContext.version>=2){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixels);return}if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,heap,toTypedArrayIndex(pixels,heap));return}}var pixelData=pixels?emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,0):null;GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixelData)};var _emscripten_glTexSubImage3D=(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,pixels)=>{if(GLctx.currentPixelUnpackBufferBinding){GLctx.texSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,pixels)}else if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,heap,toTypedArrayIndex(pixels,heap))}else{GLctx.texSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,null)}};var _emscripten_glTransformFeedbackVaryings=(program,count,varyings,bufferMode)=>{program=GL.programs[program];var vars=[];for(var i=0;i>2]));GLctx.transformFeedbackVaryings(program,vars,bufferMode)};var _emscripten_glUniform1f=(location,v0)=>{GLctx.uniform1f(webglGetUniformLocation(location),v0)};var miniTempWebGLFloatBuffers=[];var _emscripten_glUniform1fv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform1fv(webglGetUniformLocation(location),HEAPF32,value>>2,count);return}if(count<=288){var view=miniTempWebGLFloatBuffers[count];for(var i=0;i>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*4>>2)}GLctx.uniform1fv(webglGetUniformLocation(location),view)};var _emscripten_glUniform1i=(location,v0)=>{GLctx.uniform1i(webglGetUniformLocation(location),v0)};var miniTempWebGLIntBuffers=[];var _emscripten_glUniform1iv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform1iv(webglGetUniformLocation(location),HEAP32,value>>2,count);return}if(count<=288){var view=miniTempWebGLIntBuffers[count];for(var i=0;i>2]}}else{var view=HEAP32.subarray(value>>2,value+count*4>>2)}GLctx.uniform1iv(webglGetUniformLocation(location),view)};var _emscripten_glUniform1ui=(location,v0)=>{GLctx.uniform1ui(webglGetUniformLocation(location),v0)};var _emscripten_glUniform1uiv=(location,count,value)=>{count&&GLctx.uniform1uiv(webglGetUniformLocation(location),HEAPU32,value>>2,count)};var _emscripten_glUniform2f=(location,v0,v1)=>{GLctx.uniform2f(webglGetUniformLocation(location),v0,v1)};var _emscripten_glUniform2fv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform2fv(webglGetUniformLocation(location),HEAPF32,value>>2,count*2);return}if(count<=144){count*=2;var view=miniTempWebGLFloatBuffers[count];for(var i=0;i>2];view[i+1]=HEAPF32[value+(4*i+4)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*8>>2)}GLctx.uniform2fv(webglGetUniformLocation(location),view)};var _emscripten_glUniform2i=(location,v0,v1)=>{GLctx.uniform2i(webglGetUniformLocation(location),v0,v1)};var _emscripten_glUniform2iv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform2iv(webglGetUniformLocation(location),HEAP32,value>>2,count*2);return}if(count<=144){count*=2;var view=miniTempWebGLIntBuffers[count];for(var i=0;i>2];view[i+1]=HEAP32[value+(4*i+4)>>2]}}else{var view=HEAP32.subarray(value>>2,value+count*8>>2)}GLctx.uniform2iv(webglGetUniformLocation(location),view)};var _emscripten_glUniform2ui=(location,v0,v1)=>{GLctx.uniform2ui(webglGetUniformLocation(location),v0,v1)};var _emscripten_glUniform2uiv=(location,count,value)=>{count&&GLctx.uniform2uiv(webglGetUniformLocation(location),HEAPU32,value>>2,count*2)};var _emscripten_glUniform3f=(location,v0,v1,v2)=>{GLctx.uniform3f(webglGetUniformLocation(location),v0,v1,v2)};var _emscripten_glUniform3fv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform3fv(webglGetUniformLocation(location),HEAPF32,value>>2,count*3);return}if(count<=96){count*=3;var view=miniTempWebGLFloatBuffers[count];for(var i=0;i>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*12>>2)}GLctx.uniform3fv(webglGetUniformLocation(location),view)};var _emscripten_glUniform3i=(location,v0,v1,v2)=>{GLctx.uniform3i(webglGetUniformLocation(location),v0,v1,v2)};var _emscripten_glUniform3iv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform3iv(webglGetUniformLocation(location),HEAP32,value>>2,count*3);return}if(count<=96){count*=3;var view=miniTempWebGLIntBuffers[count];for(var i=0;i>2];view[i+1]=HEAP32[value+(4*i+4)>>2];view[i+2]=HEAP32[value+(4*i+8)>>2]}}else{var view=HEAP32.subarray(value>>2,value+count*12>>2)}GLctx.uniform3iv(webglGetUniformLocation(location),view)};var _emscripten_glUniform3ui=(location,v0,v1,v2)=>{GLctx.uniform3ui(webglGetUniformLocation(location),v0,v1,v2)};var _emscripten_glUniform3uiv=(location,count,value)=>{count&&GLctx.uniform3uiv(webglGetUniformLocation(location),HEAPU32,value>>2,count*3)};var _emscripten_glUniform4f=(location,v0,v1,v2,v3)=>{GLctx.uniform4f(webglGetUniformLocation(location),v0,v1,v2,v3)};var _emscripten_glUniform4fv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform4fv(webglGetUniformLocation(location),HEAPF32,value>>2,count*4);return}if(count<=72){var view=miniTempWebGLFloatBuffers[4*count];var heap=HEAPF32;value=value>>2;count*=4;for(var i=0;i>2,value+count*16>>2)}GLctx.uniform4fv(webglGetUniformLocation(location),view)};var _emscripten_glUniform4i=(location,v0,v1,v2,v3)=>{GLctx.uniform4i(webglGetUniformLocation(location),v0,v1,v2,v3)};var _emscripten_glUniform4iv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform4iv(webglGetUniformLocation(location),HEAP32,value>>2,count*4);return}if(count<=72){count*=4;var view=miniTempWebGLIntBuffers[count];for(var i=0;i>2];view[i+1]=HEAP32[value+(4*i+4)>>2];view[i+2]=HEAP32[value+(4*i+8)>>2];view[i+3]=HEAP32[value+(4*i+12)>>2]}}else{var view=HEAP32.subarray(value>>2,value+count*16>>2)}GLctx.uniform4iv(webglGetUniformLocation(location),view)};var _emscripten_glUniform4ui=(location,v0,v1,v2,v3)=>{GLctx.uniform4ui(webglGetUniformLocation(location),v0,v1,v2,v3)};var _emscripten_glUniform4uiv=(location,count,value)=>{count&&GLctx.uniform4uiv(webglGetUniformLocation(location),HEAPU32,value>>2,count*4)};var _emscripten_glUniformBlockBinding=(program,uniformBlockIndex,uniformBlockBinding)=>{program=GL.programs[program];GLctx.uniformBlockBinding(program,uniformBlockIndex,uniformBlockBinding)};var _emscripten_glUniformMatrix2fv=(location,count,transpose,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniformMatrix2fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*4);return}if(count<=72){count*=4;var view=miniTempWebGLFloatBuffers[count];for(var i=0;i>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2];view[i+3]=HEAPF32[value+(4*i+12)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*16>>2)}GLctx.uniformMatrix2fv(webglGetUniformLocation(location),!!transpose,view)};var _emscripten_glUniformMatrix2x3fv=(location,count,transpose,value)=>{count&&GLctx.uniformMatrix2x3fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*6)};var _emscripten_glUniformMatrix2x4fv=(location,count,transpose,value)=>{count&&GLctx.uniformMatrix2x4fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*8)};var _emscripten_glUniformMatrix3fv=(location,count,transpose,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniformMatrix3fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*9);return}if(count<=32){count*=9;var view=miniTempWebGLFloatBuffers[count];for(var i=0;i>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2];view[i+3]=HEAPF32[value+(4*i+12)>>2];view[i+4]=HEAPF32[value+(4*i+16)>>2];view[i+5]=HEAPF32[value+(4*i+20)>>2];view[i+6]=HEAPF32[value+(4*i+24)>>2];view[i+7]=HEAPF32[value+(4*i+28)>>2];view[i+8]=HEAPF32[value+(4*i+32)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*36>>2)}GLctx.uniformMatrix3fv(webglGetUniformLocation(location),!!transpose,view)};var _emscripten_glUniformMatrix3x2fv=(location,count,transpose,value)=>{count&&GLctx.uniformMatrix3x2fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*6)};var _emscripten_glUniformMatrix3x4fv=(location,count,transpose,value)=>{count&&GLctx.uniformMatrix3x4fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*12)};var _emscripten_glUniformMatrix4fv=(location,count,transpose,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniformMatrix4fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*16);return}if(count<=18){var view=miniTempWebGLFloatBuffers[16*count];var heap=HEAPF32;value=value>>2;count*=16;for(var i=0;i>2,value+count*64>>2)}GLctx.uniformMatrix4fv(webglGetUniformLocation(location),!!transpose,view)};var _emscripten_glUniformMatrix4x2fv=(location,count,transpose,value)=>{count&&GLctx.uniformMatrix4x2fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*8)};var _emscripten_glUniformMatrix4x3fv=(location,count,transpose,value)=>{count&&GLctx.uniformMatrix4x3fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*12)};var _emscripten_glUseProgram=program=>{program=GL.programs[program];GLctx.useProgram(program);GLctx.currentProgram=program};var _emscripten_glValidateProgram=program=>{GLctx.validateProgram(GL.programs[program])};var _emscripten_glVertexAttrib1f=(x0,x1)=>GLctx.vertexAttrib1f(x0,x1);var _emscripten_glVertexAttrib1fv=(index,v)=>{GLctx.vertexAttrib1f(index,HEAPF32[v>>2])};var _emscripten_glVertexAttrib2f=(x0,x1,x2)=>GLctx.vertexAttrib2f(x0,x1,x2);var _emscripten_glVertexAttrib2fv=(index,v)=>{GLctx.vertexAttrib2f(index,HEAPF32[v>>2],HEAPF32[v+4>>2])};var _emscripten_glVertexAttrib3f=(x0,x1,x2,x3)=>GLctx.vertexAttrib3f(x0,x1,x2,x3);var _emscripten_glVertexAttrib3fv=(index,v)=>{GLctx.vertexAttrib3f(index,HEAPF32[v>>2],HEAPF32[v+4>>2],HEAPF32[v+8>>2])};var _emscripten_glVertexAttrib4f=(x0,x1,x2,x3,x4)=>GLctx.vertexAttrib4f(x0,x1,x2,x3,x4);var _emscripten_glVertexAttrib4fv=(index,v)=>{GLctx.vertexAttrib4f(index,HEAPF32[v>>2],HEAPF32[v+4>>2],HEAPF32[v+8>>2],HEAPF32[v+12>>2])};var _emscripten_glVertexAttribDivisor=(index,divisor)=>{GLctx.vertexAttribDivisor(index,divisor)};var _glVertexAttribDivisor=_emscripten_glVertexAttribDivisor;var _emscripten_glVertexAttribDivisorANGLE=_glVertexAttribDivisor;var _emscripten_glVertexAttribDivisorARB=_glVertexAttribDivisor;var _emscripten_glVertexAttribDivisorEXT=_glVertexAttribDivisor;var _emscripten_glVertexAttribDivisorNV=_glVertexAttribDivisor;var _emscripten_glVertexAttribI4i=(x0,x1,x2,x3,x4)=>GLctx.vertexAttribI4i(x0,x1,x2,x3,x4);var _emscripten_glVertexAttribI4iv=(index,v)=>{GLctx.vertexAttribI4i(index,HEAP32[v>>2],HEAP32[v+4>>2],HEAP32[v+8>>2],HEAP32[v+12>>2])};var _emscripten_glVertexAttribI4ui=(x0,x1,x2,x3,x4)=>GLctx.vertexAttribI4ui(x0,x1,x2,x3,x4);var _emscripten_glVertexAttribI4uiv=(index,v)=>{GLctx.vertexAttribI4ui(index,HEAPU32[v>>2],HEAPU32[v+4>>2],HEAPU32[v+8>>2],HEAPU32[v+12>>2])};var _emscripten_glVertexAttribIPointer=(index,size,type,stride,ptr)=>{GLctx.vertexAttribIPointer(index,size,type,stride,ptr)};var _emscripten_glVertexAttribPointer=(index,size,type,normalized,stride,ptr)=>{GLctx.vertexAttribPointer(index,size,type,!!normalized,stride,ptr)};var _emscripten_glViewport=(x0,x1,x2,x3)=>GLctx.viewport(x0,x1,x2,x3);var _emscripten_glWaitSync=(sync,flags,timeout)=>{timeout=Number(timeout);GLctx.waitSync(GL.syncs[sync],flags,timeout)};var wasmTableMirror=[];var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func};var _emscripten_request_animation_frame_loop=(cb,userData)=>{function tick(timeStamp){if(getWasmTableEntry(cb)(timeStamp,userData)){requestAnimationFrame(tick)}}return requestAnimationFrame(tick)};var growMemory=size=>{var oldHeapSize=wasmMemory.buffer.byteLength;var pages=(size-oldHeapSize+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var ENV={};var getExecutableName=()=>thisProgram||"./this.program";var getEnvStrings=()=>{if(!getEnvStrings.strings){var lang=(globalThis.navigator?.language??"C").replace("-","_")+".UTF-8";var env={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:lang,_:getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings};var _environ_get=(__environ,environ_buf)=>{var bufSize=0;var envp=0;for(var string of getEnvStrings()){var ptr=environ_buf+bufSize;HEAPU32[__environ+envp>>2]=ptr;bufSize+=stringToUTF8(string,ptr,Infinity)+1;envp+=4}return 0};var _environ_sizes_get=(penviron_count,penviron_buf_size)=>{var strings=getEnvStrings();HEAPU32[penviron_count>>2]=strings.length;var bufSize=0;for(var string of strings){bufSize+=lengthBytesUTF8(string)+1}HEAPU32[penviron_buf_size>>2]=bufSize;return 0};var runtimeKeepaliveCounter=0;var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var _exit=exitJS;function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doReadv=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_read(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doReadv(stream,iov,iovcnt);HEAPU32[pnum>>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_seek(fd,offset,whence,newOffset){offset=bigintToI53Checked(offset);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);HEAP64[newOffset>>3]=BigInt(stream.position);if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doWritev=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var _glGetIntegerv=_emscripten_glGetIntegerv;var _glGetString=_emscripten_glGetString;var _glGetStringi=_emscripten_glGetStringi;var _llvm_eh_typeid_for=type=>type;function _random_get(buffer,size){try{randomFill(HEAPU8.subarray(buffer,buffer+size));return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var stackAlloc=sz=>__emscripten_stack_alloc(sz);var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};FS.createPreloadedFile=FS_createPreloadedFile;FS.preloadFile=FS_preloadFile;FS.staticInit();for(let i=0;i<32;++i)tempFixedLengthArray.push(new Array(i));var miniTempWebGLFloatBuffersStorage=new Float32Array(288);for(var i=0;i<=288;++i){miniTempWebGLFloatBuffers[i]=miniTempWebGLFloatBuffersStorage.subarray(0,i)}var miniTempWebGLIntBuffersStorage=new Int32Array(288);for(var i=0;i<=288;++i){miniTempWebGLIntBuffers[i]=miniTempWebGLIntBuffersStorage.subarray(0,i)}{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["preloadPlugins"])preloadPlugins=Module["preloadPlugins"];if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].shift()()}}}Module["UTF8ToString"]=UTF8ToString;Module["stringToUTF8"]=stringToUTF8;Module["lengthBytesUTF8"]=lengthBytesUTF8;Module["GL"]=GL;var _malloc,_add_font,_add_image,_add_image_with_rid,_allocate,_apply_scene_transactions,_command,_deallocate,_destroy,_devtools_rendering_set_show_fps_meter,_devtools_rendering_set_show_hit_testing,_devtools_rendering_set_show_ruler,_devtools_rendering_set_show_stats,_devtools_rendering_set_show_tiles,_export_node_as,_get_default_fallback_fonts,_get_image_bytes,_get_image_size,_get_node_absolute_bounding_box,_get_node_id_from_point,_get_node_ids_from_envelope,_get_node_ids_from_point,_grida_fonts_analyze_family,_grida_fonts_free,_grida_fonts_parse_font,_grida_markdown_to_html,_grida_svg_optimize,_grida_svg_pack,_has_missing_fonts,_highlight_strokes,_init,_init_with_backend,_list_available_fonts,_list_missing_fonts,_load_benchmark_scene,_load_dummy_scene,_load_scene_json,_pointer_move,_redraw,_resize_surface,_runtime_renderer_set_cache_tile,_runtime_renderer_set_outline_mode,_runtime_renderer_set_pixel_preview_scale,_runtime_renderer_set_pixel_preview_stable,_runtime_renderer_set_render_policy_flags,_set_debug,_set_default_fallback_fonts,_set_main_camera_transform,_set_verbose,_tick,_to_vector_network,_toggle_debug,_main,_emscripten_builtin_memalign,_setThrew,__emscripten_tempret_set,__emscripten_stack_restore,__emscripten_stack_alloc,_emscripten_stack_get_current,___cxa_decrement_exception_refcount,___cxa_increment_exception_refcount,___cxa_can_catch,___cxa_get_exception_ptr,memory,__indirect_function_table,wasmMemory,wasmTable;function assignWasmExports(wasmExports){_malloc=wasmExports["Mg"];_add_font=Module["_add_font"]=wasmExports["Og"];_add_image=Module["_add_image"]=wasmExports["Pg"];_add_image_with_rid=Module["_add_image_with_rid"]=wasmExports["Qg"];_allocate=Module["_allocate"]=wasmExports["Rg"];_apply_scene_transactions=Module["_apply_scene_transactions"]=wasmExports["Sg"];_command=Module["_command"]=wasmExports["Tg"];_deallocate=Module["_deallocate"]=wasmExports["Ug"];_destroy=Module["_destroy"]=wasmExports["Vg"];_devtools_rendering_set_show_fps_meter=Module["_devtools_rendering_set_show_fps_meter"]=wasmExports["Wg"];_devtools_rendering_set_show_hit_testing=Module["_devtools_rendering_set_show_hit_testing"]=wasmExports["Xg"];_devtools_rendering_set_show_ruler=Module["_devtools_rendering_set_show_ruler"]=wasmExports["Yg"];_devtools_rendering_set_show_stats=Module["_devtools_rendering_set_show_stats"]=wasmExports["Zg"];_devtools_rendering_set_show_tiles=Module["_devtools_rendering_set_show_tiles"]=wasmExports["_g"];_export_node_as=Module["_export_node_as"]=wasmExports["$g"];_get_default_fallback_fonts=Module["_get_default_fallback_fonts"]=wasmExports["ah"];_get_image_bytes=Module["_get_image_bytes"]=wasmExports["bh"];_get_image_size=Module["_get_image_size"]=wasmExports["ch"];_get_node_absolute_bounding_box=Module["_get_node_absolute_bounding_box"]=wasmExports["dh"];_get_node_id_from_point=Module["_get_node_id_from_point"]=wasmExports["eh"];_get_node_ids_from_envelope=Module["_get_node_ids_from_envelope"]=wasmExports["fh"];_get_node_ids_from_point=Module["_get_node_ids_from_point"]=wasmExports["gh"];_grida_fonts_analyze_family=Module["_grida_fonts_analyze_family"]=wasmExports["hh"];_grida_fonts_free=Module["_grida_fonts_free"]=wasmExports["ih"];_grida_fonts_parse_font=Module["_grida_fonts_parse_font"]=wasmExports["jh"];_grida_markdown_to_html=Module["_grida_markdown_to_html"]=wasmExports["kh"];_grida_svg_optimize=Module["_grida_svg_optimize"]=wasmExports["lh"];_grida_svg_pack=Module["_grida_svg_pack"]=wasmExports["mh"];_has_missing_fonts=Module["_has_missing_fonts"]=wasmExports["nh"];_highlight_strokes=Module["_highlight_strokes"]=wasmExports["oh"];_init=Module["_init"]=wasmExports["ph"];_init_with_backend=Module["_init_with_backend"]=wasmExports["qh"];_list_available_fonts=Module["_list_available_fonts"]=wasmExports["rh"];_list_missing_fonts=Module["_list_missing_fonts"]=wasmExports["sh"];_load_benchmark_scene=Module["_load_benchmark_scene"]=wasmExports["th"];_load_dummy_scene=Module["_load_dummy_scene"]=wasmExports["uh"];_load_scene_json=Module["_load_scene_json"]=wasmExports["vh"];_pointer_move=Module["_pointer_move"]=wasmExports["wh"];_redraw=Module["_redraw"]=wasmExports["xh"];_resize_surface=Module["_resize_surface"]=wasmExports["yh"];_runtime_renderer_set_cache_tile=Module["_runtime_renderer_set_cache_tile"]=wasmExports["zh"];_runtime_renderer_set_outline_mode=Module["_runtime_renderer_set_outline_mode"]=wasmExports["Ah"];_runtime_renderer_set_pixel_preview_scale=Module["_runtime_renderer_set_pixel_preview_scale"]=wasmExports["Bh"];_runtime_renderer_set_pixel_preview_stable=Module["_runtime_renderer_set_pixel_preview_stable"]=wasmExports["Ch"];_runtime_renderer_set_render_policy_flags=Module["_runtime_renderer_set_render_policy_flags"]=wasmExports["Dh"];_set_debug=Module["_set_debug"]=wasmExports["Eh"];_set_default_fallback_fonts=Module["_set_default_fallback_fonts"]=wasmExports["Fh"];_set_main_camera_transform=Module["_set_main_camera_transform"]=wasmExports["Gh"];_set_verbose=Module["_set_verbose"]=wasmExports["Hh"];_tick=Module["_tick"]=wasmExports["Ih"];_to_vector_network=Module["_to_vector_network"]=wasmExports["Jh"];_toggle_debug=Module["_toggle_debug"]=wasmExports["Kh"];_main=Module["_main"]=wasmExports["Lh"];_emscripten_builtin_memalign=wasmExports["Mh"];_setThrew=wasmExports["Nh"];__emscripten_tempret_set=wasmExports["Oh"];__emscripten_stack_restore=wasmExports["Ph"];__emscripten_stack_alloc=wasmExports["Qh"];_emscripten_stack_get_current=wasmExports["Rh"];___cxa_decrement_exception_refcount=wasmExports["Sh"];___cxa_increment_exception_refcount=wasmExports["Th"];___cxa_can_catch=wasmExports["Uh"];___cxa_get_exception_ptr=wasmExports["Vh"];memory=wasmMemory=wasmExports["Kg"];__indirect_function_table=wasmTable=wasmExports["Ng"]}var wasmImports={F:___cxa_begin_catch,M:___cxa_end_catch,a:___cxa_find_matching_catch_2,n:___cxa_find_matching_catch_3,ca:___cxa_find_matching_catch_4,za:___cxa_rethrow,G:___cxa_throw,db:___cxa_uncaught_exceptions,e:___resumeException,Ca:___syscall_fcntl64,xb:___syscall_fstat64,tb:___syscall_getcwd,kb:___syscall_getdents64,yb:___syscall_ioctl,ub:___syscall_lstat64,vb:___syscall_newfstatat,Da:___syscall_openat,jb:___syscall_readlinkat,wb:___syscall_stat64,Bb:__abort_js,fb:__emscripten_throw_longjmp,ob:__gmtime_js,mb:__mmap_js,nb:__munmap_js,Cb:__tzset_js,Ab:_clock_time_get,zb:_emscripten_date_now,ib:_emscripten_get_heap_max,aa:_emscripten_get_now,Df:_emscripten_glActiveTexture,Ef:_emscripten_glAttachShader,ge:_emscripten_glBeginQuery,ae:_emscripten_glBeginQueryEXT,Hc:_emscripten_glBeginTransformFeedback,Ff:_emscripten_glBindAttribLocation,Gf:_emscripten_glBindBuffer,Ec:_emscripten_glBindBufferBase,Fc:_emscripten_glBindBufferRange,Ee:_emscripten_glBindFramebuffer,Fe:_emscripten_glBindRenderbuffer,me:_emscripten_glBindSampler,Hf:_emscripten_glBindTexture,Ub:_emscripten_glBindTransformFeedback,_e:_emscripten_glBindVertexArray,bf:_emscripten_glBindVertexArrayOES,If:_emscripten_glBlendColor,Jf:_emscripten_glBlendEquation,Md:_emscripten_glBlendEquationSeparate,Kf:_emscripten_glBlendFunc,Ld:_emscripten_glBlendFuncSeparate,ye:_emscripten_glBlitFramebuffer,Lf:_emscripten_glBufferData,Mf:_emscripten_glBufferSubData,Ge:_emscripten_glCheckFramebufferStatus,Of:_emscripten_glClear,hc:_emscripten_glClearBufferfi,ic:_emscripten_glClearBufferfv,kc:_emscripten_glClearBufferiv,jc:_emscripten_glClearBufferuiv,Pf:_emscripten_glClearColor,Kd:_emscripten_glClearDepthf,Qf:_emscripten_glClearStencil,ve:_emscripten_glClientWaitSync,bd:_emscripten_glClipControlEXT,Rf:_emscripten_glColorMask,Sf:_emscripten_glCompileShader,Tf:_emscripten_glCompressedTexImage2D,Uc:_emscripten_glCompressedTexImage3D,Uf:_emscripten_glCompressedTexSubImage2D,Tc:_emscripten_glCompressedTexSubImage3D,xe:_emscripten_glCopyBufferSubData,Jd:_emscripten_glCopyTexImage2D,Vf:_emscripten_glCopyTexSubImage2D,Vc:_emscripten_glCopyTexSubImage3D,Wf:_emscripten_glCreateProgram,Xf:_emscripten_glCreateShader,Yf:_emscripten_glCullFace,Zf:_emscripten_glDeleteBuffers,He:_emscripten_glDeleteFramebuffers,_f:_emscripten_glDeleteProgram,he:_emscripten_glDeleteQueries,be:_emscripten_glDeleteQueriesEXT,Ie:_emscripten_glDeleteRenderbuffers,ne:_emscripten_glDeleteSamplers,$f:_emscripten_glDeleteShader,we:_emscripten_glDeleteSync,ag:_emscripten_glDeleteTextures,Tb:_emscripten_glDeleteTransformFeedbacks,$e:_emscripten_glDeleteVertexArrays,cf:_emscripten_glDeleteVertexArraysOES,Id:_emscripten_glDepthFunc,bg:_emscripten_glDepthMask,Hd:_emscripten_glDepthRangef,Gd:_emscripten_glDetachShader,cg:_emscripten_glDisable,dg:_emscripten_glDisableVertexAttribArray,eg:_emscripten_glDrawArrays,Ye:_emscripten_glDrawArraysInstanced,Pd:_emscripten_glDrawArraysInstancedANGLE,Fb:_emscripten_glDrawArraysInstancedARB,Ve:_emscripten_glDrawArraysInstancedBaseInstanceWEBGL,_c:_emscripten_glDrawArraysInstancedEXT,Gb:_emscripten_glDrawArraysInstancedNV,Te:_emscripten_glDrawBuffers,Yc:_emscripten_glDrawBuffersEXT,Qd:_emscripten_glDrawBuffersWEBGL,fg:_emscripten_glDrawElements,Ze:_emscripten_glDrawElementsInstanced,Od:_emscripten_glDrawElementsInstancedANGLE,Db:_emscripten_glDrawElementsInstancedARB,We:_emscripten_glDrawElementsInstancedBaseVertexBaseInstanceWEBGL,Eb:_emscripten_glDrawElementsInstancedEXT,Zc:_emscripten_glDrawElementsInstancedNV,Ne:_emscripten_glDrawRangeElements,gg:_emscripten_glEnable,hg:_emscripten_glEnableVertexAttribArray,ie:_emscripten_glEndQuery,ce:_emscripten_glEndQueryEXT,Gc:_emscripten_glEndTransformFeedback,se:_emscripten_glFenceSync,ig:_emscripten_glFinish,jg:_emscripten_glFlush,Je:_emscripten_glFramebufferRenderbuffer,Ke:_emscripten_glFramebufferTexture2D,Kc:_emscripten_glFramebufferTextureLayer,kg:_emscripten_glFrontFace,lg:_emscripten_glGenBuffers,Le:_emscripten_glGenFramebuffers,je:_emscripten_glGenQueries,de:_emscripten_glGenQueriesEXT,Me:_emscripten_glGenRenderbuffers,oe:_emscripten_glGenSamplers,mg:_emscripten_glGenTextures,Sb:_emscripten_glGenTransformFeedbacks,Xe:_emscripten_glGenVertexArrays,df:_emscripten_glGenVertexArraysOES,Ae:_emscripten_glGenerateMipmap,Fd:_emscripten_glGetActiveAttrib,Ed:_emscripten_glGetActiveUniform,cc:_emscripten_glGetActiveUniformBlockName,dc:_emscripten_glGetActiveUniformBlockiv,fc:_emscripten_glGetActiveUniformsiv,Dd:_emscripten_glGetAttachedShaders,Cd:_emscripten_glGetAttribLocation,Bd:_emscripten_glGetBooleanv,Zb:_emscripten_glGetBufferParameteri64v,ng:_emscripten_glGetBufferParameteriv,og:_emscripten_glGetError,pg:_emscripten_glGetFloatv,uc:_emscripten_glGetFragDataLocation,Be:_emscripten_glGetFramebufferAttachmentParameteriv,_b:_emscripten_glGetInteger64i_v,ac:_emscripten_glGetInteger64v,Ic:_emscripten_glGetIntegeri_v,qg:_emscripten_glGetIntegerv,Jb:_emscripten_glGetInternalformativ,Nb:_emscripten_glGetProgramBinary,rg:_emscripten_glGetProgramInfoLog,sg:_emscripten_glGetProgramiv,Zd:_emscripten_glGetQueryObjecti64vEXT,Sd:_emscripten_glGetQueryObjectivEXT,_d:_emscripten_glGetQueryObjectui64vEXT,ke:_emscripten_glGetQueryObjectuiv,ee:_emscripten_glGetQueryObjectuivEXT,le:_emscripten_glGetQueryiv,fe:_emscripten_glGetQueryivEXT,Ce:_emscripten_glGetRenderbufferParameteriv,Vb:_emscripten_glGetSamplerParameterfv,Wb:_emscripten_glGetSamplerParameteriv,tg:_emscripten_glGetShaderInfoLog,Wd:_emscripten_glGetShaderPrecisionFormat,Ad:_emscripten_glGetShaderSource,ug:_emscripten_glGetShaderiv,vg:_emscripten_glGetString,af:_emscripten_glGetStringi,$b:_emscripten_glGetSynciv,zd:_emscripten_glGetTexParameterfv,yd:_emscripten_glGetTexParameteriv,Cc:_emscripten_glGetTransformFeedbackVarying,ec:_emscripten_glGetUniformBlockIndex,gc:_emscripten_glGetUniformIndices,wg:_emscripten_glGetUniformLocation,xd:_emscripten_glGetUniformfv,wd:_emscripten_glGetUniformiv,vc:_emscripten_glGetUniformuiv,Bc:_emscripten_glGetVertexAttribIiv,Ac:_emscripten_glGetVertexAttribIuiv,td:_emscripten_glGetVertexAttribPointerv,vd:_emscripten_glGetVertexAttribfv,ud:_emscripten_glGetVertexAttribiv,sd:_emscripten_glHint,Xd:_emscripten_glInvalidateFramebuffer,Yd:_emscripten_glInvalidateSubFramebuffer,rd:_emscripten_glIsBuffer,qd:_emscripten_glIsEnabled,pd:_emscripten_glIsFramebuffer,od:_emscripten_glIsProgram,Sc:_emscripten_glIsQuery,Td:_emscripten_glIsQueryEXT,nd:_emscripten_glIsRenderbuffer,Yb:_emscripten_glIsSampler,md:_emscripten_glIsShader,te:_emscripten_glIsSync,xg:_emscripten_glIsTexture,Rb:_emscripten_glIsTransformFeedback,Jc:_emscripten_glIsVertexArray,Rd:_emscripten_glIsVertexArrayOES,yg:_emscripten_glLineWidth,zg:_emscripten_glLinkProgram,Re:_emscripten_glMultiDrawArraysInstancedBaseInstanceWEBGL,Se:_emscripten_glMultiDrawElementsInstancedBaseVertexBaseInstanceWEBGL,Qb:_emscripten_glPauseTransformFeedback,Ag:_emscripten_glPixelStorei,ad:_emscripten_glPolygonModeWEBGL,ld:_emscripten_glPolygonOffset,cd:_emscripten_glPolygonOffsetClampEXT,Mb:_emscripten_glProgramBinary,Lb:_emscripten_glProgramParameteri,$d:_emscripten_glQueryCounterEXT,Ue:_emscripten_glReadBuffer,Bg:_emscripten_glReadPixels,kd:_emscripten_glReleaseShaderCompiler,De:_emscripten_glRenderbufferStorage,ze:_emscripten_glRenderbufferStorageMultisample,Ob:_emscripten_glResumeTransformFeedback,jd:_emscripten_glSampleCoverage,pe:_emscripten_glSamplerParameterf,Xb:_emscripten_glSamplerParameterfv,qe:_emscripten_glSamplerParameteri,re:_emscripten_glSamplerParameteriv,Cg:_emscripten_glScissor,id:_emscripten_glShaderBinary,Dg:_emscripten_glShaderSource,Eg:_emscripten_glStencilFunc,Fg:_emscripten_glStencilFuncSeparate,Gg:_emscripten_glStencilMask,Hg:_emscripten_glStencilMaskSeparate,Ig:_emscripten_glStencilOp,Jg:_emscripten_glStencilOpSeparate,Ia:_emscripten_glTexImage2D,Xc:_emscripten_glTexImage3D,Ja:_emscripten_glTexParameterf,Ka:_emscripten_glTexParameterfv,La:_emscripten_glTexParameteri,Ma:_emscripten_glTexParameteriv,Oe:_emscripten_glTexStorage2D,Kb:_emscripten_glTexStorage3D,Na:_emscripten_glTexSubImage2D,Wc:_emscripten_glTexSubImage3D,Dc:_emscripten_glTransformFeedbackVaryings,Oa:_emscripten_glUniform1f,Pa:_emscripten_glUniform1fv,zf:_emscripten_glUniform1i,Af:_emscripten_glUniform1iv,tc:_emscripten_glUniform1ui,oc:_emscripten_glUniform1uiv,Bf:_emscripten_glUniform2f,Cf:_emscripten_glUniform2fv,yf:_emscripten_glUniform2i,xf:_emscripten_glUniform2iv,rc:_emscripten_glUniform2ui,nc:_emscripten_glUniform2uiv,wf:_emscripten_glUniform3f,vf:_emscripten_glUniform3fv,uf:_emscripten_glUniform3i,tf:_emscripten_glUniform3iv,qc:_emscripten_glUniform3ui,mc:_emscripten_glUniform3uiv,sf:_emscripten_glUniform4f,rf:_emscripten_glUniform4fv,ef:_emscripten_glUniform4i,ff:_emscripten_glUniform4iv,pc:_emscripten_glUniform4ui,lc:_emscripten_glUniform4uiv,bc:_emscripten_glUniformBlockBinding,gf:_emscripten_glUniformMatrix2fv,Rc:_emscripten_glUniformMatrix2x3fv,Pc:_emscripten_glUniformMatrix2x4fv,hf:_emscripten_glUniformMatrix3fv,Qc:_emscripten_glUniformMatrix3x2fv,Mc:_emscripten_glUniformMatrix3x4fv,jf:_emscripten_glUniformMatrix4fv,Oc:_emscripten_glUniformMatrix4x2fv,Lc:_emscripten_glUniformMatrix4x3fv,kf:_emscripten_glUseProgram,hd:_emscripten_glValidateProgram,lf:_emscripten_glVertexAttrib1f,gd:_emscripten_glVertexAttrib1fv,fd:_emscripten_glVertexAttrib2f,mf:_emscripten_glVertexAttrib2fv,ed:_emscripten_glVertexAttrib3f,nf:_emscripten_glVertexAttrib3fv,dd:_emscripten_glVertexAttrib4f,of:_emscripten_glVertexAttrib4fv,Pe:_emscripten_glVertexAttribDivisor,Nd:_emscripten_glVertexAttribDivisorANGLE,Hb:_emscripten_glVertexAttribDivisorARB,$c:_emscripten_glVertexAttribDivisorEXT,Ib:_emscripten_glVertexAttribDivisorNV,zc:_emscripten_glVertexAttribI4i,xc:_emscripten_glVertexAttribI4iv,yc:_emscripten_glVertexAttribI4ui,wc:_emscripten_glVertexAttribI4uiv,Qe:_emscripten_glVertexAttribIPointer,pf:_emscripten_glVertexAttribPointer,qf:_emscripten_glViewport,ue:_emscripten_glWaitSync,_a:_emscripten_request_animation_frame_loop,gb:_emscripten_resize_heap,qb:_environ_get,rb:_environ_sizes_get,Sa:_exit,ba:_fd_close,lb:_fd_pread,Aa:_fd_read,pb:_fd_seek,ga:_fd_write,Qa:_glGetIntegerv,la:_glGetString,Ra:_glGetStringi,Ud:invoke_dd,Vd:invoke_dddd,xa:invoke_diii,Va:invoke_fdiiii,Ua:invoke_fdiiiii,Ta:invoke_fii,ya:invoke_fiii,s:invoke_fiiidi,S:invoke_fiiif,t:invoke_fiiiidi,r:invoke_i,j:invoke_ii,qa:invoke_iif,hb:invoke_iiffi,na:invoke_iiffiii,h:invoke_iii,Ga:invoke_iiiffii,f:invoke_iiii,l:invoke_iiiii,cb:invoke_iiiiid,y:invoke_iiiiii,x:invoke_iiiiiii,D:invoke_iiiiiiii,q:invoke_iiiiiiiii,ma:invoke_iiiiiiiiii,Z:invoke_iiiiiiiiiiii,ja:invoke_iiiiiiiiiiiifiii,pa:invoke_iijj,eb:invoke_j,T:invoke_ji,W:invoke_jiii,_:invoke_jiiii,H:invoke_jjji,k:invoke_v,Nf:invoke_vff,b:invoke_vi,Q:invoke_vid,P:invoke_vif,u:invoke_viff,B:invoke_viffff,V:invoke_vifffff,Wa:invoke_viffffff,A:invoke_viffi,ea:invoke_viffiiiiiii,c:invoke_vii,Za:invoke_viidii,N:invoke_viif,E:invoke_viiff,wa:invoke_viififii,v:invoke_viifiiifi,d:invoke_viii,ka:invoke_viiif,z:invoke_viiiffi,I:invoke_viiiffiffii,Nc:invoke_viiifi,J:invoke_viiififiiiiiiiiiiii,i:invoke_viiii,Ya:invoke_viiiidididii,ha:invoke_viiiif,Ea:invoke_viiiiff,ta:invoke_viiiiffi,Ba:invoke_viiiifi,g:invoke_viiiii,Pb:invoke_viiiiif,Fa:invoke_viiiiiff,Xa:invoke_viiiiiffiii,$a:invoke_viiiiifi,m:invoke_viiiiii,p:invoke_viiiiiii,O:invoke_viiiiiiii,U:invoke_viiiiiiiii,L:invoke_viiiiiiiiii,oa:invoke_viiiiiiiiiii,Y:invoke_viiiiiiiiiiiiiii,Ha:invoke_viiiiiji,ab:invoke_viiiijjiiiiff,K:invoke_viiij,w:invoke_viiijii,da:invoke_viij,o:invoke_viiji,fa:invoke_viijiff,X:invoke_viijiiiif,ra:invoke_viijj,R:invoke_vij,va:invoke_vijff,bb:invoke_viji,C:invoke_vijii,ua:invoke_vijiifi,sa:invoke_vijiii,$:invoke_vijjjj,sc:invoke_vjii,ia:_llvm_eh_typeid_for,sb:_random_get};function invoke_vii(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vi(index,a1){var sp=stackSave();try{getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_ii(index,a1){var sp=stackSave();try{return getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiii(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viii(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iii(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_v(index){var sp=stackSave();try{getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_ji(index,a1){var sp=stackSave();try{return getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0);return 0n}}function invoke_viiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiij(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vij(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vff(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viij(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiji(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiff(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiif(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiji(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiffii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiff(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vid(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiiifiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vif(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viffi(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiifi(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiff(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vjii(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiffi(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viifiiifi(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiif(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiif(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiifi(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiffi(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viififii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viijiff(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijff(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viji(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiijjiiiiff(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijiifi(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiffi(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijii(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiifi(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viijj(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiififiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viijiiiif(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiffiffii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iif(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_jjji(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0);return 0n}}function invoke_iijj(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viif(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_jiii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0);return 0n}}function invoke_iiiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiffiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viff(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vifffff(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiiidi(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viidii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiidididii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiiiidi(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiffiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiijii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viffff(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viffffff(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiiif(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fdiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fdiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fii(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viffiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_dddd(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_dd(index,a1){var sp=stackSave();try{return getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijjjj(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_j(index){var sp=stackSave();try{return getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0);return 0n}}function invoke_iiiiid(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_jiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0);return 0n}}function invoke_fiii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_diii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_i(index){var sp=stackSave();try{return getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function callMain(args=[]){var entryFunction=_main;args.unshift(thisProgram);var argc=args.length;var argv=stackAlloc((argc+1)*4);var argv_ptr=argv;for(var arg of args){HEAPU32[argv_ptr>>2]=stringToUTF8OnStack(arg);argv_ptr+=4}HEAPU32[argv_ptr>>2]=0;try{var ret=entryFunction(argc,argv);exitJS(ret,true);return ret}catch(e){return handleException(e)}}function run(args=arguments_){if(runDependencies>0){dependenciesFulfilled=run;return}preRun();if(runDependencies>0){dependenciesFulfilled=run;return}function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();readyPromiseResolve?.(Module);Module["onRuntimeInitialized"]?.();var noInitialRun=Module["noInitialRun"]||false;if(!noInitialRun)callMain(args);postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}var wasmExports;wasmExports=await (createWasm());run();if(runtimeInitialized){moduleRtn=Module}else{moduleRtn=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject})} +var createGridaCanvas=(()=>{var _scriptName=globalThis.document?.currentScript?.src;return async function(moduleArg={}){var moduleRtn;var Module=moduleArg;var ENVIRONMENT_IS_WEB=!!globalThis.window;var ENVIRONMENT_IS_WORKER=!!globalThis.WorkerGlobalScope;var ENVIRONMENT_IS_NODE=globalThis.process?.versions?.node&&globalThis.process?.type!="renderer";var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};if(typeof __filename!="undefined"){_scriptName=__filename}else{}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("node:fs");scriptDirectory=__dirname+"/";readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");return ret};if(process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{readAsync=async url=>{var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var EXITSTATUS;var isFileURI=filename=>filename.startsWith("file://");var readyPromiseResolve,readyPromiseReject;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;var HEAP64,HEAPU64;var runtimeInitialized=false;function updateMemoryViews(){var b=wasmMemory.buffer;HEAP8=new Int8Array(b);HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);HEAPF64=new Float64Array(b);HEAP64=new BigInt64Array(b);HEAPU64=new BigUint64Array(b)}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;if(!Module["noFSInit"]&&!FS.initialized)FS.init();TTY.init();wasmExports["Kg"]();FS.ignorePermissions=false}function preMain(){}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(onPostRuns)}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject?.(e);throw e}var wasmBinaryFile;function findWasmBinary(){return locateFile("grida_canvas_wasm.wasm")}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={a:wasmImports};return imports}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;assignWasmExports(wasmExports);updateMemoryViews();return wasmExports}function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(inst,mod)=>{resolve(receiveInstance(inst,mod))})})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.push(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.push(cb);var noExitRuntime=true;var stackRestore=val=>__emscripten_stack_restore(val);var stackSave=()=>_emscripten_stack_get_current();var exceptionCaught=[];var uncaughtExceptionCount=0;var ___cxa_begin_catch=ptr=>{var info=new ExceptionInfo(ptr);if(!info.get_caught()){info.set_caught(true);uncaughtExceptionCount--}info.set_rethrown(false);exceptionCaught.push(info);return ___cxa_get_exception_ptr(ptr)};var exceptionLast=0;var ___cxa_end_catch=()=>{_setThrew(0,0);var info=exceptionCaught.pop();___cxa_decrement_exception_refcount(info.excPtr);exceptionLast=0};class ExceptionInfo{constructor(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24}set_type(type){HEAPU32[this.ptr+4>>2]=type}get_type(){return HEAPU32[this.ptr+4>>2]}set_destructor(destructor){HEAPU32[this.ptr+8>>2]=destructor}get_destructor(){return HEAPU32[this.ptr+8>>2]}set_caught(caught){caught=caught?1:0;HEAP8[this.ptr+12]=caught}get_caught(){return HEAP8[this.ptr+12]!=0}set_rethrown(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13]=rethrown}get_rethrown(){return HEAP8[this.ptr+13]!=0}init(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)}set_adjusted_ptr(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr}get_adjusted_ptr(){return HEAPU32[this.ptr+16>>2]}}var setTempRet0=val=>__emscripten_tempret_set(val);var findMatchingCatch=args=>{var thrown=exceptionLast;if(!thrown){setTempRet0(0);return 0}var info=new ExceptionInfo(thrown);info.set_adjusted_ptr(thrown);var thrownType=info.get_type();if(!thrownType){setTempRet0(0);return thrown}for(var caughtType of args){if(caughtType===0||caughtType===thrownType){break}var adjusted_ptr_addr=info.ptr+16;if(___cxa_can_catch(caughtType,thrownType,adjusted_ptr_addr)){setTempRet0(caughtType);return thrown}}setTempRet0(thrownType);return thrown};var ___cxa_find_matching_catch_2=()=>findMatchingCatch([]);var ___cxa_find_matching_catch_3=arg0=>findMatchingCatch([arg0]);var ___cxa_find_matching_catch_4=(arg0,arg1)=>findMatchingCatch([arg0,arg1]);var ___cxa_rethrow=()=>{var info=exceptionCaught.pop();if(!info){abort("no exception to throw")}var ptr=info.excPtr;if(!info.get_rethrown()){exceptionCaught.push(info);info.set_rethrown(true);info.set_caught(false);uncaughtExceptionCount++}___cxa_increment_exception_refcount(ptr);exceptionLast=ptr;throw exceptionLast};var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);___cxa_increment_exception_refcount(ptr);exceptionLast=ptr;uncaughtExceptionCount++;throw exceptionLast};var ___cxa_uncaught_exceptions=()=>uncaughtExceptionCount;var ___resumeException=ptr=>{if(!exceptionLast){exceptionLast=ptr}throw exceptionLast};var syscallGetVarargI=()=>{var ret=HEAP32[+SYSCALLS.varargs>>2];SYSCALLS.varargs+=4;return ret};var syscallGetVarargP=syscallGetVarargI;var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.slice(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(p=>!!p),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.slice(0,-1)}return root+dir},basename:path=>path&&path.match(/([^\/]+|\/)\/*$/)[1],join:(...paths)=>PATH.normalize(paths.join("/")),join2:(l,r)=>PATH.normalize(l+"/"+r)};var initRandomFill=()=>{if(ENVIRONMENT_IS_NODE){var nodeCrypto=require("node:crypto");return view=>nodeCrypto.randomFillSync(view)}return view=>crypto.getRandomValues(view)};var randomFill=view=>{(randomFill=initRandomFill())(view)};var PATH_FS={resolve:(...args)=>{var resolvedPath="",resolvedAbsolute=false;for(var i=args.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?args[i]:FS.cwd();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(p=>!!p),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).slice(1);to=PATH_FS.resolve(to).slice(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i{var maxIdx=idx+maxBytesToRead;if(ignoreNul)return maxIdx;while(heapOrArray[idx]&&!(idx>=maxIdx))++idx;return idx};var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead,ignoreNul)=>{var endPtr=findStringEnd(heapOrArray,idx,maxBytesToRead,ignoreNul);if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var FS_stdin_getChar_buffer=[];var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;i++}}heap[outIdx]=0;return outIdx-startIdx};var intArrayFromString=(stringy,dontAddNull,length)=>{var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array};var FS_stdin_getChar=()=>{if(!FS_stdin_getChar_buffer.length){var result=null;if(ENVIRONMENT_IS_NODE){var BUFSIZE=256;var buf=Buffer.alloc(BUFSIZE);var bytesRead=0;var fd=process.stdin.fd;try{bytesRead=fs.readSync(fd,buf,0,BUFSIZE)}catch(e){if(e.toString().includes("EOF"))bytesRead=0;else throw e}if(bytesRead>0){result=buf.slice(0,bytesRead).toString("utf-8")}}else if(globalThis.window?.prompt){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else{}if(!result){return null}FS_stdin_getChar_buffer=intArrayFromString(result,true)}return FS_stdin_getChar_buffer.shift()};var TTY={ttys:[],init(){},shutdown(){},register(dev,ops){TTY.ttys[dev]={input:[],output:[],ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close(stream){stream.tty.ops.fsync(stream.tty)},fsync(stream){stream.tty.ops.fsync(stream.tty)},read(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i0){out(UTF8ArrayToString(tty.output));tty.output=[]}},ioctl_tcgets(tty){return{c_iflag:25856,c_oflag:5,c_cflag:191,c_lflag:35387,c_cc:[3,28,127,21,4,0,1,0,17,19,26,0,18,15,23,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},ioctl_tcsets(tty,optional_actions,data){return 0},ioctl_tiocgwinsz(tty){return[24,80]}},default_tty1_ops:{put_char(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync(tty){if(tty.output?.length>0){err(UTF8ArrayToString(tty.output));tty.output=[]}}}};var zeroMemory=(ptr,size)=>HEAPU8.fill(0,ptr,ptr+size);var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var mmapAlloc=size=>{size=alignMemory(size,65536);var ptr=_emscripten_builtin_memalign(65536,size);if(ptr)zeroMemory(ptr,size);return ptr};var MEMFS={ops_table:null,mount(mount){return MEMFS.createNode(null,"/",16895,0)},createNode(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}MEMFS.ops_table||={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}};var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.atime=node.mtime=node.ctime=Date.now();if(parent){parent.contents[name]=node;parent.atime=parent.mtime=parent.ctime=node.atime}return node},getFileDataAsTypedArray(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.atime);attr.mtime=new Date(node.mtime);attr.ctime=new Date(node.ctime);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr(node,attr){for(const key of["mode","atime","mtime","ctime"]){if(attr[key]!=null){node[key]=attr[key]}}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup(parent,name){if(!MEMFS.doesNotExistError){MEMFS.doesNotExistError=new FS.ErrnoError(44);MEMFS.doesNotExistError.stack=""}throw MEMFS.doesNotExistError},mknod(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename(old_node,new_dir,new_name){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){if(FS.isDir(old_node.mode)){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}FS.hashRemoveNode(new_node)}delete old_node.parent.contents[old_node.name];new_dir.contents[new_name]=old_node;old_node.name=new_name;new_dir.ctime=new_dir.mtime=old_node.parent.ctime=old_node.parent.mtime=Date.now()},unlink(parent,name){delete parent.contents[name];parent.ctime=parent.mtime=Date.now()},rmdir(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.ctime=parent.mtime=Date.now()},readdir(node){return[".","..",...Object.keys(node.contents)]},symlink(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+length{var flagModes={r:0,"r+":2,w:512|64|1,"w+":512|64|2,a:1024|64|1,"a+":1024|64|2};var flags=flagModes[str];if(typeof flags=="undefined"){throw new Error(`Unknown file open mode: ${str}`)}return flags};var FS_getMode=(canRead,canWrite)=>{var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode};var asyncLoad=async url=>{var arrayBuffer=await readAsync(url);return new Uint8Array(arrayBuffer)};var FS_createDataFile=(...args)=>FS.createDataFile(...args);var getUniqueRunDependency=id=>id;var runDependencies=0;var dependenciesFulfilled=null;var removeRunDependency=id=>{runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}};var addRunDependency=id=>{runDependencies++;Module["monitorRunDependencies"]?.(runDependencies)};var preloadPlugins=[];var FS_handledByPreloadPlugin=async(byteArray,fullname)=>{if(typeof Browser!="undefined")Browser.init();for(var plugin of preloadPlugins){if(plugin["canHandle"](fullname)){return plugin["handle"](byteArray,fullname)}}return byteArray};var FS_preloadFile=async(parent,name,url,canRead,canWrite,dontCreateFile,canOwn,preFinish)=>{var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);addRunDependency(dep);try{var byteArray=url;if(typeof url=="string"){byteArray=await asyncLoad(url)}byteArray=await FS_handledByPreloadPlugin(byteArray,fullname);preFinish?.();if(!dontCreateFile){FS_createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}}finally{removeRunDependency(dep)}};var FS_createPreloadedFile=(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish)=>{FS_preloadFile(parent,name,url,canRead,canWrite,dontCreateFile,canOwn,preFinish).then(onload).catch(onerror)};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,filesystems:null,syncFSRequests:0,readFiles:{},ErrnoError:class{name="ErrnoError";constructor(errno){this.errno=errno}},FSStream:class{shared={};get object(){return this.node}set object(val){this.node=val}get isRead(){return(this.flags&2097155)!==1}get isWrite(){return(this.flags&2097155)!==0}get isAppend(){return this.flags&1024}get flags(){return this.shared.flags}set flags(val){this.shared.flags=val}get position(){return this.shared.position}set position(val){this.shared.position=val}},FSNode:class{node_ops={};stream_ops={};readMode=292|73;writeMode=146;mounted=null;constructor(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.rdev=rdev;this.atime=this.mtime=this.ctime=Date.now()}get read(){return(this.mode&this.readMode)===this.readMode}set read(val){val?this.mode|=this.readMode:this.mode&=~this.readMode}get write(){return(this.mode&this.writeMode)===this.writeMode}set write(val){val?this.mode|=this.writeMode:this.mode&=~this.writeMode}get isFolder(){return FS.isDir(this.mode)}get isDevice(){return FS.isChrdev(this.mode)}},lookupPath(path,opts={}){if(!path){throw new FS.ErrnoError(44)}opts.follow_mount??=true;if(!PATH.isAbs(path)){path=FS.cwd()+"/"+path}linkloop:for(var nlinks=0;nlinks<40;nlinks++){var parts=path.split("/").filter(p=>!!p);var current=FS.root;var current_path="/";for(var i=0;i>>0)%FS.nameTable.length},hashAddNode(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode(parent,name,mode,rdev){var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode(node){FS.hashRemoveNode(node)},isRoot(node){return node===node.parent},isMountpoint(node){return!!node.mounted},isFile(mode){return(mode&61440)===32768},isDir(mode){return(mode&61440)===16384},isLink(mode){return(mode&61440)===40960},isChrdev(mode){return(mode&61440)===8192},isBlkdev(mode){return(mode&61440)===24576},isFIFO(mode){return(mode&61440)===4096},isSocket(mode){return(mode&49152)===49152},flagsToPermissionString(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions(node,perms){if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}else if(perms.includes("w")&&!(node.mode&146)){return 2}else if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup(dir){if(!FS.isDir(dir.mode))return 54;var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate(dir,name){if(!FS.isDir(dir.mode)){return 54}try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&(512|64)){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},checkOpExists(op,err){if(!op){throw new FS.ErrnoError(err)}return op},MAX_OPEN_FDS:4096,nextfd(){for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStreamChecked(fd){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}return stream},getStream:fd=>FS.streams[fd],createStream(stream,fd=-1){stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream(fd){FS.streams[fd]=null},dupStream(origStream,fd=-1){var stream=FS.createStream(origStream,fd);stream.stream_ops?.dup?.(stream);return stream},doSetAttr(stream,node,attr){var setattr=stream?.stream_ops.setattr;var arg=setattr?stream:node;setattr??=node.node_ops.setattr;FS.checkOpExists(setattr,63);setattr(arg,attr)},chrdev_stream_ops:{open(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;stream.stream_ops.open?.(stream)},llseek(){throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push(...m.mounts)}return mounts},syncfs(populate,callback){if(typeof populate=="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}for(var mount of mounts){if(mount.type.syncfs){mount.type.syncfs(mount,populate,done)}else{done(null)}}},mount(type,opts,mountpoint){var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type,opts,mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);for(var[hash,current]of Object.entries(FS.nameTable)){while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}}node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup(parent,name){return parent.node_ops.lookup(parent,name)},mknod(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name){throw new FS.ErrnoError(28)}if(name==="."||name===".."){throw new FS.ErrnoError(20)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},statfs(path){return FS.statfsNode(FS.lookupPath(path,{follow:true}).node)},statfsStream(stream){return FS.statfsNode(stream.node)},statfsNode(node){var rtn={bsize:4096,frsize:4096,blocks:1e6,bfree:5e5,bavail:5e5,files:FS.nextInode,ffree:FS.nextInode-1,fsid:42,flags:2,namelen:255};if(node.node_ops.statfs){Object.assign(rtn,node.node_ops.statfs(node.mount.opts.root))}return rtn},create(path,mode=438){mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir(path,mode=511){mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree(path,mode){var dirs=path.split("/");var d="";for(var dir of dirs){if(!dir)continue;if(d||PATH.isAbs(path))d+="/";d+=dir;try{FS.mkdir(d,mode)}catch(e){if(e.errno!=20)throw e}}},mkdev(path,mode,dev){if(typeof dev=="undefined"){dev=mode;mode=438}mode|=8192;return FS.mknod(path,mode,dev)},symlink(oldpath,newpath){if(!PATH_FS.resolve(oldpath)){throw new FS.ErrnoError(44)}var lookup=FS.lookupPath(newpath,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var newname=PATH.basename(newpath);var errCode=FS.mayCreate(parent,newname);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.symlink){throw new FS.ErrnoError(63)}return parent.node_ops.symlink(parent,newname,oldpath)},rename(old_path,new_path){var old_dirname=PATH.dirname(old_path);var new_dirname=PATH.dirname(new_path);var old_name=PATH.basename(old_path);var new_name=PATH.basename(new_path);var lookup,old_dir,new_dir;lookup=FS.lookupPath(old_path,{parent:true});old_dir=lookup.node;lookup=FS.lookupPath(new_path,{parent:true});new_dir=lookup.node;if(!old_dir||!new_dir)throw new FS.ErrnoError(44);if(old_dir.mount!==new_dir.mount){throw new FS.ErrnoError(75)}var old_node=FS.lookupNode(old_dir,old_name);var relative=PATH_FS.relative(old_path,new_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(28)}relative=PATH_FS.relative(new_path,old_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(55)}var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(old_node===new_node){return}var isdir=FS.isDir(old_node.mode);var errCode=FS.mayDelete(old_dir,old_name,isdir);if(errCode){throw new FS.ErrnoError(errCode)}errCode=new_node?FS.mayDelete(new_dir,new_name,isdir):FS.mayCreate(new_dir,new_name);if(errCode){throw new FS.ErrnoError(errCode)}if(!old_dir.node_ops.rename){throw new FS.ErrnoError(63)}if(FS.isMountpoint(old_node)||new_node&&FS.isMountpoint(new_node)){throw new FS.ErrnoError(10)}if(new_dir!==old_dir){errCode=FS.nodePermissions(old_dir,"w");if(errCode){throw new FS.ErrnoError(errCode)}}FS.hashRemoveNode(old_node);try{old_dir.node_ops.rename(old_node,new_dir,new_name);old_node.parent=new_dir}catch(e){throw e}finally{FS.hashAddNode(old_node)}},rmdir(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,true);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.rmdir){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.rmdir(parent,name);FS.destroyNode(node)},readdir(path){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;var readdir=FS.checkOpExists(node.node_ops.readdir,54);return readdir(node)},unlink(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,false);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.unlink){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.unlink(parent,name);FS.destroyNode(node)},readlink(path){var lookup=FS.lookupPath(path);var link=lookup.node;if(!link){throw new FS.ErrnoError(44)}if(!link.node_ops.readlink){throw new FS.ErrnoError(28)}return link.node_ops.readlink(link)},stat(path,dontFollow){var lookup=FS.lookupPath(path,{follow:!dontFollow});var node=lookup.node;var getattr=FS.checkOpExists(node.node_ops.getattr,63);return getattr(node)},fstat(fd){var stream=FS.getStreamChecked(fd);var node=stream.node;var getattr=stream.stream_ops.getattr;var arg=getattr?stream:node;getattr??=node.node_ops.getattr;FS.checkOpExists(getattr,63);return getattr(arg)},lstat(path){return FS.stat(path,true)},doChmod(stream,node,mode,dontFollow){FS.doSetAttr(stream,node,{mode:mode&4095|node.mode&~4095,ctime:Date.now(),dontFollow})},chmod(path,mode,dontFollow){var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}FS.doChmod(null,node,mode,dontFollow)},lchmod(path,mode){FS.chmod(path,mode,true)},fchmod(fd,mode){var stream=FS.getStreamChecked(fd);FS.doChmod(stream,stream.node,mode,false)},doChown(stream,node,dontFollow){FS.doSetAttr(stream,node,{timestamp:Date.now(),dontFollow})},chown(path,uid,gid,dontFollow){var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}FS.doChown(null,node,dontFollow)},lchown(path,uid,gid){FS.chown(path,uid,gid,true)},fchown(fd,uid,gid){var stream=FS.getStreamChecked(fd);FS.doChown(stream,stream.node,false)},doTruncate(stream,node,len){if(FS.isDir(node.mode)){throw new FS.ErrnoError(31)}if(!FS.isFile(node.mode)){throw new FS.ErrnoError(28)}var errCode=FS.nodePermissions(node,"w");if(errCode){throw new FS.ErrnoError(errCode)}FS.doSetAttr(stream,node,{size:len,timestamp:Date.now()})},truncate(path,len){if(len<0){throw new FS.ErrnoError(28)}var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:true});node=lookup.node}else{node=path}FS.doTruncate(null,node,len)},ftruncate(fd,len){var stream=FS.getStreamChecked(fd);if(len<0||(stream.flags&2097155)===0){throw new FS.ErrnoError(28)}FS.doTruncate(stream,stream.node,len)},utime(path,atime,mtime){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;var setattr=FS.checkOpExists(node.node_ops.setattr,63);setattr(node,{atime,mtime})},open(path,flags,mode=438){if(path===""){throw new FS.ErrnoError(44)}flags=typeof flags=="string"?FS_modeStringToFlags(flags):flags;if(flags&64){mode=mode&4095|32768}else{mode=0}var node;var isDirPath;if(typeof path=="object"){node=path}else{isDirPath=path.endsWith("/");var lookup=FS.lookupPath(path,{follow:!(flags&131072),noent_okay:true});node=lookup.node;path=lookup.path}var created=false;if(flags&64){if(node){if(flags&128){throw new FS.ErrnoError(20)}}else if(isDirPath){throw new FS.ErrnoError(31)}else{node=FS.mknod(path,mode|511,0);created=true}}if(!node){throw new FS.ErrnoError(44)}if(FS.isChrdev(node.mode)){flags&=~512}if(flags&65536&&!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}if(!created){var errCode=FS.mayOpen(node,flags);if(errCode){throw new FS.ErrnoError(errCode)}}if(flags&512&&!created){FS.truncate(node,0)}flags&=~(128|512|131072);var stream=FS.createStream({node,path:FS.getPath(node),flags,seekable:true,position:0,stream_ops:node.stream_ops,ungotten:[],error:false});if(stream.stream_ops.open){stream.stream_ops.open(stream)}if(created){FS.chmod(node,mode&511)}if(Module["logReadFiles"]&&!(flags&1)){if(!(path in FS.readFiles)){FS.readFiles[path]=1}}return stream},close(stream){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(stream.getdents)stream.getdents=null;try{if(stream.stream_ops.close){stream.stream_ops.close(stream)}}catch(e){throw e}finally{FS.closeStream(stream.fd)}stream.fd=null},isClosed(stream){return stream.fd===null},llseek(stream,offset,whence){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(!stream.seekable||!stream.stream_ops.llseek){throw new FS.ErrnoError(70)}if(whence!=0&&whence!=1&&whence!=2){throw new FS.ErrnoError(28)}stream.position=stream.stream_ops.llseek(stream,offset,whence);stream.ungotten=[];return stream.position},read(stream,buffer,offset,length,position){if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.read){throw new FS.ErrnoError(28)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead},write(stream,buffer,offset,length,position,canOwn){if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.write){throw new FS.ErrnoError(28)}if(stream.seekable&&stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;return bytesWritten},mmap(stream,length,position,prot,flags){if((prot&2)!==0&&(flags&2)===0&&(stream.flags&2097155)!==2){throw new FS.ErrnoError(2)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(2)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(43)}if(!length){throw new FS.ErrnoError(28)}return stream.stream_ops.mmap(stream,length,position,prot,flags)},msync(stream,buffer,offset,length,mmapFlags){if(!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},ioctl(stream,cmd,arg){if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(59)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile(path,opts={}){opts.flags=opts.flags||0;opts.encoding=opts.encoding||"binary";if(opts.encoding!=="utf8"&&opts.encoding!=="binary"){abort(`Invalid encoding type "${opts.encoding}"`)}var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding==="utf8"){buf=UTF8ArrayToString(buf)}FS.close(stream);return buf},writeFile(path,data,opts={}){opts.flags=opts.flags||577;var stream=FS.open(path,opts.flags,opts.mode);if(typeof data=="string"){data=new Uint8Array(intArrayFromString(data,true))}if(ArrayBuffer.isView(data)){FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn)}else{abort("Unsupported data type")}FS.close(stream)},cwd:()=>FS.currentPath,chdir(path){var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,"x");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories(){FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices(){FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length,llseek:()=>0});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomFill(randomBuffer);randomLeft=randomBuffer.byteLength}return randomBuffer[--randomLeft]};FS.createDevice("/dev","random",randomByte);FS.createDevice("/dev","urandom",randomByte);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories(){FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount(){var node=FS.createNode(proc_self,"fd",16895,73);node.stream_ops={llseek:MEMFS.stream_ops.llseek};node.node_ops={lookup(parent,name){var fd=+name;var stream=FS.getStreamChecked(fd);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path},id:fd+1};ret.parent=ret;return ret},readdir(){return Array.from(FS.streams.entries()).filter(([k,v])=>v).map(([k,v])=>k.toString())}};return node}},{},"/proc/self/fd")},createStandardStreams(input,output,error){if(input){FS.createDevice("/dev","stdin",input)}else{FS.symlink("/dev/tty","/dev/stdin")}if(output){FS.createDevice("/dev","stdout",null,output)}else{FS.symlink("/dev/tty","/dev/stdout")}if(error){FS.createDevice("/dev","stderr",null,error)}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1)},staticInit(){FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={MEMFS}},init(input,output,error){FS.initialized=true;input??=Module["stdin"];output??=Module["stdout"];error??=Module["stderr"];FS.createStandardStreams(input,output,error)},quit(){FS.initialized=false;for(var stream of FS.streams){if(stream){FS.close(stream)}}},findObject(path,dontResolveLastLink){var ret=FS.analyzePath(path,dontResolveLastLink);if(!ret.exists){return null}return ret.object},analyzePath(path,dontResolveLastLink){try{var lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});path=lookup.path}catch(e){}var ret={isRoot:false,exists:false,error:0,name:null,path:null,object:null,parentExists:false,parentPath:null,parentObject:null};try{var lookup=FS.lookupPath(path,{parent:true});ret.parentExists=true;ret.parentPath=lookup.path;ret.parentObject=lookup.node;ret.name=PATH.basename(path);lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});ret.exists=true;ret.path=lookup.path;ret.object=lookup.node;ret.name=lookup.node.name;ret.isRoot=lookup.path==="/"}catch(e){ret.error=e.errno}return ret},createPath(parent,path,canRead,canWrite){parent=typeof parent=="string"?parent:FS.getPath(parent);var parts=path.split("/").reverse();while(parts.length){var part=parts.pop();if(!part)continue;var current=PATH.join2(parent,part);try{FS.mkdir(current)}catch(e){if(e.errno!=20)throw e}parent=current}return current},createFile(parent,name,properties,canRead,canWrite){var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS_getMode(canRead,canWrite);return FS.create(path,mode)},createDataFile(parent,name,data,canRead,canWrite,canOwn){var path=name;if(parent){parent=typeof parent=="string"?parent:FS.getPath(parent);path=name?PATH.join2(parent,name):parent}var mode=FS_getMode(canRead,canWrite);var node=FS.create(path,mode);if(data){if(typeof data=="string"){var arr=new Array(data.length);for(var i=0,len=data.length;ithis.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]}setDataGetter(getter){this.getter=getter}cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))abort("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)abort("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)abort("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))abort("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||"",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]=="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]=="undefined")abort("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true}get length(){if(!this.lengthKnown){this.cacheLength()}return this._length}get chunkSize(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}if(globalThis.XMLHttpRequest){if(!ENVIRONMENT_IS_WORKER)abort("Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc");var lazyArray=new LazyUint8Array;var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};for(const[key,fn]of Object.entries(node.stream_ops)){stream_ops[key]=(...args)=>{FS.forceLoadFile(node);return fn(...args)}}function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr,allocated:true}};node.stream_ops=stream_ops;return node}};var UTF8ToString=(ptr,maxBytesToRead,ignoreNul)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead,ignoreNul):"";var SYSCALLS={calculateAt(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return dir+"/"+path},writeStat(buf,stat){HEAPU32[buf>>2]=stat.dev;HEAPU32[buf+4>>2]=stat.mode;HEAPU32[buf+8>>2]=stat.nlink;HEAPU32[buf+12>>2]=stat.uid;HEAPU32[buf+16>>2]=stat.gid;HEAPU32[buf+20>>2]=stat.rdev;HEAP64[buf+24>>3]=BigInt(stat.size);HEAP32[buf+32>>2]=4096;HEAP32[buf+36>>2]=stat.blocks;var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();HEAP64[buf+40>>3]=BigInt(Math.floor(atime/1e3));HEAPU32[buf+48>>2]=atime%1e3*1e3*1e3;HEAP64[buf+56>>3]=BigInt(Math.floor(mtime/1e3));HEAPU32[buf+64>>2]=mtime%1e3*1e3*1e3;HEAP64[buf+72>>3]=BigInt(Math.floor(ctime/1e3));HEAPU32[buf+80>>2]=ctime%1e3*1e3*1e3;HEAP64[buf+88>>3]=BigInt(stat.ino);return 0},writeStatFs(buf,stats){HEAPU32[buf+4>>2]=stats.bsize;HEAPU32[buf+60>>2]=stats.bsize;HEAP64[buf+8>>3]=BigInt(stats.blocks);HEAP64[buf+16>>3]=BigInt(stats.bfree);HEAP64[buf+24>>3]=BigInt(stats.bavail);HEAP64[buf+32>>3]=BigInt(stats.files);HEAP64[buf+40>>3]=BigInt(stats.ffree);HEAPU32[buf+48>>2]=stats.fsid;HEAPU32[buf+64>>2]=stats.flags;HEAPU32[buf+56>>2]=stats.namelen},doMsync(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},getStreamFromFD(fd){var stream=FS.getStreamChecked(fd);return stream},varargs:undefined,getStr(ptr){var ret=UTF8ToString(ptr);return ret}};function ___syscall_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=syscallGetVarargI();if(arg<0){return-28}while(FS.streams[arg]){arg++}var newStream;newStream=FS.dupStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=syscallGetVarargI();stream.flags|=arg;return 0}case 12:{var arg=syscallGetVarargP();var offset=0;HEAP16[arg+offset>>1]=2;return 0}case 13:case 14:return 0}return-28}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fstat64(fd,buf){try{return SYSCALLS.writeStat(buf,FS.fstat(fd))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);function ___syscall_getcwd(buf,size){try{if(size===0)return-28;var cwd=FS.cwd();var cwdLengthInBytes=lengthBytesUTF8(cwd)+1;if(size>3]=BigInt(id);HEAP64[dirp+pos+8>>3]=BigInt((idx+1)*struct_size);HEAP16[dirp+pos+16>>1]=280;HEAP8[dirp+pos+18]=type;stringToUTF8(name,dirp+pos+19,256);pos+=struct_size}FS.llseek(stream,idx*struct_size,0);return pos}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:{if(!stream.tty)return-59;return 0}case 21505:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcgets){var termios=stream.tty.ops.ioctl_tcgets(stream);var argp=syscallGetVarargP();HEAP32[argp>>2]=termios.c_iflag||0;HEAP32[argp+4>>2]=termios.c_oflag||0;HEAP32[argp+8>>2]=termios.c_cflag||0;HEAP32[argp+12>>2]=termios.c_lflag||0;for(var i=0;i<32;i++){HEAP8[argp+i+17]=termios.c_cc[i]||0}return 0}return 0}case 21510:case 21511:case 21512:{if(!stream.tty)return-59;return 0}case 21506:case 21507:case 21508:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcsets){var argp=syscallGetVarargP();var c_iflag=HEAP32[argp>>2];var c_oflag=HEAP32[argp+4>>2];var c_cflag=HEAP32[argp+8>>2];var c_lflag=HEAP32[argp+12>>2];var c_cc=[];for(var i=0;i<32;i++){c_cc.push(HEAP8[argp+i+17])}return stream.tty.ops.ioctl_tcsets(stream.tty,op,{c_iflag,c_oflag,c_cflag,c_lflag,c_cc})}return 0}case 21519:{if(!stream.tty)return-59;var argp=syscallGetVarargP();HEAP32[argp>>2]=0;return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21537:case 21531:{var argp=syscallGetVarargP();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tiocgwinsz){var winsize=stream.tty.ops.ioctl_tiocgwinsz(stream.tty);var argp=syscallGetVarargP();HEAP16[argp>>1]=winsize[0];HEAP16[argp+2>>1]=winsize[1]}return 0}case 21524:{if(!stream.tty)return-59;return 0}case 21515:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_lstat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.writeStat(buf,FS.lstat(path))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_newfstatat(dirfd,path,buf,flags){try{path=SYSCALLS.getStr(path);var nofollow=flags&256;var allowEmpty=flags&4096;flags=flags&~6400;path=SYSCALLS.calculateAt(dirfd,path,allowEmpty);return SYSCALLS.writeStat(buf,nofollow?FS.lstat(path):FS.stat(path))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_openat(dirfd,path,flags,varargs){SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?syscallGetVarargI():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_readlinkat(dirfd,path,buf,bufsize){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(bufsize<=0)return-28;var ret=FS.readlink(path);var len=Math.min(bufsize,lengthBytesUTF8(ret));var endChar=HEAP8[buf+len];stringToUTF8(ret,buf,bufsize+1);HEAP8[buf+len]=endChar;return len}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_stat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.writeStat(buf,FS.stat(path))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __abort_js=()=>abort("");var __emscripten_throw_longjmp=()=>{throw Infinity};var INT53_MAX=9007199254740992;var INT53_MIN=-9007199254740992;var bigintToI53Checked=num=>numINT53_MAX?NaN:Number(num);function __gmtime_js(time,tmPtr){time=bigintToI53Checked(time);var date=new Date(time*1e3);HEAP32[tmPtr>>2]=date.getUTCSeconds();HEAP32[tmPtr+4>>2]=date.getUTCMinutes();HEAP32[tmPtr+8>>2]=date.getUTCHours();HEAP32[tmPtr+12>>2]=date.getUTCDate();HEAP32[tmPtr+16>>2]=date.getUTCMonth();HEAP32[tmPtr+20>>2]=date.getUTCFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getUTCDay();var start=Date.UTC(date.getUTCFullYear(),0,1,0,0,0,0);var yday=(date.getTime()-start)/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday}function __mmap_js(len,prot,flags,fd,offset,allocated,addr){offset=bigintToI53Checked(offset);try{var stream=SYSCALLS.getStreamFromFD(fd);var res=FS.mmap(stream,len,offset,prot,flags);var ptr=res.ptr;HEAP32[allocated>>2]=res.allocated;HEAPU32[addr>>2]=ptr;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function __munmap_js(addr,len,prot,flags,fd,offset){offset=bigintToI53Checked(offset);try{var stream=SYSCALLS.getStreamFromFD(fd);if(prot&2){SYSCALLS.doMsync(addr,stream,len,flags,offset)}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __tzset_js=(timezone,daylight,std_name,dst_name)=>{var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAPU32[timezone>>2]=stdTimezoneOffset*60;HEAP32[daylight>>2]=Number(winterOffset!=summerOffset);var extractZone=timezoneOffset=>{var sign=timezoneOffset>=0?"-":"+";var absOffset=Math.abs(timezoneOffset);var hours=String(Math.floor(absOffset/60)).padStart(2,"0");var minutes=String(absOffset%60).padStart(2,"0");return`UTC${sign}${hours}${minutes}`};var winterName=extractZone(winterOffset);var summerName=extractZone(summerOffset);if(summerOffsetperformance.now();var _emscripten_date_now=()=>Date.now();var nowIsMonotonic=1;var checkWasiClock=clock_id=>clock_id>=0&&clock_id<=3;function _clock_time_get(clk_id,ignored_precision,ptime){ignored_precision=bigintToI53Checked(ignored_precision);if(!checkWasiClock(clk_id)){return 28}var now;if(clk_id===0){now=_emscripten_date_now()}else if(nowIsMonotonic){now=_emscripten_get_now()}else{return 52}var nsec=Math.round(now*1e3*1e3);HEAP64[ptime>>3]=BigInt(nsec);return 0}var getHeapMax=()=>2147483648;var _emscripten_get_heap_max=()=>getHeapMax();var GLctx;var webgl_enable_ANGLE_instanced_arrays=ctx=>{var ext=ctx.getExtension("ANGLE_instanced_arrays");if(ext){ctx["vertexAttribDivisor"]=(index,divisor)=>ext["vertexAttribDivisorANGLE"](index,divisor);ctx["drawArraysInstanced"]=(mode,first,count,primcount)=>ext["drawArraysInstancedANGLE"](mode,first,count,primcount);ctx["drawElementsInstanced"]=(mode,count,type,indices,primcount)=>ext["drawElementsInstancedANGLE"](mode,count,type,indices,primcount);return 1}};var webgl_enable_OES_vertex_array_object=ctx=>{var ext=ctx.getExtension("OES_vertex_array_object");if(ext){ctx["createVertexArray"]=()=>ext["createVertexArrayOES"]();ctx["deleteVertexArray"]=vao=>ext["deleteVertexArrayOES"](vao);ctx["bindVertexArray"]=vao=>ext["bindVertexArrayOES"](vao);ctx["isVertexArray"]=vao=>ext["isVertexArrayOES"](vao);return 1}};var webgl_enable_WEBGL_draw_buffers=ctx=>{var ext=ctx.getExtension("WEBGL_draw_buffers");if(ext){ctx["drawBuffers"]=(n,bufs)=>ext["drawBuffersWEBGL"](n,bufs);return 1}};var webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance=ctx=>!!(ctx.dibvbi=ctx.getExtension("WEBGL_draw_instanced_base_vertex_base_instance"));var webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance=ctx=>!!(ctx.mdibvbi=ctx.getExtension("WEBGL_multi_draw_instanced_base_vertex_base_instance"));var webgl_enable_EXT_polygon_offset_clamp=ctx=>!!(ctx.extPolygonOffsetClamp=ctx.getExtension("EXT_polygon_offset_clamp"));var webgl_enable_EXT_clip_control=ctx=>!!(ctx.extClipControl=ctx.getExtension("EXT_clip_control"));var webgl_enable_WEBGL_polygon_mode=ctx=>!!(ctx.webglPolygonMode=ctx.getExtension("WEBGL_polygon_mode"));var webgl_enable_WEBGL_multi_draw=ctx=>!!(ctx.multiDrawWebgl=ctx.getExtension("WEBGL_multi_draw"));var getEmscriptenSupportedExtensions=ctx=>{var supportedExtensions=["ANGLE_instanced_arrays","EXT_blend_minmax","EXT_disjoint_timer_query","EXT_frag_depth","EXT_shader_texture_lod","EXT_sRGB","OES_element_index_uint","OES_fbo_render_mipmap","OES_standard_derivatives","OES_texture_float","OES_texture_half_float","OES_texture_half_float_linear","OES_vertex_array_object","WEBGL_color_buffer_float","WEBGL_depth_texture","WEBGL_draw_buffers","EXT_color_buffer_float","EXT_conservative_depth","EXT_disjoint_timer_query_webgl2","EXT_texture_norm16","NV_shader_noperspective_interpolation","WEBGL_clip_cull_distance","EXT_clip_control","EXT_color_buffer_half_float","EXT_depth_clamp","EXT_float_blend","EXT_polygon_offset_clamp","EXT_texture_compression_bptc","EXT_texture_compression_rgtc","EXT_texture_filter_anisotropic","KHR_parallel_shader_compile","OES_texture_float_linear","WEBGL_blend_func_extended","WEBGL_compressed_texture_astc","WEBGL_compressed_texture_etc","WEBGL_compressed_texture_etc1","WEBGL_compressed_texture_s3tc","WEBGL_compressed_texture_s3tc_srgb","WEBGL_debug_renderer_info","WEBGL_debug_shaders","WEBGL_lose_context","WEBGL_multi_draw","WEBGL_polygon_mode"];return(ctx.getSupportedExtensions()||[]).filter(ext=>supportedExtensions.includes(ext))};var GL={counter:1,buffers:[],programs:[],framebuffers:[],renderbuffers:[],textures:[],shaders:[],vaos:[],contexts:[],offscreenCanvases:{},queries:[],samplers:[],transformFeedbacks:[],syncs:[],stringCache:{},stringiCache:{},unpackAlignment:4,unpackRowLength:0,recordError:errorCode=>{if(!GL.lastError){GL.lastError=errorCode}},getNewId:table=>{var ret=GL.counter++;for(var i=table.length;i{for(var i=0;i>2]=id}},getSource:(shader,count,string,length)=>{var source="";for(var i=0;i>2]:undefined;source+=UTF8ToString(HEAPU32[string+i*4>>2],len)}return source},createContext:(canvas,webGLContextAttributes)=>{if(!canvas.getContextSafariWebGL2Fixed){canvas.getContextSafariWebGL2Fixed=canvas.getContext;function fixedGetContext(ver,attrs){var gl=canvas.getContextSafariWebGL2Fixed(ver,attrs);return ver=="webgl"==gl instanceof WebGLRenderingContext?gl:null}canvas.getContext=fixedGetContext}var ctx=webGLContextAttributes.majorVersion>1?canvas.getContext("webgl2",webGLContextAttributes):canvas.getContext("webgl",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:(ctx,webGLContextAttributes)=>{var handle=GL.getNewId(GL.contexts);var context={handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault=="undefined"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context)}return handle},makeContextCurrent:contextHandle=>{GL.currentContext=GL.contexts[contextHandle];Module["ctx"]=GLctx=GL.currentContext?.GLctx;return!(contextHandle&&!GLctx)},getContext:contextHandle=>GL.contexts[contextHandle],deleteContext:contextHandle=>{if(GL.currentContext===GL.contexts[contextHandle]){GL.currentContext=null}if(typeof JSEvents=="object"){JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas)}if(GL.contexts[contextHandle]?.GLctx.canvas){GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined}GL.contexts[contextHandle]=null},initExtensions:context=>{context||=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;webgl_enable_WEBGL_multi_draw(GLctx);webgl_enable_EXT_polygon_offset_clamp(GLctx);webgl_enable_EXT_clip_control(GLctx);webgl_enable_WEBGL_polygon_mode(GLctx);webgl_enable_ANGLE_instanced_arrays(GLctx);webgl_enable_OES_vertex_array_object(GLctx);webgl_enable_WEBGL_draw_buffers(GLctx);webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(GLctx);webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(GLctx);if(context.version>=2){GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query_webgl2")}if(context.version<2||!GLctx.disjointTimerQueryExt){GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query")}for(var ext of getEmscriptenSupportedExtensions(GLctx)){if(!ext.includes("lose_context")&&!ext.includes("debug")){GLctx.getExtension(ext)}}}};var _emscripten_glActiveTexture=x0=>GLctx.activeTexture(x0);var _emscripten_glAttachShader=(program,shader)=>{GLctx.attachShader(GL.programs[program],GL.shaders[shader])};var _emscripten_glBeginQuery=(target,id)=>{GLctx.beginQuery(target,GL.queries[id])};var _emscripten_glBeginQueryEXT=(target,id)=>{GLctx.disjointTimerQueryExt["beginQueryEXT"](target,GL.queries[id])};var _emscripten_glBeginTransformFeedback=x0=>GLctx.beginTransformFeedback(x0);var _emscripten_glBindAttribLocation=(program,index,name)=>{GLctx.bindAttribLocation(GL.programs[program],index,UTF8ToString(name))};var _emscripten_glBindBuffer=(target,buffer)=>{if(target==35051){GLctx.currentPixelPackBufferBinding=buffer}else if(target==35052){GLctx.currentPixelUnpackBufferBinding=buffer}GLctx.bindBuffer(target,GL.buffers[buffer])};var _emscripten_glBindBufferBase=(target,index,buffer)=>{GLctx.bindBufferBase(target,index,GL.buffers[buffer])};var _emscripten_glBindBufferRange=(target,index,buffer,offset,ptrsize)=>{GLctx.bindBufferRange(target,index,GL.buffers[buffer],offset,ptrsize)};var _emscripten_glBindFramebuffer=(target,framebuffer)=>{GLctx.bindFramebuffer(target,GL.framebuffers[framebuffer])};var _emscripten_glBindRenderbuffer=(target,renderbuffer)=>{GLctx.bindRenderbuffer(target,GL.renderbuffers[renderbuffer])};var _emscripten_glBindSampler=(unit,sampler)=>{GLctx.bindSampler(unit,GL.samplers[sampler])};var _emscripten_glBindTexture=(target,texture)=>{GLctx.bindTexture(target,GL.textures[texture])};var _emscripten_glBindTransformFeedback=(target,id)=>{GLctx.bindTransformFeedback(target,GL.transformFeedbacks[id])};var _emscripten_glBindVertexArray=vao=>{GLctx.bindVertexArray(GL.vaos[vao])};var _glBindVertexArray=_emscripten_glBindVertexArray;var _emscripten_glBindVertexArrayOES=_glBindVertexArray;var _emscripten_glBlendColor=(x0,x1,x2,x3)=>GLctx.blendColor(x0,x1,x2,x3);var _emscripten_glBlendEquation=x0=>GLctx.blendEquation(x0);var _emscripten_glBlendEquationSeparate=(x0,x1)=>GLctx.blendEquationSeparate(x0,x1);var _emscripten_glBlendFunc=(x0,x1)=>GLctx.blendFunc(x0,x1);var _emscripten_glBlendFuncSeparate=(x0,x1,x2,x3)=>GLctx.blendFuncSeparate(x0,x1,x2,x3);var _emscripten_glBlitFramebuffer=(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9)=>GLctx.blitFramebuffer(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9);var _emscripten_glBufferData=(target,size,data,usage)=>{if(GL.currentContext.version>=2){if(data&&size){GLctx.bufferData(target,HEAPU8,usage,data,size)}else{GLctx.bufferData(target,size,usage)}return}GLctx.bufferData(target,data?HEAPU8.subarray(data,data+size):size,usage)};var _emscripten_glBufferSubData=(target,offset,size,data)=>{if(GL.currentContext.version>=2){size&&GLctx.bufferSubData(target,offset,HEAPU8,data,size);return}GLctx.bufferSubData(target,offset,HEAPU8.subarray(data,data+size))};var _emscripten_glCheckFramebufferStatus=x0=>GLctx.checkFramebufferStatus(x0);var _emscripten_glClear=x0=>GLctx.clear(x0);var _emscripten_glClearBufferfi=(x0,x1,x2,x3)=>GLctx.clearBufferfi(x0,x1,x2,x3);var _emscripten_glClearBufferfv=(buffer,drawbuffer,value)=>{GLctx.clearBufferfv(buffer,drawbuffer,HEAPF32,value>>2)};var _emscripten_glClearBufferiv=(buffer,drawbuffer,value)=>{GLctx.clearBufferiv(buffer,drawbuffer,HEAP32,value>>2)};var _emscripten_glClearBufferuiv=(buffer,drawbuffer,value)=>{GLctx.clearBufferuiv(buffer,drawbuffer,HEAPU32,value>>2)};var _emscripten_glClearColor=(x0,x1,x2,x3)=>GLctx.clearColor(x0,x1,x2,x3);var _emscripten_glClearDepthf=x0=>GLctx.clearDepth(x0);var _emscripten_glClearStencil=x0=>GLctx.clearStencil(x0);var _emscripten_glClientWaitSync=(sync,flags,timeout)=>{timeout=Number(timeout);return GLctx.clientWaitSync(GL.syncs[sync],flags,timeout)};var _emscripten_glClipControlEXT=(origin,depth)=>{GLctx.extClipControl["clipControlEXT"](origin,depth)};var _emscripten_glColorMask=(red,green,blue,alpha)=>{GLctx.colorMask(!!red,!!green,!!blue,!!alpha)};var _emscripten_glCompileShader=shader=>{GLctx.compileShader(GL.shaders[shader])};var _emscripten_glCompressedTexImage2D=(target,level,internalFormat,width,height,border,imageSize,data)=>{if(GL.currentContext.version>=2){if(GLctx.currentPixelUnpackBufferBinding||!imageSize){GLctx.compressedTexImage2D(target,level,internalFormat,width,height,border,imageSize,data);return}GLctx.compressedTexImage2D(target,level,internalFormat,width,height,border,HEAPU8,data,imageSize);return}GLctx.compressedTexImage2D(target,level,internalFormat,width,height,border,HEAPU8.subarray(data,data+imageSize))};var _emscripten_glCompressedTexImage3D=(target,level,internalFormat,width,height,depth,border,imageSize,data)=>{if(GLctx.currentPixelUnpackBufferBinding){GLctx.compressedTexImage3D(target,level,internalFormat,width,height,depth,border,imageSize,data)}else{GLctx.compressedTexImage3D(target,level,internalFormat,width,height,depth,border,HEAPU8,data,imageSize)}};var _emscripten_glCompressedTexSubImage2D=(target,level,xoffset,yoffset,width,height,format,imageSize,data)=>{if(GL.currentContext.version>=2){if(GLctx.currentPixelUnpackBufferBinding||!imageSize){GLctx.compressedTexSubImage2D(target,level,xoffset,yoffset,width,height,format,imageSize,data);return}GLctx.compressedTexSubImage2D(target,level,xoffset,yoffset,width,height,format,HEAPU8,data,imageSize);return}GLctx.compressedTexSubImage2D(target,level,xoffset,yoffset,width,height,format,HEAPU8.subarray(data,data+imageSize))};var _emscripten_glCompressedTexSubImage3D=(target,level,xoffset,yoffset,zoffset,width,height,depth,format,imageSize,data)=>{if(GLctx.currentPixelUnpackBufferBinding){GLctx.compressedTexSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,imageSize,data)}else{GLctx.compressedTexSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,HEAPU8,data,imageSize)}};var _emscripten_glCopyBufferSubData=(x0,x1,x2,x3,x4)=>GLctx.copyBufferSubData(x0,x1,x2,x3,x4);var _emscripten_glCopyTexImage2D=(x0,x1,x2,x3,x4,x5,x6,x7)=>GLctx.copyTexImage2D(x0,x1,x2,x3,x4,x5,x6,x7);var _emscripten_glCopyTexSubImage2D=(x0,x1,x2,x3,x4,x5,x6,x7)=>GLctx.copyTexSubImage2D(x0,x1,x2,x3,x4,x5,x6,x7);var _emscripten_glCopyTexSubImage3D=(x0,x1,x2,x3,x4,x5,x6,x7,x8)=>GLctx.copyTexSubImage3D(x0,x1,x2,x3,x4,x5,x6,x7,x8);var _emscripten_glCreateProgram=()=>{var id=GL.getNewId(GL.programs);var program=GLctx.createProgram();program.name=id;program.maxUniformLength=program.maxAttributeLength=program.maxUniformBlockNameLength=0;program.uniformIdCounter=1;GL.programs[id]=program;return id};var _emscripten_glCreateShader=shaderType=>{var id=GL.getNewId(GL.shaders);GL.shaders[id]=GLctx.createShader(shaderType);return id};var _emscripten_glCullFace=x0=>GLctx.cullFace(x0);var _emscripten_glDeleteBuffers=(n,buffers)=>{for(var i=0;i>2];var buffer=GL.buffers[id];if(!buffer)continue;GLctx.deleteBuffer(buffer);buffer.name=0;GL.buffers[id]=null;if(id==GLctx.currentPixelPackBufferBinding)GLctx.currentPixelPackBufferBinding=0;if(id==GLctx.currentPixelUnpackBufferBinding)GLctx.currentPixelUnpackBufferBinding=0}};var _emscripten_glDeleteFramebuffers=(n,framebuffers)=>{for(var i=0;i>2];var framebuffer=GL.framebuffers[id];if(!framebuffer)continue;GLctx.deleteFramebuffer(framebuffer);framebuffer.name=0;GL.framebuffers[id]=null}};var _emscripten_glDeleteProgram=id=>{if(!id)return;var program=GL.programs[id];if(!program){GL.recordError(1281);return}GLctx.deleteProgram(program);program.name=0;GL.programs[id]=null};var _emscripten_glDeleteQueries=(n,ids)=>{for(var i=0;i>2];var query=GL.queries[id];if(!query)continue;GLctx.deleteQuery(query);GL.queries[id]=null}};var _emscripten_glDeleteQueriesEXT=(n,ids)=>{for(var i=0;i>2];var query=GL.queries[id];if(!query)continue;GLctx.disjointTimerQueryExt["deleteQueryEXT"](query);GL.queries[id]=null}};var _emscripten_glDeleteRenderbuffers=(n,renderbuffers)=>{for(var i=0;i>2];var renderbuffer=GL.renderbuffers[id];if(!renderbuffer)continue;GLctx.deleteRenderbuffer(renderbuffer);renderbuffer.name=0;GL.renderbuffers[id]=null}};var _emscripten_glDeleteSamplers=(n,samplers)=>{for(var i=0;i>2];var sampler=GL.samplers[id];if(!sampler)continue;GLctx.deleteSampler(sampler);sampler.name=0;GL.samplers[id]=null}};var _emscripten_glDeleteShader=id=>{if(!id)return;var shader=GL.shaders[id];if(!shader){GL.recordError(1281);return}GLctx.deleteShader(shader);GL.shaders[id]=null};var _emscripten_glDeleteSync=id=>{if(!id)return;var sync=GL.syncs[id];if(!sync){GL.recordError(1281);return}GLctx.deleteSync(sync);sync.name=0;GL.syncs[id]=null};var _emscripten_glDeleteTextures=(n,textures)=>{for(var i=0;i>2];var texture=GL.textures[id];if(!texture)continue;GLctx.deleteTexture(texture);texture.name=0;GL.textures[id]=null}};var _emscripten_glDeleteTransformFeedbacks=(n,ids)=>{for(var i=0;i>2];var transformFeedback=GL.transformFeedbacks[id];if(!transformFeedback)continue;GLctx.deleteTransformFeedback(transformFeedback);transformFeedback.name=0;GL.transformFeedbacks[id]=null}};var _emscripten_glDeleteVertexArrays=(n,vaos)=>{for(var i=0;i>2];GLctx.deleteVertexArray(GL.vaos[id]);GL.vaos[id]=null}};var _glDeleteVertexArrays=_emscripten_glDeleteVertexArrays;var _emscripten_glDeleteVertexArraysOES=_glDeleteVertexArrays;var _emscripten_glDepthFunc=x0=>GLctx.depthFunc(x0);var _emscripten_glDepthMask=flag=>{GLctx.depthMask(!!flag)};var _emscripten_glDepthRangef=(x0,x1)=>GLctx.depthRange(x0,x1);var _emscripten_glDetachShader=(program,shader)=>{GLctx.detachShader(GL.programs[program],GL.shaders[shader])};var _emscripten_glDisable=x0=>GLctx.disable(x0);var _emscripten_glDisableVertexAttribArray=index=>{GLctx.disableVertexAttribArray(index)};var _emscripten_glDrawArrays=(mode,first,count)=>{GLctx.drawArrays(mode,first,count)};var _emscripten_glDrawArraysInstanced=(mode,first,count,primcount)=>{GLctx.drawArraysInstanced(mode,first,count,primcount)};var _glDrawArraysInstanced=_emscripten_glDrawArraysInstanced;var _emscripten_glDrawArraysInstancedANGLE=_glDrawArraysInstanced;var _emscripten_glDrawArraysInstancedARB=_glDrawArraysInstanced;var _emscripten_glDrawArraysInstancedBaseInstanceWEBGL=(mode,first,count,instanceCount,baseInstance)=>{GLctx.dibvbi["drawArraysInstancedBaseInstanceWEBGL"](mode,first,count,instanceCount,baseInstance)};var _emscripten_glDrawArraysInstancedEXT=_glDrawArraysInstanced;var _emscripten_glDrawArraysInstancedNV=_glDrawArraysInstanced;var tempFixedLengthArray=[];var _emscripten_glDrawBuffers=(n,bufs)=>{var bufArray=tempFixedLengthArray[n];for(var i=0;i>2]}GLctx.drawBuffers(bufArray)};var _glDrawBuffers=_emscripten_glDrawBuffers;var _emscripten_glDrawBuffersEXT=_glDrawBuffers;var _emscripten_glDrawBuffersWEBGL=_glDrawBuffers;var _emscripten_glDrawElements=(mode,count,type,indices)=>{GLctx.drawElements(mode,count,type,indices)};var _emscripten_glDrawElementsInstanced=(mode,count,type,indices,primcount)=>{GLctx.drawElementsInstanced(mode,count,type,indices,primcount)};var _glDrawElementsInstanced=_emscripten_glDrawElementsInstanced;var _emscripten_glDrawElementsInstancedANGLE=_glDrawElementsInstanced;var _emscripten_glDrawElementsInstancedARB=_glDrawElementsInstanced;var _emscripten_glDrawElementsInstancedBaseVertexBaseInstanceWEBGL=(mode,count,type,offset,instanceCount,baseVertex,baseinstance)=>{GLctx.dibvbi["drawElementsInstancedBaseVertexBaseInstanceWEBGL"](mode,count,type,offset,instanceCount,baseVertex,baseinstance)};var _emscripten_glDrawElementsInstancedEXT=_glDrawElementsInstanced;var _emscripten_glDrawElementsInstancedNV=_glDrawElementsInstanced;var _glDrawElements=_emscripten_glDrawElements;var _emscripten_glDrawRangeElements=(mode,start,end,count,type,indices)=>{_glDrawElements(mode,count,type,indices)};var _emscripten_glEnable=x0=>GLctx.enable(x0);var _emscripten_glEnableVertexAttribArray=index=>{GLctx.enableVertexAttribArray(index)};var _emscripten_glEndQuery=x0=>GLctx.endQuery(x0);var _emscripten_glEndQueryEXT=target=>{GLctx.disjointTimerQueryExt["endQueryEXT"](target)};var _emscripten_glEndTransformFeedback=()=>GLctx.endTransformFeedback();var _emscripten_glFenceSync=(condition,flags)=>{var sync=GLctx.fenceSync(condition,flags);if(sync){var id=GL.getNewId(GL.syncs);sync.name=id;GL.syncs[id]=sync;return id}return 0};var _emscripten_glFinish=()=>GLctx.finish();var _emscripten_glFlush=()=>GLctx.flush();var _emscripten_glFramebufferRenderbuffer=(target,attachment,renderbuffertarget,renderbuffer)=>{GLctx.framebufferRenderbuffer(target,attachment,renderbuffertarget,GL.renderbuffers[renderbuffer])};var _emscripten_glFramebufferTexture2D=(target,attachment,textarget,texture,level)=>{GLctx.framebufferTexture2D(target,attachment,textarget,GL.textures[texture],level)};var _emscripten_glFramebufferTextureLayer=(target,attachment,texture,level,layer)=>{GLctx.framebufferTextureLayer(target,attachment,GL.textures[texture],level,layer)};var _emscripten_glFrontFace=x0=>GLctx.frontFace(x0);var _emscripten_glGenBuffers=(n,buffers)=>{GL.genObject(n,buffers,"createBuffer",GL.buffers)};var _emscripten_glGenFramebuffers=(n,ids)=>{GL.genObject(n,ids,"createFramebuffer",GL.framebuffers)};var _emscripten_glGenQueries=(n,ids)=>{GL.genObject(n,ids,"createQuery",GL.queries)};var _emscripten_glGenQueriesEXT=(n,ids)=>{for(var i=0;i>2]=0;return}var id=GL.getNewId(GL.queries);query.name=id;GL.queries[id]=query;HEAP32[ids+i*4>>2]=id}};var _emscripten_glGenRenderbuffers=(n,renderbuffers)=>{GL.genObject(n,renderbuffers,"createRenderbuffer",GL.renderbuffers)};var _emscripten_glGenSamplers=(n,samplers)=>{GL.genObject(n,samplers,"createSampler",GL.samplers)};var _emscripten_glGenTextures=(n,textures)=>{GL.genObject(n,textures,"createTexture",GL.textures)};var _emscripten_glGenTransformFeedbacks=(n,ids)=>{GL.genObject(n,ids,"createTransformFeedback",GL.transformFeedbacks)};var _emscripten_glGenVertexArrays=(n,arrays)=>{GL.genObject(n,arrays,"createVertexArray",GL.vaos)};var _glGenVertexArrays=_emscripten_glGenVertexArrays;var _emscripten_glGenVertexArraysOES=_glGenVertexArrays;var _emscripten_glGenerateMipmap=x0=>GLctx.generateMipmap(x0);var __glGetActiveAttribOrUniform=(funcName,program,index,bufSize,length,size,type,name)=>{program=GL.programs[program];var info=GLctx[funcName](program,index);if(info){var numBytesWrittenExclNull=name&&stringToUTF8(info.name,name,bufSize);if(length)HEAP32[length>>2]=numBytesWrittenExclNull;if(size)HEAP32[size>>2]=info.size;if(type)HEAP32[type>>2]=info.type}};var _emscripten_glGetActiveAttrib=(program,index,bufSize,length,size,type,name)=>__glGetActiveAttribOrUniform("getActiveAttrib",program,index,bufSize,length,size,type,name);var _emscripten_glGetActiveUniform=(program,index,bufSize,length,size,type,name)=>__glGetActiveAttribOrUniform("getActiveUniform",program,index,bufSize,length,size,type,name);var _emscripten_glGetActiveUniformBlockName=(program,uniformBlockIndex,bufSize,length,uniformBlockName)=>{program=GL.programs[program];var result=GLctx.getActiveUniformBlockName(program,uniformBlockIndex);if(!result)return;if(uniformBlockName&&bufSize>0){var numBytesWrittenExclNull=stringToUTF8(result,uniformBlockName,bufSize);if(length)HEAP32[length>>2]=numBytesWrittenExclNull}else{if(length)HEAP32[length>>2]=0}};var _emscripten_glGetActiveUniformBlockiv=(program,uniformBlockIndex,pname,params)=>{if(!params){GL.recordError(1281);return}program=GL.programs[program];if(pname==35393){var name=GLctx.getActiveUniformBlockName(program,uniformBlockIndex);HEAP32[params>>2]=name.length+1;return}var result=GLctx.getActiveUniformBlockParameter(program,uniformBlockIndex,pname);if(result===null)return;if(pname==35395){for(var i=0;i>2]=result[i]}}else{HEAP32[params>>2]=result}};var _emscripten_glGetActiveUniformsiv=(program,uniformCount,uniformIndices,pname,params)=>{if(!params){GL.recordError(1281);return}if(uniformCount>0&&uniformIndices==0){GL.recordError(1281);return}program=GL.programs[program];var ids=[];for(var i=0;i>2])}var result=GLctx.getActiveUniforms(program,ids,pname);if(!result)return;var len=result.length;for(var i=0;i>2]=result[i]}};var _emscripten_glGetAttachedShaders=(program,maxCount,count,shaders)=>{var result=GLctx.getAttachedShaders(GL.programs[program]);var len=result.length;if(len>maxCount){len=maxCount}HEAP32[count>>2]=len;for(var i=0;i>2]=id}};var _emscripten_glGetAttribLocation=(program,name)=>GLctx.getAttribLocation(GL.programs[program],UTF8ToString(name));var writeI53ToI64=(ptr,num)=>{HEAPU32[ptr>>2]=num;var lower=HEAPU32[ptr>>2];HEAPU32[ptr+4>>2]=(num-lower)/4294967296};var webglGetExtensions=()=>{var exts=getEmscriptenSupportedExtensions(GLctx);exts=exts.concat(exts.map(e=>"GL_"+e));return exts};var emscriptenWebGLGet=(name_,p,type)=>{if(!p){GL.recordError(1281);return}var ret=undefined;switch(name_){case 36346:ret=1;break;case 36344:if(type!=0&&type!=1){GL.recordError(1280)}return;case 34814:case 36345:ret=0;break;case 34466:var formats=GLctx.getParameter(34467);ret=formats?formats.length:0;break;case 33309:if(GL.currentContext.version<2){GL.recordError(1282);return}ret=webglGetExtensions().length;break;case 33307:case 33308:if(GL.currentContext.version<2){GL.recordError(1280);return}ret=name_==33307?3:0;break}if(ret===undefined){var result=GLctx.getParameter(name_);switch(typeof result){case"number":ret=result;break;case"boolean":ret=result?1:0;break;case"string":GL.recordError(1280);return;case"object":if(result===null){switch(name_){case 34964:case 35725:case 34965:case 36006:case 36007:case 32873:case 34229:case 36662:case 36663:case 35053:case 35055:case 36010:case 35097:case 35869:case 32874:case 36389:case 35983:case 35368:case 34068:{ret=0;break}default:{GL.recordError(1280);return}}}else if(result instanceof Float32Array||result instanceof Uint32Array||result instanceof Int32Array||result instanceof Array){for(var i=0;i>2]=result[i];break;case 2:HEAPF32[p+i*4>>2]=result[i];break;case 4:HEAP8[p+i]=result[i]?1:0;break}}return}else{try{ret=result.name|0}catch(e){GL.recordError(1280);err(`GL_INVALID_ENUM in glGet${type}v: Unknown object returned from WebGL getParameter(${name_})! (error: ${e})`);return}}break;default:GL.recordError(1280);err(`GL_INVALID_ENUM in glGet${type}v: Native code calling glGet${type}v(${name_}) and it returns ${result} of type ${typeof result}!`);return}}switch(type){case 1:writeI53ToI64(p,ret);break;case 0:HEAP32[p>>2]=ret;break;case 2:HEAPF32[p>>2]=ret;break;case 4:HEAP8[p]=ret?1:0;break}};var _emscripten_glGetBooleanv=(name_,p)=>emscriptenWebGLGet(name_,p,4);var _emscripten_glGetBufferParameteri64v=(target,value,data)=>{if(!data){GL.recordError(1281);return}writeI53ToI64(data,GLctx.getBufferParameter(target,value))};var _emscripten_glGetBufferParameteriv=(target,value,data)=>{if(!data){GL.recordError(1281);return}HEAP32[data>>2]=GLctx.getBufferParameter(target,value)};var _emscripten_glGetError=()=>{var error=GLctx.getError()||GL.lastError;GL.lastError=0;return error};var _emscripten_glGetFloatv=(name_,p)=>emscriptenWebGLGet(name_,p,2);var _emscripten_glGetFragDataLocation=(program,name)=>GLctx.getFragDataLocation(GL.programs[program],UTF8ToString(name));var _emscripten_glGetFramebufferAttachmentParameteriv=(target,attachment,pname,params)=>{var result=GLctx.getFramebufferAttachmentParameter(target,attachment,pname);if(result instanceof WebGLRenderbuffer||result instanceof WebGLTexture){result=result.name|0}HEAP32[params>>2]=result};var emscriptenWebGLGetIndexed=(target,index,data,type)=>{if(!data){GL.recordError(1281);return}var result=GLctx.getIndexedParameter(target,index);var ret;switch(typeof result){case"boolean":ret=result?1:0;break;case"number":ret=result;break;case"object":if(result===null){switch(target){case 35983:case 35368:ret=0;break;default:{GL.recordError(1280);return}}}else if(result instanceof WebGLBuffer){ret=result.name|0}else{GL.recordError(1280);return}break;default:GL.recordError(1280);return}switch(type){case 1:writeI53ToI64(data,ret);break;case 0:HEAP32[data>>2]=ret;break;case 2:HEAPF32[data>>2]=ret;break;case 4:HEAP8[data]=ret?1:0;break;default:abort("internal emscriptenWebGLGetIndexed() error, bad type: "+type)}};var _emscripten_glGetInteger64i_v=(target,index,data)=>emscriptenWebGLGetIndexed(target,index,data,1);var _emscripten_glGetInteger64v=(name_,p)=>{emscriptenWebGLGet(name_,p,1)};var _emscripten_glGetIntegeri_v=(target,index,data)=>emscriptenWebGLGetIndexed(target,index,data,0);var _emscripten_glGetIntegerv=(name_,p)=>emscriptenWebGLGet(name_,p,0);var _emscripten_glGetInternalformativ=(target,internalformat,pname,bufSize,params)=>{if(bufSize<0){GL.recordError(1281);return}if(!params){GL.recordError(1281);return}var ret=GLctx.getInternalformatParameter(target,internalformat,pname);if(ret===null)return;for(var i=0;i>2]=ret[i]}};var _emscripten_glGetProgramBinary=(program,bufSize,length,binaryFormat,binary)=>{GL.recordError(1282)};var _emscripten_glGetProgramInfoLog=(program,maxLength,length,infoLog)=>{var log=GLctx.getProgramInfoLog(GL.programs[program]);if(log===null)log="(unknown error)";var numBytesWrittenExclNull=maxLength>0&&infoLog?stringToUTF8(log,infoLog,maxLength):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull};var _emscripten_glGetProgramiv=(program,pname,p)=>{if(!p){GL.recordError(1281);return}if(program>=GL.counter){GL.recordError(1281);return}program=GL.programs[program];if(pname==35716){var log=GLctx.getProgramInfoLog(program);if(log===null)log="(unknown error)";HEAP32[p>>2]=log.length+1}else if(pname==35719){if(!program.maxUniformLength){var numActiveUniforms=GLctx.getProgramParameter(program,35718);for(var i=0;i>2]=program.maxUniformLength}else if(pname==35722){if(!program.maxAttributeLength){var numActiveAttributes=GLctx.getProgramParameter(program,35721);for(var i=0;i>2]=program.maxAttributeLength}else if(pname==35381){if(!program.maxUniformBlockNameLength){var numActiveUniformBlocks=GLctx.getProgramParameter(program,35382);for(var i=0;i>2]=program.maxUniformBlockNameLength}else{HEAP32[p>>2]=GLctx.getProgramParameter(program,pname)}};var _emscripten_glGetQueryObjecti64vEXT=(id,pname,params)=>{if(!params){GL.recordError(1281);return}var query=GL.queries[id];var param;if(GL.currentContext.version<2){param=GLctx.disjointTimerQueryExt["getQueryObjectEXT"](query,pname)}else{param=GLctx.getQueryParameter(query,pname)}var ret;if(typeof param=="boolean"){ret=param?1:0}else{ret=param}writeI53ToI64(params,ret)};var _emscripten_glGetQueryObjectivEXT=(id,pname,params)=>{if(!params){GL.recordError(1281);return}var query=GL.queries[id];var param=GLctx.disjointTimerQueryExt["getQueryObjectEXT"](query,pname);var ret;if(typeof param=="boolean"){ret=param?1:0}else{ret=param}HEAP32[params>>2]=ret};var _glGetQueryObjecti64vEXT=_emscripten_glGetQueryObjecti64vEXT;var _emscripten_glGetQueryObjectui64vEXT=_glGetQueryObjecti64vEXT;var _emscripten_glGetQueryObjectuiv=(id,pname,params)=>{if(!params){GL.recordError(1281);return}var query=GL.queries[id];var param=GLctx.getQueryParameter(query,pname);var ret;if(typeof param=="boolean"){ret=param?1:0}else{ret=param}HEAP32[params>>2]=ret};var _glGetQueryObjectivEXT=_emscripten_glGetQueryObjectivEXT;var _emscripten_glGetQueryObjectuivEXT=_glGetQueryObjectivEXT;var _emscripten_glGetQueryiv=(target,pname,params)=>{if(!params){GL.recordError(1281);return}HEAP32[params>>2]=GLctx.getQuery(target,pname)};var _emscripten_glGetQueryivEXT=(target,pname,params)=>{if(!params){GL.recordError(1281);return}HEAP32[params>>2]=GLctx.disjointTimerQueryExt["getQueryEXT"](target,pname)};var _emscripten_glGetRenderbufferParameteriv=(target,pname,params)=>{if(!params){GL.recordError(1281);return}HEAP32[params>>2]=GLctx.getRenderbufferParameter(target,pname)};var _emscripten_glGetSamplerParameterfv=(sampler,pname,params)=>{if(!params){GL.recordError(1281);return}HEAPF32[params>>2]=GLctx.getSamplerParameter(GL.samplers[sampler],pname)};var _emscripten_glGetSamplerParameteriv=(sampler,pname,params)=>{if(!params){GL.recordError(1281);return}HEAP32[params>>2]=GLctx.getSamplerParameter(GL.samplers[sampler],pname)};var _emscripten_glGetShaderInfoLog=(shader,maxLength,length,infoLog)=>{var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log="(unknown error)";var numBytesWrittenExclNull=maxLength>0&&infoLog?stringToUTF8(log,infoLog,maxLength):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull};var _emscripten_glGetShaderPrecisionFormat=(shaderType,precisionType,range,precision)=>{var result=GLctx.getShaderPrecisionFormat(shaderType,precisionType);HEAP32[range>>2]=result.rangeMin;HEAP32[range+4>>2]=result.rangeMax;HEAP32[precision>>2]=result.precision};var _emscripten_glGetShaderSource=(shader,bufSize,length,source)=>{var result=GLctx.getShaderSource(GL.shaders[shader]);if(!result)return;var numBytesWrittenExclNull=bufSize>0&&source?stringToUTF8(result,source,bufSize):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull};var _emscripten_glGetShaderiv=(shader,pname,p)=>{if(!p){GL.recordError(1281);return}if(pname==35716){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log="(unknown error)";var logLength=log?log.length+1:0;HEAP32[p>>2]=logLength}else if(pname==35720){var source=GLctx.getShaderSource(GL.shaders[shader]);var sourceLength=source?source.length+1:0;HEAP32[p>>2]=sourceLength}else{HEAP32[p>>2]=GLctx.getShaderParameter(GL.shaders[shader],pname)}};var stringToNewUTF8=str=>{var size=lengthBytesUTF8(str)+1;var ret=_malloc(size);if(ret)stringToUTF8(str,ret,size);return ret};var _emscripten_glGetString=name_=>{var ret=GL.stringCache[name_];if(!ret){switch(name_){case 7939:ret=stringToNewUTF8(webglGetExtensions().join(" "));break;case 7936:case 7937:case 37445:case 37446:var s=GLctx.getParameter(name_);if(!s){GL.recordError(1280)}ret=s?stringToNewUTF8(s):0;break;case 7938:var webGLVersion=GLctx.getParameter(7938);var glVersion=`OpenGL ES 2.0 (${webGLVersion})`;if(GL.currentContext.version>=2)glVersion=`OpenGL ES 3.0 (${webGLVersion})`;ret=stringToNewUTF8(glVersion);break;case 35724:var glslVersion=GLctx.getParameter(35724);var ver_re=/^WebGL GLSL ES ([0-9]\.[0-9][0-9]?)(?:$| .*)/;var ver_num=glslVersion.match(ver_re);if(ver_num!==null){if(ver_num[1].length==3)ver_num[1]=ver_num[1]+"0";glslVersion=`OpenGL ES GLSL ES ${ver_num[1]} (${glslVersion})`}ret=stringToNewUTF8(glslVersion);break;default:GL.recordError(1280)}GL.stringCache[name_]=ret}return ret};var _emscripten_glGetStringi=(name,index)=>{if(GL.currentContext.version<2){GL.recordError(1282);return 0}var stringiCache=GL.stringiCache[name];if(stringiCache){if(index<0||index>=stringiCache.length){GL.recordError(1281);return 0}return stringiCache[index]}switch(name){case 7939:var exts=webglGetExtensions().map(stringToNewUTF8);stringiCache=GL.stringiCache[name]=exts;if(index<0||index>=stringiCache.length){GL.recordError(1281);return 0}return stringiCache[index];default:GL.recordError(1280);return 0}};var _emscripten_glGetSynciv=(sync,pname,bufSize,length,values)=>{if(bufSize<0){GL.recordError(1281);return}if(!values){GL.recordError(1281);return}var ret=GLctx.getSyncParameter(GL.syncs[sync],pname);if(ret!==null){HEAP32[values>>2]=ret;if(length)HEAP32[length>>2]=1}};var _emscripten_glGetTexParameterfv=(target,pname,params)=>{if(!params){GL.recordError(1281);return}HEAPF32[params>>2]=GLctx.getTexParameter(target,pname)};var _emscripten_glGetTexParameteriv=(target,pname,params)=>{if(!params){GL.recordError(1281);return}HEAP32[params>>2]=GLctx.getTexParameter(target,pname)};var _emscripten_glGetTransformFeedbackVarying=(program,index,bufSize,length,size,type,name)=>{program=GL.programs[program];var info=GLctx.getTransformFeedbackVarying(program,index);if(!info)return;if(name&&bufSize>0){var numBytesWrittenExclNull=stringToUTF8(info.name,name,bufSize);if(length)HEAP32[length>>2]=numBytesWrittenExclNull}else{if(length)HEAP32[length>>2]=0}if(size)HEAP32[size>>2]=info.size;if(type)HEAP32[type>>2]=info.type};var _emscripten_glGetUniformBlockIndex=(program,uniformBlockName)=>GLctx.getUniformBlockIndex(GL.programs[program],UTF8ToString(uniformBlockName));var _emscripten_glGetUniformIndices=(program,uniformCount,uniformNames,uniformIndices)=>{if(!uniformIndices){GL.recordError(1281);return}if(uniformCount>0&&(uniformNames==0||uniformIndices==0)){GL.recordError(1281);return}program=GL.programs[program];var names=[];for(var i=0;i>2]));var result=GLctx.getUniformIndices(program,names);if(!result)return;var len=result.length;for(var i=0;i>2]=result[i]}};var jstoi_q=str=>parseInt(str);var webglGetLeftBracePos=name=>name.slice(-1)=="]"&&name.lastIndexOf("[");var webglPrepareUniformLocationsBeforeFirstUse=program=>{var uniformLocsById=program.uniformLocsById,uniformSizeAndIdsByName=program.uniformSizeAndIdsByName,i,j;if(!uniformLocsById){program.uniformLocsById=uniformLocsById={};program.uniformArrayNamesById={};var numActiveUniforms=GLctx.getProgramParameter(program,35718);for(i=0;i0?nm.slice(0,lb):nm;var id=program.uniformIdCounter;program.uniformIdCounter+=sz;uniformSizeAndIdsByName[arrayName]=[sz,id];for(j=0;j{name=UTF8ToString(name);if(program=GL.programs[program]){webglPrepareUniformLocationsBeforeFirstUse(program);var uniformLocsById=program.uniformLocsById;var arrayIndex=0;var uniformBaseName=name;var leftBrace=webglGetLeftBracePos(name);if(leftBrace>0){arrayIndex=jstoi_q(name.slice(leftBrace+1))>>>0;uniformBaseName=name.slice(0,leftBrace)}var sizeAndId=program.uniformSizeAndIdsByName[uniformBaseName];if(sizeAndId&&arrayIndex{var p=GLctx.currentProgram;if(p){var webglLoc=p.uniformLocsById[location];if(typeof webglLoc=="number"){p.uniformLocsById[location]=webglLoc=GLctx.getUniformLocation(p,p.uniformArrayNamesById[location]+(webglLoc>0?`[${webglLoc}]`:""))}return webglLoc}else{GL.recordError(1282)}};var emscriptenWebGLGetUniform=(program,location,params,type)=>{if(!params){GL.recordError(1281);return}program=GL.programs[program];webglPrepareUniformLocationsBeforeFirstUse(program);var data=GLctx.getUniform(program,webglGetUniformLocation(location));if(typeof data=="number"||typeof data=="boolean"){switch(type){case 0:HEAP32[params>>2]=data;break;case 2:HEAPF32[params>>2]=data;break}}else{for(var i=0;i>2]=data[i];break;case 2:HEAPF32[params+i*4>>2]=data[i];break}}}};var _emscripten_glGetUniformfv=(program,location,params)=>{emscriptenWebGLGetUniform(program,location,params,2)};var _emscripten_glGetUniformiv=(program,location,params)=>{emscriptenWebGLGetUniform(program,location,params,0)};var _emscripten_glGetUniformuiv=(program,location,params)=>emscriptenWebGLGetUniform(program,location,params,0);var emscriptenWebGLGetVertexAttrib=(index,pname,params,type)=>{if(!params){GL.recordError(1281);return}var data=GLctx.getVertexAttrib(index,pname);if(pname==34975){HEAP32[params>>2]=data&&data["name"]}else if(typeof data=="number"||typeof data=="boolean"){switch(type){case 0:HEAP32[params>>2]=data;break;case 2:HEAPF32[params>>2]=data;break;case 5:HEAP32[params>>2]=Math.fround(data);break}}else{for(var i=0;i>2]=data[i];break;case 2:HEAPF32[params+i*4>>2]=data[i];break;case 5:HEAP32[params+i*4>>2]=Math.fround(data[i]);break}}}};var _emscripten_glGetVertexAttribIiv=(index,pname,params)=>{emscriptenWebGLGetVertexAttrib(index,pname,params,0)};var _glGetVertexAttribIiv=_emscripten_glGetVertexAttribIiv;var _emscripten_glGetVertexAttribIuiv=_glGetVertexAttribIiv;var _emscripten_glGetVertexAttribPointerv=(index,pname,pointer)=>{if(!pointer){GL.recordError(1281);return}HEAP32[pointer>>2]=GLctx.getVertexAttribOffset(index,pname)};var _emscripten_glGetVertexAttribfv=(index,pname,params)=>{emscriptenWebGLGetVertexAttrib(index,pname,params,2)};var _emscripten_glGetVertexAttribiv=(index,pname,params)=>{emscriptenWebGLGetVertexAttrib(index,pname,params,5)};var _emscripten_glHint=(x0,x1)=>GLctx.hint(x0,x1);var _emscripten_glInvalidateFramebuffer=(target,numAttachments,attachments)=>{var list=tempFixedLengthArray[numAttachments];for(var i=0;i>2]}GLctx.invalidateFramebuffer(target,list)};var _emscripten_glInvalidateSubFramebuffer=(target,numAttachments,attachments,x,y,width,height)=>{var list=tempFixedLengthArray[numAttachments];for(var i=0;i>2]}GLctx.invalidateSubFramebuffer(target,list,x,y,width,height)};var _emscripten_glIsBuffer=buffer=>{var b=GL.buffers[buffer];if(!b)return 0;return GLctx.isBuffer(b)};var _emscripten_glIsEnabled=x0=>GLctx.isEnabled(x0);var _emscripten_glIsFramebuffer=framebuffer=>{var fb=GL.framebuffers[framebuffer];if(!fb)return 0;return GLctx.isFramebuffer(fb)};var _emscripten_glIsProgram=program=>{program=GL.programs[program];if(!program)return 0;return GLctx.isProgram(program)};var _emscripten_glIsQuery=id=>{var query=GL.queries[id];if(!query)return 0;return GLctx.isQuery(query)};var _emscripten_glIsQueryEXT=id=>{var query=GL.queries[id];if(!query)return 0;return GLctx.disjointTimerQueryExt["isQueryEXT"](query)};var _emscripten_glIsRenderbuffer=renderbuffer=>{var rb=GL.renderbuffers[renderbuffer];if(!rb)return 0;return GLctx.isRenderbuffer(rb)};var _emscripten_glIsSampler=id=>{var sampler=GL.samplers[id];if(!sampler)return 0;return GLctx.isSampler(sampler)};var _emscripten_glIsShader=shader=>{var s=GL.shaders[shader];if(!s)return 0;return GLctx.isShader(s)};var _emscripten_glIsSync=sync=>GLctx.isSync(GL.syncs[sync]);var _emscripten_glIsTexture=id=>{var texture=GL.textures[id];if(!texture)return 0;return GLctx.isTexture(texture)};var _emscripten_glIsTransformFeedback=id=>GLctx.isTransformFeedback(GL.transformFeedbacks[id]);var _emscripten_glIsVertexArray=array=>{var vao=GL.vaos[array];if(!vao)return 0;return GLctx.isVertexArray(vao)};var _glIsVertexArray=_emscripten_glIsVertexArray;var _emscripten_glIsVertexArrayOES=_glIsVertexArray;var _emscripten_glLineWidth=x0=>GLctx.lineWidth(x0);var _emscripten_glLinkProgram=program=>{program=GL.programs[program];GLctx.linkProgram(program);program.uniformLocsById=0;program.uniformSizeAndIdsByName={}};var _emscripten_glMultiDrawArraysInstancedBaseInstanceWEBGL=(mode,firsts,counts,instanceCounts,baseInstances,drawCount)=>{GLctx.mdibvbi["multiDrawArraysInstancedBaseInstanceWEBGL"](mode,HEAP32,firsts>>2,HEAP32,counts>>2,HEAP32,instanceCounts>>2,HEAPU32,baseInstances>>2,drawCount)};var _emscripten_glMultiDrawElementsInstancedBaseVertexBaseInstanceWEBGL=(mode,counts,type,offsets,instanceCounts,baseVertices,baseInstances,drawCount)=>{GLctx.mdibvbi["multiDrawElementsInstancedBaseVertexBaseInstanceWEBGL"](mode,HEAP32,counts>>2,type,HEAP32,offsets>>2,HEAP32,instanceCounts>>2,HEAP32,baseVertices>>2,HEAPU32,baseInstances>>2,drawCount)};var _emscripten_glPauseTransformFeedback=()=>GLctx.pauseTransformFeedback();var _emscripten_glPixelStorei=(pname,param)=>{if(pname==3317){GL.unpackAlignment=param}else if(pname==3314){GL.unpackRowLength=param}GLctx.pixelStorei(pname,param)};var _emscripten_glPolygonModeWEBGL=(face,mode)=>{GLctx.webglPolygonMode["polygonModeWEBGL"](face,mode)};var _emscripten_glPolygonOffset=(x0,x1)=>GLctx.polygonOffset(x0,x1);var _emscripten_glPolygonOffsetClampEXT=(factor,units,clamp)=>{GLctx.extPolygonOffsetClamp["polygonOffsetClampEXT"](factor,units,clamp)};var _emscripten_glProgramBinary=(program,binaryFormat,binary,length)=>{GL.recordError(1280)};var _emscripten_glProgramParameteri=(program,pname,value)=>{GL.recordError(1280)};var _emscripten_glQueryCounterEXT=(id,target)=>{GLctx.disjointTimerQueryExt["queryCounterEXT"](GL.queries[id],target)};var _emscripten_glReadBuffer=x0=>GLctx.readBuffer(x0);var computeUnpackAlignedImageSize=(width,height,sizePerPixel)=>{function roundedToNextMultipleOf(x,y){return x+y-1&-y}var plainRowSize=(GL.unpackRowLength||width)*sizePerPixel;var alignedRowSize=roundedToNextMultipleOf(plainRowSize,GL.unpackAlignment);return height*alignedRowSize};var colorChannelsInGlTextureFormat=format=>{var colorChannels={5:3,6:4,8:2,29502:3,29504:4,26917:2,26918:2,29846:3,29847:4};return colorChannels[format-6402]||1};var heapObjectForWebGLType=type=>{type-=5120;if(type==0)return HEAP8;if(type==1)return HEAPU8;if(type==2)return HEAP16;if(type==4)return HEAP32;if(type==6)return HEAPF32;if(type==5||type==28922||type==28520||type==30779||type==30782)return HEAPU32;return HEAPU16};var toTypedArrayIndex=(pointer,heap)=>pointer>>>31-Math.clz32(heap.BYTES_PER_ELEMENT);var emscriptenWebGLGetTexPixelData=(type,format,width,height,pixels,internalFormat)=>{var heap=heapObjectForWebGLType(type);var sizePerPixel=colorChannelsInGlTextureFormat(format)*heap.BYTES_PER_ELEMENT;var bytes=computeUnpackAlignedImageSize(width,height,sizePerPixel);return heap.subarray(toTypedArrayIndex(pixels,heap),toTypedArrayIndex(pixels+bytes,heap))};var _emscripten_glReadPixels=(x,y,width,height,format,type,pixels)=>{if(GL.currentContext.version>=2){if(GLctx.currentPixelPackBufferBinding){GLctx.readPixels(x,y,width,height,format,type,pixels);return}var heap=heapObjectForWebGLType(type);var target=toTypedArrayIndex(pixels,heap);GLctx.readPixels(x,y,width,height,format,type,heap,target);return}var pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,format);if(!pixelData){GL.recordError(1280);return}GLctx.readPixels(x,y,width,height,format,type,pixelData)};var _emscripten_glReleaseShaderCompiler=()=>{};var _emscripten_glRenderbufferStorage=(x0,x1,x2,x3)=>GLctx.renderbufferStorage(x0,x1,x2,x3);var _emscripten_glRenderbufferStorageMultisample=(x0,x1,x2,x3,x4)=>GLctx.renderbufferStorageMultisample(x0,x1,x2,x3,x4);var _emscripten_glResumeTransformFeedback=()=>GLctx.resumeTransformFeedback();var _emscripten_glSampleCoverage=(value,invert)=>{GLctx.sampleCoverage(value,!!invert)};var _emscripten_glSamplerParameterf=(sampler,pname,param)=>{GLctx.samplerParameterf(GL.samplers[sampler],pname,param)};var _emscripten_glSamplerParameterfv=(sampler,pname,params)=>{var param=HEAPF32[params>>2];GLctx.samplerParameterf(GL.samplers[sampler],pname,param)};var _emscripten_glSamplerParameteri=(sampler,pname,param)=>{GLctx.samplerParameteri(GL.samplers[sampler],pname,param)};var _emscripten_glSamplerParameteriv=(sampler,pname,params)=>{var param=HEAP32[params>>2];GLctx.samplerParameteri(GL.samplers[sampler],pname,param)};var _emscripten_glScissor=(x0,x1,x2,x3)=>GLctx.scissor(x0,x1,x2,x3);var _emscripten_glShaderBinary=(count,shaders,binaryformat,binary,length)=>{GL.recordError(1280)};var _emscripten_glShaderSource=(shader,count,string,length)=>{var source=GL.getSource(shader,count,string,length);GLctx.shaderSource(GL.shaders[shader],source)};var _emscripten_glStencilFunc=(x0,x1,x2)=>GLctx.stencilFunc(x0,x1,x2);var _emscripten_glStencilFuncSeparate=(x0,x1,x2,x3)=>GLctx.stencilFuncSeparate(x0,x1,x2,x3);var _emscripten_glStencilMask=x0=>GLctx.stencilMask(x0);var _emscripten_glStencilMaskSeparate=(x0,x1)=>GLctx.stencilMaskSeparate(x0,x1);var _emscripten_glStencilOp=(x0,x1,x2)=>GLctx.stencilOp(x0,x1,x2);var _emscripten_glStencilOpSeparate=(x0,x1,x2,x3)=>GLctx.stencilOpSeparate(x0,x1,x2,x3);var _emscripten_glTexImage2D=(target,level,internalFormat,width,height,border,format,type,pixels)=>{if(GL.currentContext.version>=2){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixels);return}if(pixels){var heap=heapObjectForWebGLType(type);var index=toTypedArrayIndex(pixels,heap);GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,heap,index);return}}var pixelData=pixels?emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat):null;GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixelData)};var _emscripten_glTexImage3D=(target,level,internalFormat,width,height,depth,border,format,type,pixels)=>{if(GLctx.currentPixelUnpackBufferBinding){GLctx.texImage3D(target,level,internalFormat,width,height,depth,border,format,type,pixels)}else if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texImage3D(target,level,internalFormat,width,height,depth,border,format,type,heap,toTypedArrayIndex(pixels,heap))}else{GLctx.texImage3D(target,level,internalFormat,width,height,depth,border,format,type,null)}};var _emscripten_glTexParameterf=(x0,x1,x2)=>GLctx.texParameterf(x0,x1,x2);var _emscripten_glTexParameterfv=(target,pname,params)=>{var param=HEAPF32[params>>2];GLctx.texParameterf(target,pname,param)};var _emscripten_glTexParameteri=(x0,x1,x2)=>GLctx.texParameteri(x0,x1,x2);var _emscripten_glTexParameteriv=(target,pname,params)=>{var param=HEAP32[params>>2];GLctx.texParameteri(target,pname,param)};var _emscripten_glTexStorage2D=(x0,x1,x2,x3,x4)=>GLctx.texStorage2D(x0,x1,x2,x3,x4);var _emscripten_glTexStorage3D=(x0,x1,x2,x3,x4,x5)=>GLctx.texStorage3D(x0,x1,x2,x3,x4,x5);var _emscripten_glTexSubImage2D=(target,level,xoffset,yoffset,width,height,format,type,pixels)=>{if(GL.currentContext.version>=2){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixels);return}if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,heap,toTypedArrayIndex(pixels,heap));return}}var pixelData=pixels?emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,0):null;GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixelData)};var _emscripten_glTexSubImage3D=(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,pixels)=>{if(GLctx.currentPixelUnpackBufferBinding){GLctx.texSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,pixels)}else if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,heap,toTypedArrayIndex(pixels,heap))}else{GLctx.texSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,null)}};var _emscripten_glTransformFeedbackVaryings=(program,count,varyings,bufferMode)=>{program=GL.programs[program];var vars=[];for(var i=0;i>2]));GLctx.transformFeedbackVaryings(program,vars,bufferMode)};var _emscripten_glUniform1f=(location,v0)=>{GLctx.uniform1f(webglGetUniformLocation(location),v0)};var miniTempWebGLFloatBuffers=[];var _emscripten_glUniform1fv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform1fv(webglGetUniformLocation(location),HEAPF32,value>>2,count);return}if(count<=288){var view=miniTempWebGLFloatBuffers[count];for(var i=0;i>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*4>>2)}GLctx.uniform1fv(webglGetUniformLocation(location),view)};var _emscripten_glUniform1i=(location,v0)=>{GLctx.uniform1i(webglGetUniformLocation(location),v0)};var miniTempWebGLIntBuffers=[];var _emscripten_glUniform1iv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform1iv(webglGetUniformLocation(location),HEAP32,value>>2,count);return}if(count<=288){var view=miniTempWebGLIntBuffers[count];for(var i=0;i>2]}}else{var view=HEAP32.subarray(value>>2,value+count*4>>2)}GLctx.uniform1iv(webglGetUniformLocation(location),view)};var _emscripten_glUniform1ui=(location,v0)=>{GLctx.uniform1ui(webglGetUniformLocation(location),v0)};var _emscripten_glUniform1uiv=(location,count,value)=>{count&&GLctx.uniform1uiv(webglGetUniformLocation(location),HEAPU32,value>>2,count)};var _emscripten_glUniform2f=(location,v0,v1)=>{GLctx.uniform2f(webglGetUniformLocation(location),v0,v1)};var _emscripten_glUniform2fv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform2fv(webglGetUniformLocation(location),HEAPF32,value>>2,count*2);return}if(count<=144){count*=2;var view=miniTempWebGLFloatBuffers[count];for(var i=0;i>2];view[i+1]=HEAPF32[value+(4*i+4)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*8>>2)}GLctx.uniform2fv(webglGetUniformLocation(location),view)};var _emscripten_glUniform2i=(location,v0,v1)=>{GLctx.uniform2i(webglGetUniformLocation(location),v0,v1)};var _emscripten_glUniform2iv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform2iv(webglGetUniformLocation(location),HEAP32,value>>2,count*2);return}if(count<=144){count*=2;var view=miniTempWebGLIntBuffers[count];for(var i=0;i>2];view[i+1]=HEAP32[value+(4*i+4)>>2]}}else{var view=HEAP32.subarray(value>>2,value+count*8>>2)}GLctx.uniform2iv(webglGetUniformLocation(location),view)};var _emscripten_glUniform2ui=(location,v0,v1)=>{GLctx.uniform2ui(webglGetUniformLocation(location),v0,v1)};var _emscripten_glUniform2uiv=(location,count,value)=>{count&&GLctx.uniform2uiv(webglGetUniformLocation(location),HEAPU32,value>>2,count*2)};var _emscripten_glUniform3f=(location,v0,v1,v2)=>{GLctx.uniform3f(webglGetUniformLocation(location),v0,v1,v2)};var _emscripten_glUniform3fv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform3fv(webglGetUniformLocation(location),HEAPF32,value>>2,count*3);return}if(count<=96){count*=3;var view=miniTempWebGLFloatBuffers[count];for(var i=0;i>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*12>>2)}GLctx.uniform3fv(webglGetUniformLocation(location),view)};var _emscripten_glUniform3i=(location,v0,v1,v2)=>{GLctx.uniform3i(webglGetUniformLocation(location),v0,v1,v2)};var _emscripten_glUniform3iv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform3iv(webglGetUniformLocation(location),HEAP32,value>>2,count*3);return}if(count<=96){count*=3;var view=miniTempWebGLIntBuffers[count];for(var i=0;i>2];view[i+1]=HEAP32[value+(4*i+4)>>2];view[i+2]=HEAP32[value+(4*i+8)>>2]}}else{var view=HEAP32.subarray(value>>2,value+count*12>>2)}GLctx.uniform3iv(webglGetUniformLocation(location),view)};var _emscripten_glUniform3ui=(location,v0,v1,v2)=>{GLctx.uniform3ui(webglGetUniformLocation(location),v0,v1,v2)};var _emscripten_glUniform3uiv=(location,count,value)=>{count&&GLctx.uniform3uiv(webglGetUniformLocation(location),HEAPU32,value>>2,count*3)};var _emscripten_glUniform4f=(location,v0,v1,v2,v3)=>{GLctx.uniform4f(webglGetUniformLocation(location),v0,v1,v2,v3)};var _emscripten_glUniform4fv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform4fv(webglGetUniformLocation(location),HEAPF32,value>>2,count*4);return}if(count<=72){var view=miniTempWebGLFloatBuffers[4*count];var heap=HEAPF32;value=value>>2;count*=4;for(var i=0;i>2,value+count*16>>2)}GLctx.uniform4fv(webglGetUniformLocation(location),view)};var _emscripten_glUniform4i=(location,v0,v1,v2,v3)=>{GLctx.uniform4i(webglGetUniformLocation(location),v0,v1,v2,v3)};var _emscripten_glUniform4iv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform4iv(webglGetUniformLocation(location),HEAP32,value>>2,count*4);return}if(count<=72){count*=4;var view=miniTempWebGLIntBuffers[count];for(var i=0;i>2];view[i+1]=HEAP32[value+(4*i+4)>>2];view[i+2]=HEAP32[value+(4*i+8)>>2];view[i+3]=HEAP32[value+(4*i+12)>>2]}}else{var view=HEAP32.subarray(value>>2,value+count*16>>2)}GLctx.uniform4iv(webglGetUniformLocation(location),view)};var _emscripten_glUniform4ui=(location,v0,v1,v2,v3)=>{GLctx.uniform4ui(webglGetUniformLocation(location),v0,v1,v2,v3)};var _emscripten_glUniform4uiv=(location,count,value)=>{count&&GLctx.uniform4uiv(webglGetUniformLocation(location),HEAPU32,value>>2,count*4)};var _emscripten_glUniformBlockBinding=(program,uniformBlockIndex,uniformBlockBinding)=>{program=GL.programs[program];GLctx.uniformBlockBinding(program,uniformBlockIndex,uniformBlockBinding)};var _emscripten_glUniformMatrix2fv=(location,count,transpose,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniformMatrix2fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*4);return}if(count<=72){count*=4;var view=miniTempWebGLFloatBuffers[count];for(var i=0;i>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2];view[i+3]=HEAPF32[value+(4*i+12)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*16>>2)}GLctx.uniformMatrix2fv(webglGetUniformLocation(location),!!transpose,view)};var _emscripten_glUniformMatrix2x3fv=(location,count,transpose,value)=>{count&&GLctx.uniformMatrix2x3fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*6)};var _emscripten_glUniformMatrix2x4fv=(location,count,transpose,value)=>{count&&GLctx.uniformMatrix2x4fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*8)};var _emscripten_glUniformMatrix3fv=(location,count,transpose,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniformMatrix3fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*9);return}if(count<=32){count*=9;var view=miniTempWebGLFloatBuffers[count];for(var i=0;i>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2];view[i+3]=HEAPF32[value+(4*i+12)>>2];view[i+4]=HEAPF32[value+(4*i+16)>>2];view[i+5]=HEAPF32[value+(4*i+20)>>2];view[i+6]=HEAPF32[value+(4*i+24)>>2];view[i+7]=HEAPF32[value+(4*i+28)>>2];view[i+8]=HEAPF32[value+(4*i+32)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*36>>2)}GLctx.uniformMatrix3fv(webglGetUniformLocation(location),!!transpose,view)};var _emscripten_glUniformMatrix3x2fv=(location,count,transpose,value)=>{count&&GLctx.uniformMatrix3x2fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*6)};var _emscripten_glUniformMatrix3x4fv=(location,count,transpose,value)=>{count&&GLctx.uniformMatrix3x4fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*12)};var _emscripten_glUniformMatrix4fv=(location,count,transpose,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniformMatrix4fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*16);return}if(count<=18){var view=miniTempWebGLFloatBuffers[16*count];var heap=HEAPF32;value=value>>2;count*=16;for(var i=0;i>2,value+count*64>>2)}GLctx.uniformMatrix4fv(webglGetUniformLocation(location),!!transpose,view)};var _emscripten_glUniformMatrix4x2fv=(location,count,transpose,value)=>{count&&GLctx.uniformMatrix4x2fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*8)};var _emscripten_glUniformMatrix4x3fv=(location,count,transpose,value)=>{count&&GLctx.uniformMatrix4x3fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*12)};var _emscripten_glUseProgram=program=>{program=GL.programs[program];GLctx.useProgram(program);GLctx.currentProgram=program};var _emscripten_glValidateProgram=program=>{GLctx.validateProgram(GL.programs[program])};var _emscripten_glVertexAttrib1f=(x0,x1)=>GLctx.vertexAttrib1f(x0,x1);var _emscripten_glVertexAttrib1fv=(index,v)=>{GLctx.vertexAttrib1f(index,HEAPF32[v>>2])};var _emscripten_glVertexAttrib2f=(x0,x1,x2)=>GLctx.vertexAttrib2f(x0,x1,x2);var _emscripten_glVertexAttrib2fv=(index,v)=>{GLctx.vertexAttrib2f(index,HEAPF32[v>>2],HEAPF32[v+4>>2])};var _emscripten_glVertexAttrib3f=(x0,x1,x2,x3)=>GLctx.vertexAttrib3f(x0,x1,x2,x3);var _emscripten_glVertexAttrib3fv=(index,v)=>{GLctx.vertexAttrib3f(index,HEAPF32[v>>2],HEAPF32[v+4>>2],HEAPF32[v+8>>2])};var _emscripten_glVertexAttrib4f=(x0,x1,x2,x3,x4)=>GLctx.vertexAttrib4f(x0,x1,x2,x3,x4);var _emscripten_glVertexAttrib4fv=(index,v)=>{GLctx.vertexAttrib4f(index,HEAPF32[v>>2],HEAPF32[v+4>>2],HEAPF32[v+8>>2],HEAPF32[v+12>>2])};var _emscripten_glVertexAttribDivisor=(index,divisor)=>{GLctx.vertexAttribDivisor(index,divisor)};var _glVertexAttribDivisor=_emscripten_glVertexAttribDivisor;var _emscripten_glVertexAttribDivisorANGLE=_glVertexAttribDivisor;var _emscripten_glVertexAttribDivisorARB=_glVertexAttribDivisor;var _emscripten_glVertexAttribDivisorEXT=_glVertexAttribDivisor;var _emscripten_glVertexAttribDivisorNV=_glVertexAttribDivisor;var _emscripten_glVertexAttribI4i=(x0,x1,x2,x3,x4)=>GLctx.vertexAttribI4i(x0,x1,x2,x3,x4);var _emscripten_glVertexAttribI4iv=(index,v)=>{GLctx.vertexAttribI4i(index,HEAP32[v>>2],HEAP32[v+4>>2],HEAP32[v+8>>2],HEAP32[v+12>>2])};var _emscripten_glVertexAttribI4ui=(x0,x1,x2,x3,x4)=>GLctx.vertexAttribI4ui(x0,x1,x2,x3,x4);var _emscripten_glVertexAttribI4uiv=(index,v)=>{GLctx.vertexAttribI4ui(index,HEAPU32[v>>2],HEAPU32[v+4>>2],HEAPU32[v+8>>2],HEAPU32[v+12>>2])};var _emscripten_glVertexAttribIPointer=(index,size,type,stride,ptr)=>{GLctx.vertexAttribIPointer(index,size,type,stride,ptr)};var _emscripten_glVertexAttribPointer=(index,size,type,normalized,stride,ptr)=>{GLctx.vertexAttribPointer(index,size,type,!!normalized,stride,ptr)};var _emscripten_glViewport=(x0,x1,x2,x3)=>GLctx.viewport(x0,x1,x2,x3);var _emscripten_glWaitSync=(sync,flags,timeout)=>{timeout=Number(timeout);GLctx.waitSync(GL.syncs[sync],flags,timeout)};var wasmTableMirror=[];var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func};var _emscripten_request_animation_frame_loop=(cb,userData)=>{function tick(timeStamp){if(getWasmTableEntry(cb)(timeStamp,userData)){requestAnimationFrame(tick)}}return requestAnimationFrame(tick)};var growMemory=size=>{var oldHeapSize=wasmMemory.buffer.byteLength;var pages=(size-oldHeapSize+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var ENV={};var getExecutableName=()=>thisProgram||"./this.program";var getEnvStrings=()=>{if(!getEnvStrings.strings){var lang=(globalThis.navigator?.language??"C").replace("-","_")+".UTF-8";var env={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:lang,_:getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings};var _environ_get=(__environ,environ_buf)=>{var bufSize=0;var envp=0;for(var string of getEnvStrings()){var ptr=environ_buf+bufSize;HEAPU32[__environ+envp>>2]=ptr;bufSize+=stringToUTF8(string,ptr,Infinity)+1;envp+=4}return 0};var _environ_sizes_get=(penviron_count,penviron_buf_size)=>{var strings=getEnvStrings();HEAPU32[penviron_count>>2]=strings.length;var bufSize=0;for(var string of strings){bufSize+=lengthBytesUTF8(string)+1}HEAPU32[penviron_buf_size>>2]=bufSize;return 0};var runtimeKeepaliveCounter=0;var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var _exit=exitJS;function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doReadv=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_read(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doReadv(stream,iov,iovcnt);HEAPU32[pnum>>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_seek(fd,offset,whence,newOffset){offset=bigintToI53Checked(offset);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);HEAP64[newOffset>>3]=BigInt(stream.position);if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doWritev=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var _glGetIntegerv=_emscripten_glGetIntegerv;var _glGetString=_emscripten_glGetString;var _glGetStringi=_emscripten_glGetStringi;var _llvm_eh_typeid_for=type=>type;function _random_get(buffer,size){try{randomFill(HEAPU8.subarray(buffer,buffer+size));return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var stackAlloc=sz=>__emscripten_stack_alloc(sz);var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};FS.createPreloadedFile=FS_createPreloadedFile;FS.preloadFile=FS_preloadFile;FS.staticInit();for(let i=0;i<32;++i)tempFixedLengthArray.push(new Array(i));var miniTempWebGLFloatBuffersStorage=new Float32Array(288);for(var i=0;i<=288;++i){miniTempWebGLFloatBuffers[i]=miniTempWebGLFloatBuffersStorage.subarray(0,i)}var miniTempWebGLIntBuffersStorage=new Int32Array(288);for(var i=0;i<=288;++i){miniTempWebGLIntBuffers[i]=miniTempWebGLIntBuffersStorage.subarray(0,i)}{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["preloadPlugins"])preloadPlugins=Module["preloadPlugins"];if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].shift()()}}}Module["UTF8ToString"]=UTF8ToString;Module["stringToUTF8"]=stringToUTF8;Module["lengthBytesUTF8"]=lengthBytesUTF8;Module["GL"]=GL;var _malloc,_add_font,_add_image,_add_image_with_rid,_allocate,_apply_scene_transactions,_command,_deallocate,_destroy,_devtools_rendering_set_show_fps_meter,_devtools_rendering_set_show_hit_testing,_devtools_rendering_set_show_ruler,_devtools_rendering_set_show_stats,_devtools_rendering_set_show_tiles,_export_node_as,_get_default_fallback_fonts,_get_image_bytes,_get_image_size,_get_node_absolute_bounding_box,_get_node_id_from_point,_get_node_ids_from_envelope,_get_node_ids_from_point,_grida_fonts_analyze_family,_grida_fonts_free,_grida_fonts_parse_font,_grida_markdown_to_html,_grida_svg_optimize,_grida_svg_pack,_has_missing_fonts,_highlight_strokes,_init,_init_with_backend,_list_available_fonts,_list_missing_fonts,_load_benchmark_scene,_load_dummy_scene,_load_scene_json,_pointer_move,_redraw,_resize_surface,_runtime_renderer_set_cache_tile,_runtime_renderer_set_outline_mode,_runtime_renderer_set_pixel_preview_scale,_runtime_renderer_set_pixel_preview_stable,_runtime_renderer_set_render_policy_flags,_set_debug,_set_default_fallback_fonts,_set_main_camera_transform,_set_verbose,_tick,_to_vector_network,_toggle_debug,_main,_emscripten_builtin_memalign,_setThrew,__emscripten_tempret_set,__emscripten_stack_restore,__emscripten_stack_alloc,_emscripten_stack_get_current,___cxa_decrement_exception_refcount,___cxa_increment_exception_refcount,___cxa_can_catch,___cxa_get_exception_ptr,memory,__indirect_function_table,wasmMemory,wasmTable;function assignWasmExports(wasmExports){_malloc=wasmExports["Lg"];_add_font=Module["_add_font"]=wasmExports["Ng"];_add_image=Module["_add_image"]=wasmExports["Og"];_add_image_with_rid=Module["_add_image_with_rid"]=wasmExports["Pg"];_allocate=Module["_allocate"]=wasmExports["Qg"];_apply_scene_transactions=Module["_apply_scene_transactions"]=wasmExports["Rg"];_command=Module["_command"]=wasmExports["Sg"];_deallocate=Module["_deallocate"]=wasmExports["Tg"];_destroy=Module["_destroy"]=wasmExports["Ug"];_devtools_rendering_set_show_fps_meter=Module["_devtools_rendering_set_show_fps_meter"]=wasmExports["Vg"];_devtools_rendering_set_show_hit_testing=Module["_devtools_rendering_set_show_hit_testing"]=wasmExports["Wg"];_devtools_rendering_set_show_ruler=Module["_devtools_rendering_set_show_ruler"]=wasmExports["Xg"];_devtools_rendering_set_show_stats=Module["_devtools_rendering_set_show_stats"]=wasmExports["Yg"];_devtools_rendering_set_show_tiles=Module["_devtools_rendering_set_show_tiles"]=wasmExports["Zg"];_export_node_as=Module["_export_node_as"]=wasmExports["_g"];_get_default_fallback_fonts=Module["_get_default_fallback_fonts"]=wasmExports["$g"];_get_image_bytes=Module["_get_image_bytes"]=wasmExports["ah"];_get_image_size=Module["_get_image_size"]=wasmExports["bh"];_get_node_absolute_bounding_box=Module["_get_node_absolute_bounding_box"]=wasmExports["ch"];_get_node_id_from_point=Module["_get_node_id_from_point"]=wasmExports["dh"];_get_node_ids_from_envelope=Module["_get_node_ids_from_envelope"]=wasmExports["eh"];_get_node_ids_from_point=Module["_get_node_ids_from_point"]=wasmExports["fh"];_grida_fonts_analyze_family=Module["_grida_fonts_analyze_family"]=wasmExports["gh"];_grida_fonts_free=Module["_grida_fonts_free"]=wasmExports["hh"];_grida_fonts_parse_font=Module["_grida_fonts_parse_font"]=wasmExports["ih"];_grida_markdown_to_html=Module["_grida_markdown_to_html"]=wasmExports["jh"];_grida_svg_optimize=Module["_grida_svg_optimize"]=wasmExports["kh"];_grida_svg_pack=Module["_grida_svg_pack"]=wasmExports["lh"];_has_missing_fonts=Module["_has_missing_fonts"]=wasmExports["mh"];_highlight_strokes=Module["_highlight_strokes"]=wasmExports["nh"];_init=Module["_init"]=wasmExports["oh"];_init_with_backend=Module["_init_with_backend"]=wasmExports["ph"];_list_available_fonts=Module["_list_available_fonts"]=wasmExports["qh"];_list_missing_fonts=Module["_list_missing_fonts"]=wasmExports["rh"];_load_benchmark_scene=Module["_load_benchmark_scene"]=wasmExports["sh"];_load_dummy_scene=Module["_load_dummy_scene"]=wasmExports["th"];_load_scene_json=Module["_load_scene_json"]=wasmExports["uh"];_pointer_move=Module["_pointer_move"]=wasmExports["vh"];_redraw=Module["_redraw"]=wasmExports["wh"];_resize_surface=Module["_resize_surface"]=wasmExports["xh"];_runtime_renderer_set_cache_tile=Module["_runtime_renderer_set_cache_tile"]=wasmExports["yh"];_runtime_renderer_set_outline_mode=Module["_runtime_renderer_set_outline_mode"]=wasmExports["zh"];_runtime_renderer_set_pixel_preview_scale=Module["_runtime_renderer_set_pixel_preview_scale"]=wasmExports["Ah"];_runtime_renderer_set_pixel_preview_stable=Module["_runtime_renderer_set_pixel_preview_stable"]=wasmExports["Bh"];_runtime_renderer_set_render_policy_flags=Module["_runtime_renderer_set_render_policy_flags"]=wasmExports["Ch"];_set_debug=Module["_set_debug"]=wasmExports["Dh"];_set_default_fallback_fonts=Module["_set_default_fallback_fonts"]=wasmExports["Eh"];_set_main_camera_transform=Module["_set_main_camera_transform"]=wasmExports["Fh"];_set_verbose=Module["_set_verbose"]=wasmExports["Gh"];_tick=Module["_tick"]=wasmExports["Hh"];_to_vector_network=Module["_to_vector_network"]=wasmExports["Ih"];_toggle_debug=Module["_toggle_debug"]=wasmExports["Jh"];_main=Module["_main"]=wasmExports["Kh"];_emscripten_builtin_memalign=wasmExports["Lh"];_setThrew=wasmExports["Mh"];__emscripten_tempret_set=wasmExports["Nh"];__emscripten_stack_restore=wasmExports["Oh"];__emscripten_stack_alloc=wasmExports["Ph"];_emscripten_stack_get_current=wasmExports["Qh"];___cxa_decrement_exception_refcount=wasmExports["Rh"];___cxa_increment_exception_refcount=wasmExports["Sh"];___cxa_can_catch=wasmExports["Th"];___cxa_get_exception_ptr=wasmExports["Uh"];memory=wasmMemory=wasmExports["Jg"];__indirect_function_table=wasmTable=wasmExports["Mg"]}var wasmImports={F:___cxa_begin_catch,M:___cxa_end_catch,a:___cxa_find_matching_catch_2,n:___cxa_find_matching_catch_3,ba:___cxa_find_matching_catch_4,xa:___cxa_rethrow,G:___cxa_throw,cb:___cxa_uncaught_exceptions,e:___resumeException,Ba:___syscall_fcntl64,wb:___syscall_fstat64,sb:___syscall_getcwd,ib:___syscall_getdents64,xb:___syscall_ioctl,tb:___syscall_lstat64,ub:___syscall_newfstatat,Ca:___syscall_openat,hb:___syscall_readlinkat,vb:___syscall_stat64,Ab:__abort_js,eb:__emscripten_throw_longjmp,mb:__gmtime_js,kb:__mmap_js,lb:__munmap_js,Bb:__tzset_js,zb:_clock_time_get,yb:_emscripten_date_now,gb:_emscripten_get_heap_max,Cf:_emscripten_glActiveTexture,Df:_emscripten_glAttachShader,fe:_emscripten_glBeginQuery,$d:_emscripten_glBeginQueryEXT,Gc:_emscripten_glBeginTransformFeedback,Ef:_emscripten_glBindAttribLocation,Ff:_emscripten_glBindBuffer,Dc:_emscripten_glBindBufferBase,Ec:_emscripten_glBindBufferRange,De:_emscripten_glBindFramebuffer,Ee:_emscripten_glBindRenderbuffer,le:_emscripten_glBindSampler,Gf:_emscripten_glBindTexture,Tb:_emscripten_glBindTransformFeedback,Ze:_emscripten_glBindVertexArray,af:_emscripten_glBindVertexArrayOES,Hf:_emscripten_glBlendColor,If:_emscripten_glBlendEquation,Ld:_emscripten_glBlendEquationSeparate,Jf:_emscripten_glBlendFunc,Kd:_emscripten_glBlendFuncSeparate,xe:_emscripten_glBlitFramebuffer,Kf:_emscripten_glBufferData,Lf:_emscripten_glBufferSubData,Fe:_emscripten_glCheckFramebufferStatus,Nf:_emscripten_glClear,gc:_emscripten_glClearBufferfi,hc:_emscripten_glClearBufferfv,jc:_emscripten_glClearBufferiv,ic:_emscripten_glClearBufferuiv,Of:_emscripten_glClearColor,Jd:_emscripten_glClearDepthf,Pf:_emscripten_glClearStencil,ue:_emscripten_glClientWaitSync,ad:_emscripten_glClipControlEXT,Qf:_emscripten_glColorMask,Rf:_emscripten_glCompileShader,Sf:_emscripten_glCompressedTexImage2D,Tc:_emscripten_glCompressedTexImage3D,Tf:_emscripten_glCompressedTexSubImage2D,Sc:_emscripten_glCompressedTexSubImage3D,we:_emscripten_glCopyBufferSubData,Id:_emscripten_glCopyTexImage2D,Uf:_emscripten_glCopyTexSubImage2D,Uc:_emscripten_glCopyTexSubImage3D,Vf:_emscripten_glCreateProgram,Wf:_emscripten_glCreateShader,Xf:_emscripten_glCullFace,Yf:_emscripten_glDeleteBuffers,Ge:_emscripten_glDeleteFramebuffers,Zf:_emscripten_glDeleteProgram,ge:_emscripten_glDeleteQueries,ae:_emscripten_glDeleteQueriesEXT,He:_emscripten_glDeleteRenderbuffers,me:_emscripten_glDeleteSamplers,_f:_emscripten_glDeleteShader,ve:_emscripten_glDeleteSync,$f:_emscripten_glDeleteTextures,Sb:_emscripten_glDeleteTransformFeedbacks,_e:_emscripten_glDeleteVertexArrays,bf:_emscripten_glDeleteVertexArraysOES,Hd:_emscripten_glDepthFunc,ag:_emscripten_glDepthMask,Gd:_emscripten_glDepthRangef,Fd:_emscripten_glDetachShader,bg:_emscripten_glDisable,cg:_emscripten_glDisableVertexAttribArray,dg:_emscripten_glDrawArrays,Xe:_emscripten_glDrawArraysInstanced,Od:_emscripten_glDrawArraysInstancedANGLE,Eb:_emscripten_glDrawArraysInstancedARB,Ue:_emscripten_glDrawArraysInstancedBaseInstanceWEBGL,Zc:_emscripten_glDrawArraysInstancedEXT,Fb:_emscripten_glDrawArraysInstancedNV,Se:_emscripten_glDrawBuffers,Xc:_emscripten_glDrawBuffersEXT,Pd:_emscripten_glDrawBuffersWEBGL,eg:_emscripten_glDrawElements,Ye:_emscripten_glDrawElementsInstanced,Nd:_emscripten_glDrawElementsInstancedANGLE,Cb:_emscripten_glDrawElementsInstancedARB,Ve:_emscripten_glDrawElementsInstancedBaseVertexBaseInstanceWEBGL,Db:_emscripten_glDrawElementsInstancedEXT,Yc:_emscripten_glDrawElementsInstancedNV,Me:_emscripten_glDrawRangeElements,fg:_emscripten_glEnable,gg:_emscripten_glEnableVertexAttribArray,he:_emscripten_glEndQuery,be:_emscripten_glEndQueryEXT,Fc:_emscripten_glEndTransformFeedback,re:_emscripten_glFenceSync,hg:_emscripten_glFinish,ig:_emscripten_glFlush,Ie:_emscripten_glFramebufferRenderbuffer,Je:_emscripten_glFramebufferTexture2D,Jc:_emscripten_glFramebufferTextureLayer,jg:_emscripten_glFrontFace,kg:_emscripten_glGenBuffers,Ke:_emscripten_glGenFramebuffers,ie:_emscripten_glGenQueries,ce:_emscripten_glGenQueriesEXT,Le:_emscripten_glGenRenderbuffers,ne:_emscripten_glGenSamplers,lg:_emscripten_glGenTextures,Rb:_emscripten_glGenTransformFeedbacks,We:_emscripten_glGenVertexArrays,cf:_emscripten_glGenVertexArraysOES,ze:_emscripten_glGenerateMipmap,Ed:_emscripten_glGetActiveAttrib,Dd:_emscripten_glGetActiveUniform,bc:_emscripten_glGetActiveUniformBlockName,cc:_emscripten_glGetActiveUniformBlockiv,ec:_emscripten_glGetActiveUniformsiv,Cd:_emscripten_glGetAttachedShaders,Bd:_emscripten_glGetAttribLocation,Ad:_emscripten_glGetBooleanv,Yb:_emscripten_glGetBufferParameteri64v,mg:_emscripten_glGetBufferParameteriv,ng:_emscripten_glGetError,og:_emscripten_glGetFloatv,tc:_emscripten_glGetFragDataLocation,Ae:_emscripten_glGetFramebufferAttachmentParameteriv,Zb:_emscripten_glGetInteger64i_v,$b:_emscripten_glGetInteger64v,Hc:_emscripten_glGetIntegeri_v,pg:_emscripten_glGetIntegerv,Ib:_emscripten_glGetInternalformativ,Mb:_emscripten_glGetProgramBinary,qg:_emscripten_glGetProgramInfoLog,rg:_emscripten_glGetProgramiv,Yd:_emscripten_glGetQueryObjecti64vEXT,Rd:_emscripten_glGetQueryObjectivEXT,Zd:_emscripten_glGetQueryObjectui64vEXT,je:_emscripten_glGetQueryObjectuiv,de:_emscripten_glGetQueryObjectuivEXT,ke:_emscripten_glGetQueryiv,ee:_emscripten_glGetQueryivEXT,Be:_emscripten_glGetRenderbufferParameteriv,Ub:_emscripten_glGetSamplerParameterfv,Vb:_emscripten_glGetSamplerParameteriv,sg:_emscripten_glGetShaderInfoLog,Vd:_emscripten_glGetShaderPrecisionFormat,zd:_emscripten_glGetShaderSource,tg:_emscripten_glGetShaderiv,ug:_emscripten_glGetString,$e:_emscripten_glGetStringi,_b:_emscripten_glGetSynciv,yd:_emscripten_glGetTexParameterfv,xd:_emscripten_glGetTexParameteriv,Bc:_emscripten_glGetTransformFeedbackVarying,dc:_emscripten_glGetUniformBlockIndex,fc:_emscripten_glGetUniformIndices,vg:_emscripten_glGetUniformLocation,wd:_emscripten_glGetUniformfv,vd:_emscripten_glGetUniformiv,uc:_emscripten_glGetUniformuiv,Ac:_emscripten_glGetVertexAttribIiv,zc:_emscripten_glGetVertexAttribIuiv,sd:_emscripten_glGetVertexAttribPointerv,ud:_emscripten_glGetVertexAttribfv,td:_emscripten_glGetVertexAttribiv,rd:_emscripten_glHint,Wd:_emscripten_glInvalidateFramebuffer,Xd:_emscripten_glInvalidateSubFramebuffer,qd:_emscripten_glIsBuffer,pd:_emscripten_glIsEnabled,od:_emscripten_glIsFramebuffer,nd:_emscripten_glIsProgram,Rc:_emscripten_glIsQuery,Sd:_emscripten_glIsQueryEXT,md:_emscripten_glIsRenderbuffer,Xb:_emscripten_glIsSampler,ld:_emscripten_glIsShader,se:_emscripten_glIsSync,wg:_emscripten_glIsTexture,Qb:_emscripten_glIsTransformFeedback,Ic:_emscripten_glIsVertexArray,Qd:_emscripten_glIsVertexArrayOES,xg:_emscripten_glLineWidth,yg:_emscripten_glLinkProgram,Qe:_emscripten_glMultiDrawArraysInstancedBaseInstanceWEBGL,Re:_emscripten_glMultiDrawElementsInstancedBaseVertexBaseInstanceWEBGL,Pb:_emscripten_glPauseTransformFeedback,zg:_emscripten_glPixelStorei,$c:_emscripten_glPolygonModeWEBGL,kd:_emscripten_glPolygonOffset,bd:_emscripten_glPolygonOffsetClampEXT,Lb:_emscripten_glProgramBinary,Kb:_emscripten_glProgramParameteri,_d:_emscripten_glQueryCounterEXT,Te:_emscripten_glReadBuffer,Ag:_emscripten_glReadPixels,jd:_emscripten_glReleaseShaderCompiler,Ce:_emscripten_glRenderbufferStorage,ye:_emscripten_glRenderbufferStorageMultisample,Nb:_emscripten_glResumeTransformFeedback,id:_emscripten_glSampleCoverage,oe:_emscripten_glSamplerParameterf,Wb:_emscripten_glSamplerParameterfv,pe:_emscripten_glSamplerParameteri,qe:_emscripten_glSamplerParameteriv,Bg:_emscripten_glScissor,hd:_emscripten_glShaderBinary,Cg:_emscripten_glShaderSource,Dg:_emscripten_glStencilFunc,Eg:_emscripten_glStencilFuncSeparate,Fg:_emscripten_glStencilMask,Gg:_emscripten_glStencilMaskSeparate,Hg:_emscripten_glStencilOp,Ig:_emscripten_glStencilOpSeparate,Ha:_emscripten_glTexImage2D,Wc:_emscripten_glTexImage3D,Ia:_emscripten_glTexParameterf,Ja:_emscripten_glTexParameterfv,Ka:_emscripten_glTexParameteri,La:_emscripten_glTexParameteriv,Ne:_emscripten_glTexStorage2D,Jb:_emscripten_glTexStorage3D,Ma:_emscripten_glTexSubImage2D,Vc:_emscripten_glTexSubImage3D,Cc:_emscripten_glTransformFeedbackVaryings,Na:_emscripten_glUniform1f,Oa:_emscripten_glUniform1fv,yf:_emscripten_glUniform1i,zf:_emscripten_glUniform1iv,sc:_emscripten_glUniform1ui,nc:_emscripten_glUniform1uiv,Af:_emscripten_glUniform2f,Bf:_emscripten_glUniform2fv,xf:_emscripten_glUniform2i,wf:_emscripten_glUniform2iv,qc:_emscripten_glUniform2ui,mc:_emscripten_glUniform2uiv,vf:_emscripten_glUniform3f,uf:_emscripten_glUniform3fv,tf:_emscripten_glUniform3i,sf:_emscripten_glUniform3iv,pc:_emscripten_glUniform3ui,lc:_emscripten_glUniform3uiv,rf:_emscripten_glUniform4f,qf:_emscripten_glUniform4fv,df:_emscripten_glUniform4i,ef:_emscripten_glUniform4iv,oc:_emscripten_glUniform4ui,kc:_emscripten_glUniform4uiv,ac:_emscripten_glUniformBlockBinding,ff:_emscripten_glUniformMatrix2fv,Qc:_emscripten_glUniformMatrix2x3fv,Oc:_emscripten_glUniformMatrix2x4fv,gf:_emscripten_glUniformMatrix3fv,Pc:_emscripten_glUniformMatrix3x2fv,Lc:_emscripten_glUniformMatrix3x4fv,hf:_emscripten_glUniformMatrix4fv,Nc:_emscripten_glUniformMatrix4x2fv,Kc:_emscripten_glUniformMatrix4x3fv,jf:_emscripten_glUseProgram,gd:_emscripten_glValidateProgram,kf:_emscripten_glVertexAttrib1f,fd:_emscripten_glVertexAttrib1fv,ed:_emscripten_glVertexAttrib2f,lf:_emscripten_glVertexAttrib2fv,dd:_emscripten_glVertexAttrib3f,mf:_emscripten_glVertexAttrib3fv,cd:_emscripten_glVertexAttrib4f,nf:_emscripten_glVertexAttrib4fv,Oe:_emscripten_glVertexAttribDivisor,Md:_emscripten_glVertexAttribDivisorANGLE,Gb:_emscripten_glVertexAttribDivisorARB,_c:_emscripten_glVertexAttribDivisorEXT,Hb:_emscripten_glVertexAttribDivisorNV,yc:_emscripten_glVertexAttribI4i,wc:_emscripten_glVertexAttribI4iv,xc:_emscripten_glVertexAttribI4ui,vc:_emscripten_glVertexAttribI4uiv,Pe:_emscripten_glVertexAttribIPointer,of:_emscripten_glVertexAttribPointer,pf:_emscripten_glViewport,te:_emscripten_glWaitSync,Za:_emscripten_request_animation_frame_loop,fb:_emscripten_resize_heap,pb:_environ_get,qb:_environ_sizes_get,Ra:_exit,aa:_fd_close,jb:_fd_pread,za:_fd_read,nb:_fd_seek,fa:_fd_write,Pa:_glGetIntegerv,ka:_glGetString,Qa:_glGetStringi,Td:invoke_dd,Ud:invoke_dddd,va:invoke_diii,Ua:invoke_fdiiii,Ta:invoke_fdiiiii,Sa:invoke_fii,wa:invoke_fiii,s:invoke_fiiidi,R:invoke_fiiif,t:invoke_fiiiidi,r:invoke_i,j:invoke_ii,pa:invoke_iif,ob:invoke_iiffi,ma:invoke_iiffiii,h:invoke_iii,Fa:invoke_iiiffii,f:invoke_iiii,l:invoke_iiiii,bb:invoke_iiiiid,y:invoke_iiiiii,x:invoke_iiiiiii,D:invoke_iiiiiiii,q:invoke_iiiiiiiii,la:invoke_iiiiiiiiii,Z:invoke_iiiiiiiiiiii,ia:invoke_iiiiiiiiiiiifiii,oa:invoke_iijj,db:invoke_j,T:invoke_ji,W:invoke_jiii,_:invoke_jiiii,H:invoke_jjji,k:invoke_v,Mf:invoke_vff,b:invoke_vi,P:invoke_vid,O:invoke_vif,u:invoke_viff,B:invoke_viffff,V:invoke_vifffff,Va:invoke_viffffff,A:invoke_viffi,da:invoke_viffiiiiiii,c:invoke_vii,Ya:invoke_viidii,N:invoke_viif,E:invoke_viiff,ya:invoke_viififii,v:invoke_viifiiifi,d:invoke_viii,ja:invoke_viiif,z:invoke_viiiffi,I:invoke_viiiffiffii,Mc:invoke_viiifi,J:invoke_viiififiiiiiiiiiiii,i:invoke_viiii,Xa:invoke_viiiidididii,ga:invoke_viiiif,Da:invoke_viiiiff,sa:invoke_viiiiffi,Aa:invoke_viiiifi,g:invoke_viiiii,Ob:invoke_viiiiif,Ea:invoke_viiiiiff,Wa:invoke_viiiiiffiii,_a:invoke_viiiiifi,m:invoke_viiiiii,p:invoke_viiiiiii,S:invoke_viiiiiiii,U:invoke_viiiiiiiii,L:invoke_viiiiiiiiii,na:invoke_viiiiiiiiiii,Y:invoke_viiiiiiiiiiiiiii,Ga:invoke_viiiiiji,$a:invoke_viiiijjiiiiff,K:invoke_viiij,w:invoke_viiijii,ca:invoke_viij,o:invoke_viiji,ea:invoke_viijiff,X:invoke_viijiiiif,qa:invoke_viijj,Q:invoke_vij,ua:invoke_vijff,ab:invoke_viji,C:invoke_vijii,ta:invoke_vijiifi,ra:invoke_vijiii,$:invoke_vijjjj,rc:invoke_vjii,ha:_llvm_eh_typeid_for,rb:_random_get};function invoke_vii(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vi(index,a1){var sp=stackSave();try{getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_ii(index,a1){var sp=stackSave();try{return getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiii(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viii(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iii(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_v(index){var sp=stackSave();try{getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_ji(index,a1){var sp=stackSave();try{return getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0);return 0n}}function invoke_viiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiij(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vij(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vff(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viij(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiji(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiff(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiif(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiji(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiffii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiff(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vid(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiiifiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vif(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viffi(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiifi(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiff(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vjii(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiffi(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viifiiifi(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiif(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiif(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiifi(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiffi(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viififii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viijiff(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijff(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viji(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiijjiiiiff(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijiifi(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiffi(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijii(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiifi(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viijj(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiififiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viijiiiif(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiffiffii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iif(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_jjji(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0);return 0n}}function invoke_iijj(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viif(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_jiii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0);return 0n}}function invoke_iiiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiffiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viff(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vifffff(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiiidi(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viidii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiidididii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiiiidi(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiffiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiijii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viffff(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viffffff(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiiif(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fdiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fdiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fii(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viffiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_dddd(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_dd(index,a1){var sp=stackSave();try{return getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vijjjj(index,a1,a2,a3,a4,a5){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_j(index){var sp=stackSave();try{return getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0);return 0n}}function invoke_iiiiid(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_jiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0);return 0n}}function invoke_fiii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_diii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_i(index){var sp=stackSave();try{return getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function callMain(args=[]){var entryFunction=_main;args.unshift(thisProgram);var argc=args.length;var argv=stackAlloc((argc+1)*4);var argv_ptr=argv;for(var arg of args){HEAPU32[argv_ptr>>2]=stringToUTF8OnStack(arg);argv_ptr+=4}HEAPU32[argv_ptr>>2]=0;try{var ret=entryFunction(argc,argv);exitJS(ret,true);return ret}catch(e){return handleException(e)}}function run(args=arguments_){if(runDependencies>0){dependenciesFulfilled=run;return}preRun();if(runDependencies>0){dependenciesFulfilled=run;return}function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();readyPromiseResolve?.(Module);Module["onRuntimeInitialized"]?.();var noInitialRun=Module["noInitialRun"]||false;if(!noInitialRun)callMain(args);postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}var wasmExports;wasmExports=await (createWasm());run();if(runtimeInitialized){moduleRtn=Module}else{moduleRtn=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject})} ;return moduleRtn}})();if(typeof exports==="object"&&typeof module==="object"){module.exports=createGridaCanvas;module.exports.default=createGridaCanvas}else if(typeof define==="function"&&define["amd"])define([],()=>createGridaCanvas); diff --git a/crates/grida-canvas-wasm/lib/bin/grida_canvas_wasm.wasm b/crates/grida-canvas-wasm/lib/bin/grida_canvas_wasm.wasm index 6554c9ba48..24628fa7d4 100755 --- a/crates/grida-canvas-wasm/lib/bin/grida_canvas_wasm.wasm +++ b/crates/grida-canvas-wasm/lib/bin/grida_canvas_wasm.wasm @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5f06878d460fab4e85c4d25682667db4927f1203aa1cbf2ab4b2b01b0ffb6522 -size 12848424 +oid sha256:63b78d73f5aa54808403a4a2794a7f28c43471d01cc4b3495777dab4eb10b6b7 +size 12841196 diff --git a/crates/grida-canvas-wasm/package.json b/crates/grida-canvas-wasm/package.json index 33715ce0ab..eea7819d0c 100644 --- a/crates/grida-canvas-wasm/package.json +++ b/crates/grida-canvas-wasm/package.json @@ -1,6 +1,6 @@ { "name": "@grida/canvas-wasm", - "version": "0.90.0-canary.8", + "version": "0.90.0-canary.9", "private": false, "description": "WASM bindings for Grida Canvas", "keywords": [ diff --git a/packages/grida-canvas-sdk-render-figma/package.json b/packages/grida-canvas-sdk-render-figma/package.json index 1989d33273..19dcf33676 100644 --- a/packages/grida-canvas-sdk-render-figma/package.json +++ b/packages/grida-canvas-sdk-render-figma/package.json @@ -62,7 +62,7 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@grida/canvas-wasm": "0.90.0-canary.8", + "@grida/canvas-wasm": "0.90.0-canary.9", "commander": "^12.1.0" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 09a25c147e..4f8da87baa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1186,8 +1186,8 @@ importers: packages/grida-canvas-sdk-render-figma: dependencies: '@grida/canvas-wasm': - specifier: 0.90.0-canary.8 - version: 0.90.0-canary.8 + specifier: 0.90.0-canary.9 + version: 0.90.0-canary.9 commander: specifier: ^12.1.0 version: 12.1.0 @@ -3382,8 +3382,8 @@ packages: '@formatjs/intl-localematcher@0.6.2': resolution: {integrity: sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA==} - '@grida/canvas-wasm@0.90.0-canary.8': - resolution: {integrity: sha512-Sd6v3Vmbogjx0iQgkMduGwTHpZaWR1XLHP1D+KSn1WnHB8S68MSV2Ta4hkhueEtsuFdLdvE71oovypo2iHwDMA==} + '@grida/canvas-wasm@0.90.0-canary.9': + resolution: {integrity: sha512-Bg/ipGH0PglCg57HW9PF1CycFsvlw1J4X4zq20aOUEekN7E5xBj7HHs8t+jTQ1hMlph4RZs1kPG1w3UXgkd/EA==} '@grida/fonts@0.0.0': resolution: {integrity: sha512-ZuuuO4nfdNC5ImLZuwSyNYGVnFDa9H2fpG1hEY0vgp0rNR16ZkOH+IRARbq7EHOlnHTrMDlwDLpBQEGsLrTStw==} @@ -18026,7 +18026,7 @@ snapshots: dependencies: tslib: 2.8.1 - '@grida/canvas-wasm@0.90.0-canary.8': {} + '@grida/canvas-wasm@0.90.0-canary.9': {} '@grida/fonts@0.0.0': {} From 3643ec33b940283ff2006a79d816dfd56f6a2b85 Mon Sep 17 00:00:00 2001 From: Universe Date: Tue, 3 Mar 2026 00:22:53 +0900 Subject: [PATCH 5/5] fix: improve vector geometry shape handling for polygons and stars - Updated `build_regular_polygon_vector_geometry` and `build_star_vector_geometry` functions to ensure they return an empty shape when fewer than 3 points are provided, enhancing robustness. - Modified the `toVectorNetwork` method to return `vn.FlattenResult` instead of `vn.VectorNetwork`, aligning with recent changes in the vector network structure. - Enhanced the flattening logic for polygons and stars to preserve corner radius information, improving the accuracy of shape representation. This update aims to enhance the handling of vector shapes and ensure proper rendering in the grida-canvas project. --- .../grida-canvas/src/shape/regular_polygon.rs | 6 ++- crates/grida-canvas/src/shape/regular_star.rs | 2 +- editor/grida-canvas/editor.i.ts | 2 +- editor/grida-canvas/editor.ts | 2 +- .../grida-canvas/reducers/methods/flatten.ts | 45 ++++++++++++------- 5 files changed, 38 insertions(+), 19 deletions(-) diff --git a/crates/grida-canvas/src/shape/regular_polygon.rs b/crates/grida-canvas/src/shape/regular_polygon.rs index 7f3bfe8477..a5a51e4909 100644 --- a/crates/grida-canvas/src/shape/regular_polygon.rs +++ b/crates/grida-canvas/src/shape/regular_polygon.rs @@ -42,8 +42,12 @@ pub fn build_regular_polygon_path(shape: &RegularPolygonShape) -> skia_safe::Pat /// Build a [`VectorGeometryShape`] from the regular polygon points, preserving the corner radius. pub fn build_regular_polygon_vector_geometry(shape: &RegularPolygonShape) -> VectorGeometryShape { + let points = build_regular_polygon_points(shape); + if points.len() < 3 { + return VectorGeometryShape::new(); + } build_simple_polygon_vector_geometry(&SimplePolygonShape { - points: build_regular_polygon_points(shape), + points, corner_radius: shape.corner_radius, }) } diff --git a/crates/grida-canvas/src/shape/regular_star.rs b/crates/grida-canvas/src/shape/regular_star.rs index df1685646d..84395684ea 100644 --- a/crates/grida-canvas/src/shape/regular_star.rs +++ b/crates/grida-canvas/src/shape/regular_star.rs @@ -70,7 +70,7 @@ pub fn build_star_path(shape: &RegularStarShape) -> skia_safe::Path { /// Build a [`VectorGeometryShape`] from the star polygon points, preserving the corner radius. pub fn build_star_vector_geometry(shape: &RegularStarShape) -> VectorGeometryShape { let points = build_star_points(shape); - if points.is_empty() { + if points.len() < 3 { return VectorGeometryShape::new(); } build_simple_polygon_vector_geometry(&SimplePolygonShape { diff --git a/editor/grida-canvas/editor.i.ts b/editor/grida-canvas/editor.i.ts index 4ac6e3b439..bf299648b6 100644 --- a/editor/grida-canvas/editor.i.ts +++ b/editor/grida-canvas/editor.i.ts @@ -2780,7 +2780,7 @@ export namespace editor.api { } export interface IDocumentVectorInterfaceActions { - toVectorNetwork(node_id: string): vn.VectorNetwork | null; + toVectorNetwork(node_id: string): vn.FlattenResult | null; } export interface IDocumentSVGInterfaceActions { diff --git a/editor/grida-canvas/editor.ts b/editor/grida-canvas/editor.ts index 86f9148acd..fbcadaae53 100644 --- a/editor/grida-canvas/editor.ts +++ b/editor/grida-canvas/editor.ts @@ -3783,7 +3783,7 @@ export class Editor // #endregion IRulerActions implementation // #region IVectorInterfaceActions implementation - toVectorNetwork(node_id: string): vn.VectorNetwork | null { + toVectorNetwork(node_id: string): vn.FlattenResult | null { if (!this.vectorProvider) { throw new Error("Vector interface provider is not bound"); } diff --git a/editor/grida-canvas/reducers/methods/flatten.ts b/editor/grida-canvas/reducers/methods/flatten.ts index f9c9dfd3dd..ef5cfe0ee2 100644 --- a/editor/grida-canvas/reducers/methods/flatten.ts +++ b/editor/grida-canvas/reducers/methods/flatten.ts @@ -140,6 +140,10 @@ function toVectorNetworkFallback( ): vn.FlattenResult | null { switch (node.type) { case "rectangle": { + // Rectangle does NOT carry corner_radius here. Native rrect uses + // conic arcs while corner_path uses quadratic Bézier — different + // curves. The Rust backend bakes rrect geometry; this fallback + // produces a sharp rect (acceptable degradation when WASM is absent). return vn.fromRect({ x: 0, y: 0, @@ -157,23 +161,34 @@ function toVectorNetworkFallback( }); } case "polygon": { - return vn.fromRegularPolygon({ - x: 0, - y: 0, - width: size.width, - height: size.height, - points: node.point_count ?? 3, - }); + // Polygon/star use corner_path PathEffect for rendering, so + // corner_radius is a rendering effect — preserve it on the result. + // (Mirrors what the Rust backend returns for these shapes.) + const cr = node.corner_radius; + return { + ...vn.fromRegularPolygon({ + x: 0, + y: 0, + width: size.width, + height: size.height, + points: node.point_count ?? 3, + }), + ...(cr && cr > 0 ? { corner_radius: cr } : {}), + }; } case "star": { - return vn.fromRegularStarPolygon({ - x: 0, - y: 0, - width: size.width, - height: size.height, - points: node.point_count ?? 5, - innerRadius: node.inner_radius ?? 0.5, - }); + const cr = node.corner_radius; + return { + ...vn.fromRegularStarPolygon({ + x: 0, + y: 0, + width: size.width, + height: size.height, + points: node.point_count ?? 5, + innerRadius: node.inner_radius ?? 0.5, + }), + ...(cr && cr > 0 ? { corner_radius: cr } : {}), + }; } case "line": { // return vn.fromLine({