From 12889d9d503a325e78823a8ebc48b54d4c2b9124 Mon Sep 17 00:00:00 2001 From: Surma Date: Wed, 9 Dec 2020 11:44:46 +0000 Subject: [PATCH] Add node version of MozJPEG encoder & decoder (#886) * Add node version of MozJPEG * Update paths for MozJPEG encoder --- cli/src/codecs.js | 68 +- .../{mozjpeg_enc => mozjpeg}/LICENSE.codec.md | 0 codecs/{mozjpeg_enc => mozjpeg}/Makefile | 14 +- codecs/mozjpeg/dec/mozjpeg_dec.cpp | 57 + codecs/mozjpeg/dec/mozjpeg_node_dec.js | 58 + codecs/mozjpeg/dec/mozjpeg_node_dec.wasm | Bin 0 -> 154068 bytes .../enc}/mozjpeg_enc.cpp | 0 .../enc}/mozjpeg_enc.d.ts | 0 codecs/mozjpeg/enc/mozjpeg_enc.js | 60 + .../enc}/mozjpeg_enc.wasm | Bin 236302 -> 236142 bytes codecs/mozjpeg/enc/mozjpeg_node_enc.js | 61 + codecs/mozjpeg/enc/mozjpeg_node_enc.wasm | Bin 0 -> 236142 bytes .../package-lock.json | 0 codecs/{mozjpeg_enc => mozjpeg}/package.json | 1 - codecs/mozjpeg_enc/README.md | 44 - codecs/mozjpeg_enc/example.html | 51 - codecs/mozjpeg_enc/mozjpeg_enc.js | 1285 ----------------- src/features/encoders/mozJPEG/shared/meta.ts | 2 +- .../encoders/mozJPEG/worker/mozjpegEncode.ts | 4 +- 19 files changed, 284 insertions(+), 1421 deletions(-) rename codecs/{mozjpeg_enc => mozjpeg}/LICENSE.codec.md (100%) rename codecs/{mozjpeg_enc => mozjpeg}/Makefile (76%) create mode 100644 codecs/mozjpeg/dec/mozjpeg_dec.cpp create mode 100644 codecs/mozjpeg/dec/mozjpeg_node_dec.js create mode 100755 codecs/mozjpeg/dec/mozjpeg_node_dec.wasm rename codecs/{mozjpeg_enc => mozjpeg/enc}/mozjpeg_enc.cpp (100%) rename codecs/{mozjpeg_enc => mozjpeg/enc}/mozjpeg_enc.d.ts (100%) create mode 100644 codecs/mozjpeg/enc/mozjpeg_enc.js rename codecs/{mozjpeg_enc => mozjpeg/enc}/mozjpeg_enc.wasm (67%) create mode 100644 codecs/mozjpeg/enc/mozjpeg_node_enc.js create mode 100755 codecs/mozjpeg/enc/mozjpeg_node_enc.wasm rename codecs/{mozjpeg_enc => mozjpeg}/package-lock.json (100%) rename codecs/{mozjpeg_enc => mozjpeg}/package.json (68%) delete mode 100644 codecs/mozjpeg_enc/README.md delete mode 100644 codecs/mozjpeg_enc/example.html delete mode 100644 codecs/mozjpeg_enc/mozjpeg_enc.js diff --git a/cli/src/codecs.js b/cli/src/codecs.js index 5fe25788..98d5bf21 100644 --- a/cli/src/codecs.js +++ b/cli/src/codecs.js @@ -2,10 +2,10 @@ import { promises as fsp } from 'fs'; import { instantiateEmscriptenWasm, pathify } from './emscripten-utils.js'; // MozJPEG -// import mozEnc from '../../codecs/mozjpeg/enc/mozjpeg_enc.js'; -// import mozEncWasm from 'asset-url:../../codecs/mozjpeg/enc/mozjpeg_enc.wasm'; -// import mozDec from '../../codecs/mozjpeg/dec/mozjpeg_dec.js'; -// import mozDecWasm from 'asset-url:../../codecs/mozjpeg/dec/mozjpeg_dec.wasm'; +import mozEnc from '../../codecs/mozjpeg/enc/mozjpeg_node_enc.js'; +import mozEncWasm from 'asset-url:../../codecs/mozjpeg/enc/mozjpeg_node_enc.wasm'; +import mozDec from '../../codecs/mozjpeg/dec/mozjpeg_node_dec.js'; +import mozDecWasm from 'asset-url:../../codecs/mozjpeg/dec/mozjpeg_node_dec.wasm'; // WebP import webpEnc from '../../codecs/webp/enc/webp_node_enc.js'; @@ -195,36 +195,36 @@ export const preprocessors = { }; export const codecs = { - // mozjpeg: { - // name: "MozJPEG", - // extension: "jpg", - // detectors: [/^\xFF\xD8\xFF/], - // dec: () => instantiateEmscriptenWasm(mozDec, mozDecWasm), - // enc: () => instantiateEmscriptenWasm(mozEnc, mozEncWasm), - // defaultEncoderOptions: { - // quality: 75, - // baseline: false, - // arithmetic: false, - // progressive: true, - // optimize_coding: true, - // smoothing: 0, - // color_space: 3 /*YCbCr*/, - // quant_table: 3, - // trellis_multipass: false, - // trellis_opt_zero: false, - // trellis_opt_table: false, - // trellis_loops: 1, - // auto_subsample: true, - // chroma_subsample: 2, - // separate_chroma_quality: false, - // chroma_quality: 75 - // }, - // autoOptimize: { - // option: "quality", - // min: 0, - // max: 100 - // } - // }, + mozjpeg: { + name: 'MozJPEG', + extension: 'jpg', + detectors: [/^\xFF\xD8\xFF/], + dec: () => instantiateEmscriptenWasm(mozDec, mozDecWasm), + enc: () => instantiateEmscriptenWasm(mozEnc, mozEncWasm), + defaultEncoderOptions: { + quality: 75, + baseline: false, + arithmetic: false, + progressive: true, + optimize_coding: true, + smoothing: 0, + color_space: 3 /*YCbCr*/, + quant_table: 3, + trellis_multipass: false, + trellis_opt_zero: false, + trellis_opt_table: false, + trellis_loops: 1, + auto_subsample: true, + chroma_subsample: 2, + separate_chroma_quality: false, + chroma_quality: 75, + }, + autoOptimize: { + option: 'quality', + min: 0, + max: 100, + }, + }, webp: { name: 'WebP', extension: 'webp', diff --git a/codecs/mozjpeg_enc/LICENSE.codec.md b/codecs/mozjpeg/LICENSE.codec.md similarity index 100% rename from codecs/mozjpeg_enc/LICENSE.codec.md rename to codecs/mozjpeg/LICENSE.codec.md diff --git a/codecs/mozjpeg_enc/Makefile b/codecs/mozjpeg/Makefile similarity index 76% rename from codecs/mozjpeg_enc/Makefile rename to codecs/mozjpeg/Makefile index 062b5dc4..65179d79 100644 --- a/codecs/mozjpeg_enc/Makefile +++ b/codecs/mozjpeg/Makefile @@ -2,14 +2,22 @@ CODEC_URL := https://github.com/mozilla/mozjpeg/archive/v3.3.1.tar.gz CODEC_DIR := node_modules/mozjpeg CODEC_OUT_RELATIVE := .libs/libjpeg.a rdswitch.o CODEC_OUT := $(addprefix $(CODEC_DIR)/, $(CODEC_OUT_RELATIVE)) -OUT_JS := mozjpeg_enc.js +ENVIRONMENT = worker + +OUT_JS := enc/mozjpeg_enc.js enc/mozjpeg_node_enc.js dec/mozjpeg_node_dec.js OUT_WASM := $(OUT_JS:.js=.wasm) .PHONY: all clean all: $(OUT_JS) -%.js: %.cpp $(CODEC_OUT) +# Define dependencies for all variations of build artifacts. +$(filter enc/%,$(OUT_JS)): enc/mozjpeg_enc.cpp +$(filter dec/%,$(OUT_JS)): dec/mozjpeg_dec.cpp + +enc/mozjpeg_node_enc.js dec/mozjpeg_node_dec.js: ENVIRONMENT = node + +%.js: $(CODEC_OUT) $(CXX) \ -I $(CODEC_DIR) \ ${CXXFLAGS} \ @@ -19,7 +27,7 @@ all: $(OUT_JS) -s ALLOW_MEMORY_GROWTH=1 \ -s MODULARIZE=1 \ -s TEXTDECODER=2 \ - -s ENVIRONMENT='worker' \ + -s ENVIRONMENT=$(ENVIRONMENT) \ -s EXPORT_ES6=1 \ -o $@ \ $+ diff --git a/codecs/mozjpeg/dec/mozjpeg_dec.cpp b/codecs/mozjpeg/dec/mozjpeg_dec.cpp new file mode 100644 index 00000000..6c08a9f9 --- /dev/null +++ b/codecs/mozjpeg/dec/mozjpeg_dec.cpp @@ -0,0 +1,57 @@ +#include +#include +#include "config.h" +#include "jpeglib.h" + +extern "C" { +#include "cdjpeg.h" +} + +using namespace emscripten; + +thread_local const val Uint8ClampedArray = val::global("Uint8ClampedArray"); +thread_local const val ImageData = val::global("ImageData"); + +val decode(std::string image_in) { + uint8_t* image_buffer = (uint8_t*)image_in.c_str(); + + jpeg_decompress_struct cinfo; + jpeg_error_mgr jerr; + // Initialize the JPEG decompression object with default error handling. + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + + jpeg_mem_src(&cinfo, image_buffer, image_in.length()); + // Read file header, set default decompression parameters + jpeg_read_header(&cinfo, TRUE); + // Force RGBA decoding, even for grayscale images + cinfo.out_color_space = JCS_EXT_RGBA; + jpeg_start_decompress(&cinfo); + + // Prepare output buffer + size_t output_size = cinfo.output_width * cinfo.output_height * 4; + std::vector output_buffer(output_size); + auto stride = cinfo.output_width * 4; + + // Process data + while (cinfo.output_scanline < cinfo.output_height) { + uint8_t* ptr = &output_buffer[stride * cinfo.output_scanline]; + jpeg_read_scanlines(&cinfo, &ptr, 1); + } + jpeg_finish_decompress(&cinfo); + + // Step 7: release JPEG compression object + + auto data = Uint8ClampedArray.new_(typed_memory_view(output_size, &output_buffer[0])); + auto js_result = ImageData.new_(data, cinfo.output_width, cinfo.output_height); + + // This is an important step since it will release a good deal of memory. + jpeg_destroy_decompress(&cinfo); + + // And we're done! + return js_result; +} + +EMSCRIPTEN_BINDINGS(my_module) { + function("decode", &decode); +} diff --git a/codecs/mozjpeg/dec/mozjpeg_node_dec.js b/codecs/mozjpeg/dec/mozjpeg_node_dec.js new file mode 100644 index 00000000..bdfe3903 --- /dev/null +++ b/codecs/mozjpeg/dec/mozjpeg_node_dec.js @@ -0,0 +1,58 @@ + +var Module = (function() { + var _scriptDir = import.meta.url; + + return ( +function(Module) { + Module = Module || {}; + + +var e;e||(e=typeof Module !== 'undefined' ? Module : {});var aa,r;e.ready=new Promise(function(a,b){aa=a;r=b});var t={},u;for(u in e)e.hasOwnProperty(u)&&(t[u]=e[u]);var ba="./this.program";function ca(a,b){throw b;}var da="",ea,fa,ha,ia;da=__dirname+"/";ea=function(a){ha||(ha=require("fs"));ia||(ia=require("path"));a=ia.normalize(a);return ha.readFileSync(a,null)};fa=function(a){a=ea(a);a.buffer||(a=new Uint8Array(a));a.buffer||v("Assertion failed: undefined");return a}; +1=g){var l=a.charCodeAt(++f);g=65536+((g&1023)<<10)|l&1023}if(127>=g){if(b>=c)break;d[b++]=g}else{if(2047>=g){if(b+1>=c)break;d[b++]=192|g>>6}else{if(65535>=g){if(b+2>=c)break;d[b++]=224|g>>12}else{if(b+3>=c)break;d[b++]=240|g>>18;d[b++]=128|g>>12&63}d[b++]=128|g>>6&63}d[b++]=128|g&63}}d[b]=0}}var oa=new TextDecoder("utf-16le"); +function pa(a,b){var c=a>>1;for(b=c+b/2;!(c>=b)&&C[c];)++c;return oa.decode(A.subarray(a,c<<1))}function qa(a,b,c){void 0===c&&(c=2147483647);if(2>c)return 0;c-=2;var d=b;c=c<2*a.length?c/2:a.length;for(var f=0;f>1]=a.charCodeAt(f),b+=2;D[b>>1]=0;return b-d}function ra(a){return 2*a.length}function sa(a,b){for(var c=0,d="";!(c>=b/4);){var f=E[a+4*c>>2];if(0==f)break;++c;65536<=f?(f-=65536,d+=String.fromCharCode(55296|f>>10,56320|f&1023)):d+=String.fromCharCode(f)}return d} +function ta(a,b,c){void 0===c&&(c=2147483647);if(4>c)return 0;var d=b;c=d+c-4;for(var f=0;f=g){var l=a.charCodeAt(++f);g=65536+((g&1023)<<10)|l&1023}E[b>>2]=g;b+=4;if(b+4>c)break}E[b>>2]=0;return b-d}function ua(a){for(var b=0,c=0;c=d&&++c;b+=4}return b}var F,G,A,D,C,E,I,va,wa; +function xa(a){F=a;e.HEAP8=G=new Int8Array(a);e.HEAP16=D=new Int16Array(a);e.HEAP32=E=new Int32Array(a);e.HEAPU8=A=new Uint8Array(a);e.HEAPU16=C=new Uint16Array(a);e.HEAPU32=I=new Uint32Array(a);e.HEAPF32=va=new Float32Array(a);e.HEAPF64=wa=new Float64Array(a)}var ya=e.INITIAL_MEMORY||16777216;e.wasmMemory?z=e.wasmMemory:z=new WebAssembly.Memory({initial:ya/65536,maximum:32768});z&&(F=z.buffer);ya=F.byteLength;xa(F);var J,za=[],Aa=[],Ba=[],Ca=[]; +function Da(){var a=e.preRun.shift();za.unshift(a)}var K=0,Ea=null,M=null;e.preloadedImages={};e.preloadedAudios={};function v(a){if(e.onAbort)e.onAbort(a);w(a);la=!0;a=new WebAssembly.RuntimeError("abort("+a+"). Build with -s ASSERTIONS=1 for more info.");r(a);throw a;}function Fa(){var a=N;return String.prototype.startsWith?a.startsWith("data:application/octet-stream;base64,"):0===a.indexOf("data:application/octet-stream;base64,")}var N="mozjpeg_node_dec.wasm"; +if(!Fa()){var Ga=N;N=e.locateFile?e.locateFile(Ga,da):da+Ga}function Ha(){try{if(y)return new Uint8Array(y);if(fa)return fa(N);throw"both async and sync fetching of the wasm failed";}catch(a){v(a)}}function O(a){for(;0=b?"_"+a:a} +function La(a,b){a=Ka(a);return(new Function("body","return function "+a+'() {\n "use strict"; return body.apply(this, arguments);\n};\n'))(b)}function Ma(a){var b=Error,c=La(a,function(d){this.name=a;this.message=d;d=Error(d).stack;void 0!==d&&(this.stack=this.toString()+"\n"+d.replace(/^Error(:[^\n]*)?\n/,""))});c.prototype=Object.create(b.prototype);c.prototype.constructor=c;c.prototype.toString=function(){return void 0===this.message?this.name:this.name+": "+this.message};return c} +var Na=void 0;function T(a){throw new Na(a);}var Oa=void 0;function Pa(a,b){function c(h){h=b(h);if(h.length!==d.length)throw new Oa("Mismatched type converter count");for(var k=0;k>2])}function Va(a){if(null===a)return"null";var b=typeof a;return"object"===b||"array"===b||"function"===b?a.toString():""+a} +function Wa(a,b){switch(b){case 2:return function(c){return this.fromWireType(va[c>>2])};case 3:return function(c){return this.fromWireType(wa[c>>3])};default:throw new TypeError("Unknown float type: "+a);}}function Xa(a){var b=Function;if(!(b instanceof Function))throw new TypeError("new_ called with constructor type "+typeof b+" which is not a function");var c=La(b.name||"unknownFunctionName",function(){});c.prototype=b.prototype;c=new c;a=b.apply(c,a);return a instanceof Object?a:c} +function Ya(a){for(;a.length;){var b=a.pop();a.pop()(b)}}function Za(a,b){var c=e;if(void 0===c[a].G){var d=c[a];c[a]=function(){c[a].G.hasOwnProperty(arguments.length)||T("Function '"+b+"' called with an invalid number of arguments ("+arguments.length+") - expects one of ("+c[a].G+")!");return c[a].G[arguments.length].apply(this,arguments)};c[a].G=[];c[a].G[d.K]=d}} +function $a(a,b,c){e.hasOwnProperty(a)?((void 0===c||void 0!==e[a].G&&void 0!==e[a].G[c])&&T("Cannot register public name '"+a+"' twice"),Za(a,a),e.hasOwnProperty(c)&&T("Cannot register multiple overloads of a function with the same number of arguments ("+c+")!"),e[a].G[c]=b):(e[a]=b,void 0!==c&&(e[a].O=c))}function ab(a,b){for(var c=[],d=0;d>2)+d]);return c} +function bb(a,b){0<=a.indexOf("j")||v("Assertion failed: getDynCaller should only be called with i64 sigs");var c=[];return function(){c.length=arguments.length;for(var d=0;d>1]}:function(d){return C[d>>1]};case 2:return c?function(d){return E[d>>2]}:function(d){return I[d>>2]};default:throw new TypeError("Unknown integer type: "+a);}}var ib={};function jb(){return"object"===typeof globalThis?globalThis:Function("return this")()}function kb(a,b){var c=R[a];void 0===c&&T(b+" has unknown type "+eb(a));return c}var lb={},mb={}; +function nb(){if(!ob){var a={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:("object"===typeof navigator&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8",_:ba||"./this.program"},b;for(b in mb)a[b]=mb[b];var c=[];for(b in a)c.push(b+"="+a[b]);ob=c}return ob}for(var ob,pb=[null,[],[]],qb=Array(256),Y=0;256>Y;++Y)qb[Y]=String.fromCharCode(Y);Ja=qb;Na=e.BindingError=Ma("BindingError");Oa=e.InternalError=Ma("InternalError"); +e.count_emval_handles=function(){for(var a=0,b=5;b>g])},H:null})},x:function(a,b){b=P(b);U(a,{name:b,fromWireType:function(c){var d=V[c].value;Ra(c);return d},toWireType:function(c,d){return W(d)},argPackAdvance:8, +readValueFromPointer:Sa,H:null})},n:function(a,b,c){c=Ia(c);b=P(b);U(a,{name:b,fromWireType:function(d){return d},toWireType:function(d,f){if("number"!==typeof f&&"boolean"!==typeof f)throw new TypeError('Cannot convert "'+Va(f)+'" to '+this.name);return f},argPackAdvance:8,readValueFromPointer:Wa(b,c),H:null})},q:function(a,b,c,d,f,g){var l=ab(b,c);a=P(a);f=cb(d,f);$a(a,function(){gb("Cannot call "+a+" due to unbound types",l)},b-1);Pa(l,function(h){var k=[h[0],null].concat(h.slice(1)),m=h=a,n=f, +p=k.length;2>p&&T("argTypes array size mismatch! Must at least get return value and 'this' types!");for(var x=null!==k[1]&&!1,B=!1,q=1;q>>h}}var k=-1!=b.indexOf("unsigned");U(a,{name:b,fromWireType:g,toWireType:function(m,n){if("number"!==typeof n&&"boolean"!==typeof n)throw new TypeError('Cannot convert "'+Va(n)+'" to '+this.name);if(nf)throw new TypeError('Passing a number "'+Va(n)+'" from JS side to C/C++ side to an argument of type "'+b+'", which is outside the valid range ['+d+", "+f+"]!");return k?n>>>0:n|0},argPackAdvance:8,readValueFromPointer:hb(b,l,0!==d),H:null})}, +b:function(a,b,c){function d(g){g>>=2;var l=I;return new f(F,l[g+1],l[g])}var f=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array][b];c=P(c);U(a,{name:c,fromWireType:d,argPackAdvance:8,readValueFromPointer:d},{M:!0})},i:function(a,b){b=P(b);var c="std::string"===b;U(a,{name:b,fromWireType:function(d){var f=I[d>>2];if(c)for(var g=d+4,l=0;l<=f;++l){var h=d+4+l;if(l==f||0==A[h]){if(g){for(var k=g+(h-g),m=g;!(m>=k)&&A[m];)++m;g=ma.decode(A.subarray(g,m))}else g= +"";if(void 0===n)var n=g;else n+=String.fromCharCode(0),n+=g;g=h+1}}else{n=Array(f);for(l=0;l=p&&(p=65536+((p&1023)<< +10)|f.charCodeAt(++n)&1023);127>=p?++m:m=2047>=p?m+2:65535>=p?m+3:m+4}return m}:function(){return f.length})(),h=sb(4+l+1);I[h>>2]=l;if(c&&g)na(f,h+4,l+1);else if(g)for(g=0;g>2],n=l(),p,x=k+4,B=0;B<=m;++B){var q=k+4+B*b;if(B==m||0==n[q>>h])x=d(x,q-x),void 0===p?p=x:(p+=String.fromCharCode(0),p+=x),x=q+b}X(k);return p},toWireType:function(k,m){"string"!==typeof m&&T("Cannot pass non-string to C++ string type "+c);var n=g(m),p=sb(4+n+b);I[p>>2]=n>>h;f(m,p+4,n+b);null!==k&&k.push(X,p);return p},argPackAdvance:8,readValueFromPointer:Sa,H:function(k){X(k)}})}, +p:function(a,b){b=P(b);U(a,{N:!0,name:b,argPackAdvance:0,fromWireType:function(){},toWireType:function(){}})},e:Ra,f:function(a){if(0===a)return W(jb());var b=ib[a];a=void 0===b?P(a):b;return W(jb()[a])},j:function(a){4>> 2) + "+ +g+'], "parameter '+g+'");\nvar arg'+g+" = argType"+g+".readValueFromPointer(args);\nargs += argType"+g+"['argPackAdvance'];\n";f=(new Function("requireRegisteredType","Module","__emval_register",l+("var obj = new constructor("+f+");\nreturn __emval_register(obj);\n}\n")))(kb,e,W);lb[b]=f}return f(a,c,d)},l:function(){v()},t:function(a,b,c){A.copyWithin(a,b,b+c)},d:function(a){a>>>=0;var b=A.length;if(2147483648=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);d=Math.max(16777216, +a,d);0>>16);xa(z.buffer);var f=1;break a}catch(g){}f=void 0}if(f)return!0}return!1},u:function(a,b){var c=0;nb().forEach(function(d,f){var g=b+c;f=E[a+4*f>>2]=g;for(g=0;g>0]=d.charCodeAt(g);G[f>>0]=0;c+=d.length+1});return 0},v:function(a,b){var c=nb();E[a>>2]=c.length;var d=0;c.forEach(function(f){d+=f.length+1});E[b>>2]=d;return 0},y:function(a){if(!noExitRuntime){if(e.onExit)e.onExit(a);la= +!0}ca(a,new ja(a))},w:function(){return 0},r:function(){},m:function(a,b,c,d){for(var f=0,g=0;g>2],h=E[b+(8*g+4)>>2],k=0;k>2]=f;return 0},a:z,s:function(){}}; +(function(){function a(f){e.asm=f.exports;J=e.asm.z;K--;e.monitorRunDependencies&&e.monitorRunDependencies(K);0==K&&(null!==Ea&&(clearInterval(Ea),Ea=null),M&&(f=M,M=null,f()))}function b(f){a(f.instance)}function c(f){return Promise.resolve().then(Ha).then(function(g){return WebAssembly.instantiate(g,d)}).then(f,function(g){w("failed to asynchronously prepare wasm: "+g);v(g)})}var d={a:tb};K++;e.monitorRunDependencies&&e.monitorRunDependencies(K);if(e.instantiateWasm)try{return e.instantiateWasm(d, +a)}catch(f){return w("Module.instantiateWasm callback failed with error: "+f),!1}(function(){return y||"function"!==typeof WebAssembly.instantiateStreaming||Fa()||"function"!==typeof fetch?c(b):fetch(N,{credentials:"same-origin"}).then(function(f){return WebAssembly.instantiateStreaming(f,d).then(b,function(g){w("wasm streaming compile failed: "+g);w("falling back to ArrayBuffer instantiation");return c(b)})})})().catch(r);return{}})(); +var rb=e.___wasm_call_ctors=function(){return(rb=e.___wasm_call_ctors=e.asm.A).apply(null,arguments)},sb=e._malloc=function(){return(sb=e._malloc=e.asm.B).apply(null,arguments)},X=e._free=function(){return(X=e._free=e.asm.C).apply(null,arguments)},fb=e.___getTypeName=function(){return(fb=e.___getTypeName=e.asm.D).apply(null,arguments)};e.___embind_register_native_and_builtin_types=function(){return(e.___embind_register_native_and_builtin_types=e.asm.E).apply(null,arguments)}; +e.dynCall_jiji=function(){return(e.dynCall_jiji=e.asm.F).apply(null,arguments)};var Z;function ja(a){this.name="ExitStatus";this.message="Program terminated with exit("+a+")";this.status=a}M=function ub(){Z||vb();Z||(M=ub)}; +function vb(){function a(){if(!Z&&(Z=!0,e.calledRun=!0,!la)){O(Aa);O(Ba);aa(e);if(e.onRuntimeInitialized)e.onRuntimeInitialized();if(e.postRun)for("function"==typeof e.postRun&&(e.postRun=[e.postRun]);e.postRun.length;){var b=e.postRun.shift();Ca.unshift(b)}O(Ca)}}if(!(08qiE>OuMvcoDddyjQnPi%R^!p$1F{U`QZ-5FmW`XCQzn zN!0Ie?S0NY_s$(lvYnQIZ0Vk}&;GOa+Uwt5d+oiWZ+PolTogs_mt6lYw-)i&t=*NZ zt?4ITBcaK&ejEOWG`>V-ddM8z)wXO^M$%h8MLCc2Cn^*8)F6c_BOc@9zCnJDt6lQN z`X?ca9`DgV$9O;PK{|e1O;Vq#QN8>E^Kk*Ie@VDU3CHa5Sp05xx%&q952Gpm{YO!Q zf8P{2{{2S!{0;6O+w+^FnCH7K&o@O0&jb6q8l^n%kJ|kE7JL3Dmgk$To&%QiVASR7 zp{T>ZZ?#f~t+uyCEmDryzi+ozj#~b2u{_@pyY+Z|Jx<;ce_I^8nKYhr@k|n3a@j)M zh?eG(sSdx*D-#!YrfCFiH@cgm?{!n_v5N|qzRNx6 zitlv)+R_=rhoJgci#06 z{1$ z#}CBo4AZ^weesF-Wc(NI&)w(TXWeJqU%UV2{>nY${?h%4d)obx`$P8!?)TmAxlg&@ zb-&|&+kMjgmizzRQ|=S)H{8eF$J|?Ye#^JVf9C$!{i=J?eYg7_`ue}Sf9dXXC)`PQ zzq{8RUtZg}^8xp*|MXYfFT1nuKe+e1|K$Fod#~HQbLYQtKjePU{U2`k|LJyrpL@4E z?RNhw_XF-d4pCmSDbSPi+k@o+1a1FJuwYran@KZj@kFP zP$f!k_|g>E6L-kOPlGCthR<G_{7#ST=(_E%4LS5I#$tD;Zys?_cMW%Y)nY_7@J&-j|_M6n#81!AToVl!dZL;Wpdj6;5e<)F8WTMf#22^t8 zZ8K4tW>NZxixWdSXpgQ+4&;q}uWi`l(X8>cGmbpHN1VptR(mO;J@MVe+8pUS;|>)@ z@mjn*EUdCS<3>O3QnaBekFKoUe=KhRhd$)->ifT1H92Jf$L}4a)R;LHwCrSzR|_|I z|FLV6qhx^s^62V_A-UP|Bv3<|CFu{QadU0z_=}_Bsc1EC?tor|5x0_^I@zDk8Y?e* zAWK%}d70tmoc+1sL_WJRr}Qr)eNOG)zp`HbSv%36rjjaaN>%+{HcKV_E!465)O(9_ z&`G~dkJrdqCgf89S$y`KdtGB0x@zm~bLZSGGj1Cl-B;B~&C!Xx8(KWe+Z|c`?e$B- zeH^}LC;QXgn6B=t;P(}j8GHrxH(x=cRza5Zohor74c&iopBl;%{f6960ZxBXtcjk;1{BTvWFE2^Jk6+QtTC4q5nzgENxZ#a6 z(Kc#cUZq2`_IGw)-l5`7sJK&Ayf=?UF;u*qS7cMCt=N-CE9G%C|J@f#1f-ynFmuK9kMfaVDF|w%FJ93B!EnB>Csd{PSd+%VzF4b1a(! z3-iZwqzGV<^>gQF2nk>n^{k>8CJ+(x!I9jvf@)_@6?C)NZFfRz^vMqO< z5&GuDJjZ~AhX-m+HnQ|M^Qk8kvA^K&EQB>#HC))lx}Gjj&HDw#z$NJDVD0t-+wUcO41Q5@&uT z^fHNXC23aN1F+Ezr%nPMRMcMTr*L-mfOR7QAgC7ry2n6fr*LmQlXoRd+$r8(bLb4> zf^Mmj#42fI)F7eOeW35+<4|ODJIwE(wY*)dyRU+;0xLC(-6G(aJm(@H6~Q8m=_@p8 zFFpUg-TUIKY036D#;pD(VwCUfND^E4rH0$Z$fouQ!`GWrWp#h=o~&I;aAM>?N5QEHjkY_-eG9S zh6n`aY-$gE&DtrIAnrt|^j6rUJ0DEYrPf`#lPATWqhuFA;#$Us#yohnOofb&w749A zTyZ&C@^GK>7{7bsEi zTd{-yfS0&%dzI5`@W`iEul*Qo!ua4uMwt`Z)pO88uf7VTV4xk8Z9!FunNP*pNEQp+ zQ!EeiCWeQvg09M}mU+c)Nef_QaWg z+Oa3z;h%QyiFf*^U3=nP{%QA~c(;GLW>0*Lf4Xi@e4T%~eouTo9a~NE`$z8OzIqGY|CR6-g+8D|?&qJCiq%d1T9y zRWI=n3COn^d&jVM`i?Jm-8Bra-fG_65yg@}ti5f>sYFzSdKBkmU{|&B&mj>UuLFdh=&x`}>CTG#pYp(VUI#T}md49P zoJA@Hj#dv*Dmr{Hk9dn#4u{u=k8Dj!|2@| zDdMqrSG|XxH-0aw4|UT!5tEo$QjYq>%ZR(c$o|Jh zLbYXWiU`@(D5x(!?h!xzS`a@Cey2Y#_$}hY#i`%$R3-5$V#Gj%{56O26xPe7ZPb+o zo^0Y%<&>eI&fSu`B}xH)#zT^MUXqCng86yf3{|44Pzi}1x_N^MOdw4qFsjTKqzSuB z6Gq0ZJ0lsg0CkG?4HgOrsu_`f51Ats=}hYbea9 z_=z<{Fuy63OW*sg67L|1WV@i&)qO6dPdo>0(?=dKXs+0h_Yc0 z2x@(O&QhRlP&{`;B6gCqD>6mZ%w2uCbQ6rk)p48-3>BCfkEh1L49Eh7y`MYe>RD zC?ZiTI+3X6*d>XQFixUDno6{Ev1)3RCwB2PCld8UI3&>;Ez`UwV6ng`iB6}b>_uE* zu9Pw-f;`Nyj*Fg>B{L8zkx3DV1LZ2|gQN+fjNu+w4#qafJ!u7mj`4yjum{ma5Q{1z zx~_Bq*f-HB#`&ZdOmOyXG|!uueAOI9#naTqU*l7OBETddDo{$nJFG713#^x6A;xRP z!=F%Ds(r*B1m_1o5v{CUOaDH=!}@7i>kYk2Eg9<&y6bXsxBKVq_o5aQR(bj2FC&Cpq@xjKqqkQof= zvTHHJ+hQKmpDrHy1n?(Dl&EFON>GaA8hI0}-!>zDGtv$aIz*;U~+bQN>m9DT2wX)}7!Z8MaEyNhHXD-|;qFg0plse0+v5;32!Un`c^Gv@KPyW+1$Rq&e()+0+z9H}eQ<2zLq%p&qJ+5;bJp+`zM^ z-XrR*SyRo@Jk0?%fEoo$Gz!?$S=(@`q$m(ljvmk2s{u`D`GA{F36TV$?|jobFF&4C z`(AZiw7@^o=N<_X6(C{8h2m+yHhQfgVn884$S2umXoM5PPP^MoBP2ePJ7zFZKj~7Y z8hy1=P{RDJOiCP(z{?s6TD75Y6^2}GD46n?jwov~>J@({0vi2ERbq!#O&+y=dmfqe2w1P2N)(~PEnB594%{(``?230{s@sH= zJc!w-$TT%ELE0|vG&=+&6zzio2&v1{QtnnwtgC~W_}%;EQCO8^MFudvYZRXbqO*n| z0Fgft0oKI`*C^WDjq;jzf@<700~JxF&Eja*46QcHR+&?Xs03RO`x*uChZRFQHPHn# zq^Wvh`w(+nVpy}l3bR=(e*rQF0{3I(htU5E0;!vELj#wiCFf|>8B628V!lg&Z_J+R9D7StObWR zH5U;kaXE}&3?v$|Wb*lm6<{SnovRR<*cXx}<}cmWoNu%cP`3tN+N!u{SuUkQh5wg|Z}SJB)A(vn@n_|ev)JXQ3O z$8O%#m|$m#hcus+nIM}TvQj}br!S}yGR9+LKL}2iPW1+3HL0C}h7dBxY`C74x$yvl z6-N(NDck{_3mxbb47d`M?eJHazF4(}2>}5$Bbu2&1!JE6IX@ewf9;}IEM#qJ&XSv! z1|h#qYntM6)~BphI%Zw5r6ZCJ5evDK1!*4^e2?`3=PPO~(ho2io*Kn*=HJ*F<*4&H z3?M0fl#mfN*$>mo2m{Cu2xI0lCK9fiRKoK%sg!^>hDdF;1+B?J#7|c(`5%b9gPqUp z1x_8Ey-;g?_EOGOhO?KLnJmbz&0ZQddr|w$0xdm#LH1K3f2{ejjtYd{{HgukuP3&hj=y>Qy6Pzs31kg`QqhoQ5t;)z zQ335@DpACS9Z#H10+95^n!=d#7QH7-Xc&PnN;3h@*objT0b-Ja>A-U*P54lx8DxTy zCbqQ@-w z&Dcnjx*<&*1DbTx;zrVpZ<4|4NmGz0*JRS9W=PXS$s#`iQT&K`RW&AxCs<<;sU&(J zDmDRa?2bj*(TGP_lw}dC$b_+$9;}EpBGJqn7H62jQ9FjRF#(UyaR!H+i7=5$n-i{z zm$NA^rI`Y6&ntwR`zDji4vd)no_Hxu7mjDq+YjcryUk*mG7&u`5#5l8_L)sYBWi^M zKe?tRq^|to2on?0q??b5cYRnWKLAr)%t=`xFf=hm^cva2BgT~yEM7S?)`*Sp8Hx@3 zAp_@s9E)K2ibdeY;Cs4Y-az@(r8f**`ks=~_p~W*1dgmmOe_NCSOApEx6U0MQ$|K) z=i!c4vYfRl!3}q)bp$u#Q*ws_Ixwk%;BHA^VNPw%9gI-mj`NZ_oM+tOYE+4O-$0e} zoQqE-0vmxUr#)3}q)9Uyd{(1L7Q#f6W;QU#hI|4|lBYBqa9&Y!Nt59M|#}vhsbIeJy2uldY_ox#{N8I4qMu0#r$-F%3K9QZqbu zs|*1UsvKtEv77eZ=U$us!c^Q?Ybe&`=@9EuMzp{!5n(GvwQgnYSe~w|y*?|0SnO*) zl|eqN?E257@#iNf_r_|eSZ{tQI0<#U0jC1polxqIu~HVyvoD(}m*}bLj*+(wQ7xDN zH~=uAh-|4Z*WWSnwjq{9>%vfMy&(%g2@NZL1q35#@8@SEu7_-djr1EUU^(N#H$KuD zS(uAcyG6z%teCUv4(C$c2{@MuPuRjVd^*iyIHXM@k z53fFTvWy96oaFPAlBbny-AeE8cZq~ZNXT9x9f0BcEC z$On=5(2#}?4SCu^LyohO=p@ltL{211AssFIteAWjN4et4x8cXm;DJ zU_DHLzC=)TfAItB4v&TaJ4Pw_%a0zkup&l_tWjEPUrLwAlpmULZ8`l+OR)|n2S>y@ zz0KV5E#%Rl-{d=!KlzcgK22}bQRTp6mkfP8-ifE#N9p5`zo48~P@sb%vgrl?T(Dz8 zgzD{HMpGuT1g0Dlif=JE@M_c?6XuAQPQfvO-13UdW*=q>3>^~<`ZIJ)@CH?hEiqeS zR{t8z(@MvLvN{l^*`{0syvv<{F5_3jTY|Ekp(z~`Sfr7R3xl5WX7#oz z#{@u=|FttF=h4Bz!qDOa11zi8I#ya3a>@G-78F8$V+YhLUBFS4;AOPMBEhR^M{rP> zAr@@m#Cw<&R-`3cviaipAW=L2MTJgmb?wA1d=rZDFX?H4zZ!b z2&FZW8|pQKrE-wbgr`G`&+>E_D)-HwhZu*hFHx8TnD>%BFJcrb44&sej8I&S7@L}c zmBc99Ta!{|tYU!)#7O!=4lzQzLR3kNvJ0YMw^lJ@;AIpIjb`e9B}qD%;soS{CsD-4mS z8KE`tz6UE3u*)<;D<}L#Dq6IVpk^UP?k?}+lR_~k7Q;cqmR~C^Y5Gkr!A+3Ggvv@C z>!*R^x(x0`7?zLjxb_2_Vqg^rtO97ljM8Oh>=Y$R1H*8kn5ul>B+4=UD|XGSB|#m> zJ4_k>C#v*zEB_LBTNyV;kCo|vd@fRqc4OuG2h6BxoT}`Z>yH_d%J*l^MPDZ|>T@<% zs+?xvSXRZ3`>8b*0_1z&EX%9`*zbKaKT_+xJC;zqUnV0bR?sUx*ilR1ozE~LW(i;` zGWpC}LG{zJDzHCmC+IUw;4Oh0%n%_f0jvl3(F9BjKGFlp>icu7mZKzt|My~xNUMF# z62ENbc?0guyVHM@U`beZfm7W3uHXN7VzHKt>&pL2gHOXya?6MU_9i&^JJ5$?b@2CLw2ub%5UJEfX-M z%SXI!Ax*KOyn2h<%rpgiWaCS37nol^4tSK1yIDpqjS|>Hse6m1{g_l`E=rnI}e?XlK%qbM8#$-i#%e9V-4L z8WcAiJo7-=`C#)qZ}a2C!@}>Rmr?TSC@M0u*wjqa`!q9x- z!-qm;tb?Al7>{~5$f%EViTRc(yJ7R% z6v<@ms=4sH17eQ+4nd0XLhI6bQYOcYh{%0gz0RIsBVbP@nMY-x6Pc((N}0Y*fE3xEQ82= zp9ON!9bWkn3J(Pdd;sz^*C+u0982Dcw#I-wVth*-f{W?I`RnivV{8i-tfBH_^9-{s zHISCZMuu0$M3s<~r%DP4Bygrx_fgf%U(i4J73uilcfM zi^aDQ=;%qdQ`mdf#>)T&BWZ*JAxYR^cxi<+Ml{qp*af5=ZAh|K30AJ)ohsp#{bx2O z;nRfVsUk%WXmb>1Pb!ViN{i$dJ5XR2!BVWrBFD|BId6oSb-R7V-iZ&RV7#9U)>W_v z#aNu+0V?og=8NnTD)}ZWsa6W!q99AVtkGDTG849KEPjVCo{SZztl~bXxG|~GJAEnb z#@W~?KJv2B=Hy1d-WQkQSuakb3%=3Tq(<-Zr4;;IFXem6>UG(u_l9pk)SG;9g_+fh z(S@yoF^Bgbb3;w2YjjNu~NR#ox?`c z$&D&Vf&Q@bU<76w-Q^qYPHL2BHI>4sA1UP<-92n{W^$v)eDRsF;xu}VZ*+E2qwCHW zn;k3WTfJ`B>fGd3PlobyW94b~df#ksQnRN*vEHCg3cgWhb*v8DuqVDzEGq8Y6Tj0T zCp7KUWN&@Tp7>ox)FX{Z_pNPi2eF*I; zO6r2!WkZC-*=V~=OVut|dKVw2=-F78^Jy$uO=8)$DS=cr7v1yZsh7}65yRTLR(|{QC||ElYJ6C?&X^d!>EMas+jeXB`u_>-)}hEoVA?VA zwsYid*T~!Mk+*9`-mV*YyWaZwndlIjvo?fvQcWh2Oyk)}rgeBD$@rjsQLwi28{w8yE%9yX78nI69$66&CBX6CNH@Rh}3Yf2!UlEZ* zG1i>aqn7nZ5h)TUF+GyCQ%O)lP0Aj1N^#P)9dekvm^r_R?@C_T?_o$XuLBzcN z>Zo-Kf=p%~QnynIR;*71oYa6I+JIw1@i9yd$5SOlvjN8)K@=pdPYeAwJ=<1mv06i_ zmaSo}sx?y(wSLPwRU6i|9@QhX>veUsS1r_)sIGV!Q{J{&D5_X`%up$ld)_v8*$jet zRWP=zd7&y{9+OI^Y36r&T28hfcFrBUF|t2T-_Undk09@01c$_@)|e8pmN93JpWlO<(db6;s?`H({9#0Hw%3}X*P$$Q44lm{dD|H>v3i+i~ZSn znU0X!$nlb5P3KecRJO7%AVGGi{m6_bLd10XEc(wYa}K*{88vWP2caDVk!Tj!G(0z6 z<`k^ubYOsmPvU^GIU;D)VK{!w=fE&b(!H7SPdw2{n=|w1C}~8|(mF#5uzcJU#I~v5 zS%~~1KqS7bp$N~50&yzq+zN;~jYknFMk=)KL1fw>5Xr+tcnpg~Qb30tLmcP91VAC> z%`iyhac3O7nG%CD9)nXGF=$9F8N|S&poK=Q+!b>$jxhXr1Hl>Ts6^*nf-vLN|4 zeKT|$=+Cg%$_#rUTE^%v5tWXRBrp-3Wb_BcZVF!7ZyNSCf+v6M1n}^REL=2rOxA@x zOm#VRiv>~@mJEa*hKgJoF%3vRwQ;H>Mwj6cZeS22s1)gyCH)3TIF67R zMRfCkt|3M=On|Qpa_cg7VYC=P1eB8S7>WEl8bF*SN@B^;h>58QCPn&=@=%yX3zDT~ z$vEGhch>PKHH_GIx zh?`lY$~H8SSQ9uzRBytZfc^yu*iaMdgphJ^b;ye&XFr;-NiA~L1gE3{Yi`9wa5@4k zeko~~;I5-Lw$3L1SdIfySzE=Y%@e3J`SBFzZ=O36%pYjDumx!?w2NYVHYTiH?%r7D0@p5CmAN7><7xfU;n@kRr-n0JQsB&1 z3MFyiuIt4+XzEzK#)k3kOz>|>=B>5r@`?n)th;YMp7X(hPY~|hq7v4#HP)@-+ChISKi3WVa|L4^FDJ`j zqFY3gZY<#Pr=4|IG1P2>#;f5Y9GqR*bez>S=y!2zvdWxKtE~Son}*eM<}9j;%EYBC z`Dyf=?bsvbB|;o;u)o98;oohMo#lH$W@{026^{q6*J2bvc_A66`KJ{k{*Dp7C-3|_nn9L8X zqa8UNgHYQNa3C%yc9`UM`~v5-%tUlRU?Y%_2)ARmrH5pXs^N|=pJ|J7lP#*Xf|7i| z*D1aj((oI_Rl-dGRdEM!W^wj7z0jP_!!Dq$f9Nu}r&zy7yrg02v2)*JfnZEP_d`v` zdiM7LCXt9YD<(VO!bQ3&p8 z#-2qV@I6I;7_F%IQX!Zp=Q}3~039*SmE*w2q#TE_&MD_ekFYyg3SzLzu7M8?ow^3( zQ%WA~kM#v3HT1=Rwh{6KZ{SmF2|3HEjA6S!Pail3EZ@S=bEeCn_Uyk=x0X9i37YtDo&+D|%BqOgRg$h_rUVxqy zIqY#Dhb8?9c!aC|^rP6PAC35g0PQTLj5VH>z_>IE1Epugw+LkK2~xmSp-f?0`-Z?^9h`n3D9Mn9-@I3xUw?y|l0$cIGa} z#I>%yMhj4ov0{xB7$cJI3{u)=`=Hk<#+Er}B0(B_Z49zbZ!a=3+MA~c491I1^0%36 zhTS>e4`^77Asond?HhNdGqT_W2_Fp-ctVbkZKk!RCDnB5QmuXkJ&{K<{3>}Db28eP zmMY~;S?Y8txL^RzMsMxC)M}>%#?I-$4d2Du*BwAkS8jX8h9%;3YQ{8k2`k9h(eW#jZAx&@_AushX0zppsIvf zpuz`2To&iafNQy^I5bDdQNlc8D6&j!YO+jOnaMB+?Mes;ciJO^z0pbE^-_1a1&pPu zd54sQ&KGxamJZId{-s$=NA!vXc&L9F{qkSYQHT22c{^k8%Gn+->*XYJ+RjxJ<1}zT zLeQ5E3imcMX0A9y?=G{~OTYnNd)cDBUarEYoQ3T5ImzA5N3%E9 zZ`mW7Et!~anxBeUXFew|$0wC|l^E#N{cH@I+AoR2>msiNPwy9is8@5BJ$nTzQL8}p zg$jV>@~jzFqBnsdKu|VGH#g5%!j|@@h)`e$%vyGt6xFb=?aVqlKE3A1+GchcfVH#s zeyx4$JskoHWm!+3t+=w+i>ta4YDP=FoY?kQOPl2>tAo7pS<$mg>DjgoJsY3(b7XHb zyR-(H-luDz!Sou#(6fofmA&j)SzXz)t+k$w7anWLdNv`Cpi^}?K`PCXp3PSXF@aPk1#DZ*P2BsrOw^Fc=3awXw`@w=H z|5EJ16yq5-qm3jyJ)ZEX@r0+w6P_GTcw#)^vGIhn;|Y(9Cp5(0Iaw z;|Zt66V}HQo?(aNC_cs$J~f{3)Of;^;|WiUCp$3>5KTkRC!t34CQ-S4-I!okswPsX^!fA=P*~O< z2jho=ovI){B0<1P;KqVFf^Ti7aqhu0TlElDSVP>eN%$;GTI9u+P-mu4 zur;Zm`mQon-?vwNR~RY9aP@3#PsJwpeI8WK>@S*!g@FZ)grOm;(2)6RG0!JgJ46Fx zQlVi-)teo@JU0Et@-;LNw`FM9Sry#r3u4M|Ea=fNGepC#3Jtq_F zLj!wahiKScp<%bLw!2xiLp0Q>;hL&9*ZA^ytu}&HLqkao*Hs0t^95%o72H4#*H>t` z-WTHXDtMr#yD>Qt)FLv2x#WtdWt944jP?Cbl+PkVc@A7pL*S&El1hl3#c>89Bt+Oq47FV4*YdAYxl_#oNAn+R>}XZ& zs4sSf|Ed#pm`Ux7kNFG)xgYZxu1wMYENikji!$!Z%aF-w#pX9=PfWX{f+x5MupZin zGi@`^EG%T3W@+29t(v9bh2rE~jt`G81vpCr56LkOXVmduI-D_2*!rya0Ih$<_N3VL z#GVvH+OQ{<(u$@%5tUZ7?1|8gg8e3x-GVu#AZQL251uHN&1{jH{q|w)*9~yC;!|(P zg|8Rf>w1apMbQPk01RJnfZ<=GKfbJ{j8$1JK~!b6lKmS+?7)mz}AXWo>8J?p#%t{RL&&UcKymy{sJn70j9ydzd*Jq%6BoFMCP7 z?4|XxmsMqnX)DWWIlb!d<@K_niK^YDs_Ygk%S!Xr(e_Z*US1T++RGK8ti4c4{IAaZ6!m?i)WqB zy5cFzH%&ekQ2BHAKb{Q*?#`#}CbCn;;M8!Jwm!F6aH1IQOtm?o*q!-QRSXYcIO=Dr z>PguS$Isw(pOic;8IG$F@8fa0Hgyk^1Wt^)Cr@p|Dc&{S!}&Xa!e;J~j_&jw&FCo3 z>9o3_Nr;}V-ctP64c_RI-%>@Bq6oa6X}mnrEWP|{Iz8=I*^sclbyh?e_3{>`A)>GI z?eF%8t~$i+6-Hzx( zIgQZ*w$X|6nib=&TW}%+XYShgnKsY&(gn6lN#^ zdm{by#7$W^$Kwhs0(GYA0iwD_TDCsrS|)J@jU(K|&tA;mblcIqt<88y6xYN(B1ZLOmB zlOkfhJ_^CKo+Yh^;DG)dmL@*u_Om{fO}!;I{?RHlE?ETLetA)W2`Zr@=6`jz{=